예제 #1
0
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);
    }
}
예제 #2
0
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();
}
예제 #3
0
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;
    }
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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);
}
예제 #7
0
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);
}
예제 #8
0
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);
}