static void _muc_user_handler(xmpp_stanza_t *const stanza) { inp_nonblocking(TRUE); const char *type = xmpp_stanza_get_type(stanza); // handler still fires if error if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { return; } const char *from = xmpp_stanza_get_from(stanza); if (!from) { log_warning("MUC User stanza received with no from attribute"); return; } Jid *from_jid = jid_create(from); if (from_jid == NULL || from_jid->resourcepart == NULL) { log_warning("MUC User stanza received with invalid from attribute: %s", from); jid_destroy(from_jid); return; } jid_destroy(from_jid); if (stanza_is_muc_self_presence(stanza, connection_get_fulljid())) { _muc_user_self_handler(stanza); } else { _muc_user_occupant_handler(stanza); } }
static void _init(char *log_level) { setlocale(LC_ALL, ""); // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGWINCH, ui_sigwinch_handler); if (pthread_mutex_init(&lock, NULL) != 0) { log_error("Mutex init failed"); exit(1); } pthread_mutex_lock(&lock); files_create_directories(); log_level_t prof_log_level = log_level_from_string(log_level); prefs_load(); log_init(prof_log_level); log_stderr_init(PROF_LEVEL_ERROR); if (strcmp(PACKAGE_STATUS, "development") == 0) { #ifdef HAVE_GIT_VERSION log_info("Starting Profanity (%sdev.%s.%s)...", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION); #else log_info("Starting Profanity (%sdev)...", PACKAGE_VERSION); #endif } else { log_info("Starting Profanity (%s)...", PACKAGE_VERSION); } chat_log_init(); groupchat_log_init(); accounts_load(); char *theme = prefs_get_string(PREF_THEME); theme_init(theme); prefs_free_string(theme); ui_init(); session_init(); cmd_init(); log_info("Initialising contact list"); muc_init(); tlscerts_init(); scripts_init(); #ifdef HAVE_LIBOTR otr_init(); #endif #ifdef HAVE_LIBGPGME p_gpg_init(); #endif #ifdef HAVE_OMEMO omemo_init(); #endif atexit(_shutdown); plugins_init(); #ifdef HAVE_GTK tray_init(); #endif inp_nonblocking(TRUE); ui_resize(); }
char * inp_readline(void) { free(inp_line); inp_line = NULL; p_rl_timeout.tv_sec = inp_timeout / 1000; p_rl_timeout.tv_usec = inp_timeout % 1000 * 1000; FD_ZERO(&fds); FD_SET(fileno(rl_instream), &fds); errno = 0; r = select(FD_SETSIZE, &fds, NULL, NULL, &p_rl_timeout); if (r < 0) { if (errno != EINTR) { char *err_msg = strerror(errno); log_error("Readline failed: %s", err_msg); } return NULL; } if (FD_ISSET(fileno(rl_instream), &fds)) { rl_callback_read_char(); if (rl_line_buffer && rl_line_buffer[0] != '/' && rl_line_buffer[0] != '\0' && rl_line_buffer[0] != '\n') { prof_handle_activity(); } ui_reset_idle_time(); if (!get_password) { _inp_write(rl_line_buffer, rl_point); } inp_nonblocking(TRUE); } else { inp_nonblocking(FALSE); prof_handle_idle(); } if (inp_line) { return strdup(inp_line); } else { return NULL; } }
static void _init(char *log_level) { setlocale(LC_ALL, ""); // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGWINCH, ui_sigwinch_handler); _create_directories(); log_level_t prof_log_level = log_level_from_string(log_level); prefs_load(); log_init(prof_log_level); log_stderr_init(PROF_LEVEL_ERROR); if (strcmp(PROF_PACKAGE_STATUS, "development") == 0) { #ifdef PROF_HAVE_GIT_VERSION log_info("Starting Profanity (%sdev.%s.%s)...", PROF_PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION); #else log_info("Starting Profanity (%sdev)...", PROF_PACKAGE_VERSION); #endif } else { log_info("Starting Profanity (%s)...", PROF_PACKAGE_VERSION); } chat_log_init(); groupchat_log_init(); accounts_load(); char *theme = prefs_get_string(PREF_THEME); theme_init(theme); prefs_free_string(theme); ui_init(); jabber_init(); cmd_init(); log_info("Initialising contact list"); muc_init(); tlscerts_init(); scripts_init(); #ifdef PROF_HAVE_LIBOTR otr_init(); #endif #ifdef PROF_HAVE_LIBGPGME p_gpg_init(); #endif atexit(_shutdown); plugins_init(); #ifdef PROF_HAVE_GTK if (gtk_ready) { log_debug("Building GTK icon"); create_tray(); } #endif inp_nonblocking(TRUE); }
void win_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp, int flags, theme_item_t theme_item, const char *const from, const char *const message) { if (timestamp == NULL) { timestamp = g_date_time_new_now_local(); } else { g_date_time_ref(timestamp); } buffer_push(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, from, message, NULL); _win_print(window, show_char, pad_indent, timestamp, flags, theme_item, from, message, NULL); // TODO: cross-reference.. this should be replaced by a real event-based system inp_nonblocking(TRUE); g_date_time_unref(timestamp); }
static void _unavailable_handler(xmpp_stanza_t *const stanza) { inp_nonblocking(TRUE); xmpp_conn_t *conn = connection_get_conn(); const char *jid = xmpp_conn_get_jid(conn); const char *from = xmpp_stanza_get_from(stanza); if (!from) { log_warning("Unavailable presence received with no from attribute"); } log_debug("Unavailable presence handler fired for %s", from); Jid *my_jid = jid_create(jid); Jid *from_jid = jid_create(from); if (my_jid == NULL || from_jid == NULL) { jid_destroy(my_jid); jid_destroy(from_jid); return; } if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { char *status_str = stanza_get_status(stanza, NULL); if (from_jid->resourcepart) { sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str); // hack for servers that do not send full jid with unavailable presence } else { sv_ev_contact_offline(from_jid->barejid, "__prof_default", status_str); } free(status_str); } else { if (from_jid->resourcepart) { connection_remove_available_resource(from_jid->resourcepart); } } jid_destroy(my_jid); jid_destroy(from_jid); }
void win_print_with_receipt(ProfWin *window, const char show_char, int pad_indent, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char *const from, const char *const message, char *id) { GDateTime *time; if (tstamp == NULL) { time = g_date_time_new_now_local(); } else { time = g_date_time_new_from_timeval_utc(tstamp); } DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t)); receipt->id = strdup(id); receipt->received = FALSE; buffer_push(window->layout->buffer, show_char, pad_indent, time, flags, theme_item, from, message, receipt); _win_print(window, show_char, pad_indent, time, flags, theme_item, from, message, receipt); // TODO: cross-reference.. this should be replaced by a real event-based system inp_nonblocking(TRUE); g_date_time_unref(time); }
static void _available_handler(xmpp_stanza_t *const stanza) { inp_nonblocking(TRUE); // handler still fires if error if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { return; } // handler still fires if other types if ((g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNAVAILABLE) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBE) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBED) == 0) || (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNSUBSCRIBED) == 0)) { return; } // handler still fires for muc presence if (stanza_is_muc_presence(stanza)) { return; } int err = 0; XMPPPresence *xmpp_presence = stanza_parse_presence(stanza, &err); if (!xmpp_presence) { const char *from = NULL; switch(err) { case STANZA_PARSE_ERROR_NO_FROM: log_warning("Available presence handler fired with no from attribute."); break; case STANZA_PARSE_ERROR_INVALID_FROM: from = xmpp_stanza_get_from(stanza); log_warning("Available presence handler fired with invalid from attribute: %s", from); break; default: log_warning("Available presence handler fired, could not parse stanza."); break; } return; } else { char *jid = jid_fulljid_or_barejid(xmpp_presence->jid); log_debug("Presence available handler fired for: %s", jid); } xmpp_conn_t *conn = connection_get_conn(); const char *my_jid_str = xmpp_conn_get_jid(conn); Jid *my_jid = jid_create(my_jid_str); XMPPCaps *caps = stanza_parse_caps(stanza); if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && caps) { log_info("Presence contains capabilities."); char *jid = jid_fulljid_or_barejid(xmpp_presence->jid); _handle_caps(jid, caps); } stanza_free_caps(caps); Resource *resource = stanza_resource_from_presence(xmpp_presence); if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) { connection_add_available_resource(resource); } else { char *pgpsig = NULL; xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_SIGNED); if (x) { pgpsig = xmpp_stanza_get_text(x); } sv_ev_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity, pgpsig); xmpp_ctx_t *ctx = connection_get_ctx(); xmpp_free(ctx, pgpsig); } jid_destroy(my_jid); stanza_free_presence(xmpp_presence); }