Beispiel #1
0
void
prof_run(const int disable_tls, char *log_level, char *account_name)
{
    _init(disable_tls, log_level);
    log_info("Starting main event loop");
    inp_non_block();
    GTimer *timer = g_timer_new();
    gboolean cmd_result = TRUE;
    jabber_conn_status_t conn_status = jabber_get_connection_status();

    char inp[INP_WIN_MAX];
    int size = 0;

    ui_update_screen();

    if (account_name != NULL) {
      char *cmd = "/connect";
      snprintf(inp, sizeof(inp), "%s %s", cmd, account_name);
      process_input(inp);
    } else if (prefs_get_string(PREF_CONNECT_ACCOUNT) != NULL) {
      char *cmd = "/connect";
      snprintf(inp, sizeof(inp), "%s %s", cmd, prefs_get_string(PREF_CONNECT_ACCOUNT));
      process_input(inp);
    }

    while(cmd_result == TRUE) {
        wint_t ch = ERR;
        size = 0;

        while(ch != '\n') {
            conn_status = jabber_get_connection_status();
            if (conn_status == JABBER_CONNECTED) {
                _handle_idle_time();
            }

            gdouble elapsed = g_timer_elapsed(timer, NULL);

            gint remind_period = prefs_get_notify_remind();
            if (remind_period > 0 && elapsed >= remind_period) {
                notify_remind();
                g_timer_start(timer);
            }

            ui_handle_special_keys(&ch, inp, size);
            ui_update_screen();
            jabber_process_events();

            ch = inp_get_char(inp, &size);
            if (ch != ERR) {
                ui_reset_idle_time();
            }
        }

        inp[size++] = '\0';
        cmd_result = process_input(inp);
    }

    g_timer_destroy(timer);
}
Beispiel #2
0
int
ui_close_read_wins(void)
{
    int count = 0;
    jabber_conn_status_t conn_status = jabber_get_connection_status();

    GList *win_nums = wins_get_nums();
    GList *curr = win_nums;

    while (curr != NULL) {
        int num = GPOINTER_TO_INT(curr->data);
        if ((num != 1) && (ui_win_unread(num) == 0)) {
            if (conn_status == JABBER_CONNECTED) {
                ui_close_connected_win(num);
            }
            ui_close_win(num);
            count++;
        }
        curr = g_list_next(curr);
    }

    g_list_free(curr);
    g_list_free(win_nums);

    return count;
}
Beispiel #3
0
static int
cb_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient)
{
    jabber_conn_status_t conn_status = jabber_get_connection_status();
    if (conn_status != JABBER_CONNECTED) {
        return PRESENCE_OFFLINE;
    }

    PContact contact = roster_get_contact(recipient);

    // not in roster
    if (contact == NULL) {
        return PRESENCE_ONLINE;
    }

    // not subscribed
    if (p_contact_subscribed(contact) == FALSE) {
        return PRESENCE_ONLINE;
    }

    // subscribed
    if (g_strcmp0(p_contact_presence(contact), "offline") == 0) {
        return PRESENCE_OFFLINE;
    } else {
        return PRESENCE_ONLINE;
    }
}
Beispiel #4
0
void
prof_handle_idle(void)
{
    jabber_conn_status_t status = jabber_get_connection_status();
    if (status == JABBER_CONNECTED) {
        GSList *recipients = ui_get_recipients();
        GSList *curr = recipients;

        while (curr != NULL) {
            char *recipient = curr->data;
            if (chat_session_get_recipient_supports(recipient)) {
                chat_session_no_activity(recipient);

                if (chat_session_is_gone(recipient) &&
                        !chat_session_get_sent(recipient)) {
                    message_send_gone(recipient);
                } else if (chat_session_is_inactive(recipient) &&
                        !chat_session_get_sent(recipient)) {
                    message_send_inactive(recipient);
                } else if (prefs_get_boolean(PREF_OUTTYPE) &&
                        chat_session_is_paused(recipient) &&
                        !chat_session_get_sent(recipient)) {
                    message_send_paused(recipient);
                }
            }

            curr = g_slist_next(curr);
        }

        if (recipients != NULL) {
            g_slist_free(recipients);
        }
    }
}
Beispiel #5
0
void
cons_show_account_list(gchar **accounts)
{
    int size = g_strv_length(accounts);
    if (size > 0) {
        cons_show("Accounts:");
        int i = 0;
        for (i = 0; i < size; i++) {
            if ((jabber_get_connection_status() == JABBER_CONNECTED) &&
                    (g_strcmp0(jabber_get_account_name(), accounts[i]) == 0)) {
                resource_presence_t presence = accounts_get_last_presence(accounts[i]);
                win_print_time(console, '-');
                win_presence_colour_on(console, string_from_resource_presence(presence));
                wprintw(console->win, "%s\n", accounts[i]);
                win_presence_colour_off(console, string_from_resource_presence(presence));
            } else {
                cons_show(accounts[i]);
            }
        }
        cons_show("");
    } else {
        cons_show("No accounts created yet.");
        cons_show("");
    }

    ui_console_dirty();
    cons_alert();
}
Beispiel #6
0
static void
_jabber_disconnect(void)
{
    // if connected, send end stream and wait for response
    if (jabber_conn.conn_status == JABBER_CONNECTED) {
        log_info("Closing connection");
        jabber_conn.conn_status = JABBER_DISCONNECTING;
        xmpp_disconnect(jabber_conn.conn);

        while (jabber_get_connection_status() == JABBER_DISCONNECTING) {
            jabber_process_events();
        }
        _connection_free_saved_account();
        _connection_free_saved_details();
        _connection_free_session_data();
        if (jabber_conn.conn != NULL) {
            xmpp_conn_release(jabber_conn.conn);
            jabber_conn.conn = NULL;
        }
        if (jabber_conn.ctx != NULL) {
            xmpp_ctx_free(jabber_conn.ctx);
            jabber_conn.ctx = NULL;
        }
    }

    jabber_conn.conn_status = JABBER_STARTED;
    FREE_SET_NULL(jabber_conn.presence_message);
    FREE_SET_NULL(jabber_conn.domain);
}
Beispiel #7
0
void
jabber_disconnect(void)
{
    // if connected, send end stream and wait for response
    if (jabber_conn.conn_status == JABBER_CONNECTED) {
        char *account_name = jabber_get_account_name();
        const char *fulljid = jabber_get_fulljid();
        plugins_on_disconnect(account_name, fulljid);
        log_info("Closing connection");
        accounts_set_last_activity(jabber_get_account_name());
        jabber_conn.conn_status = JABBER_DISCONNECTING;
        xmpp_disconnect(jabber_conn.conn);

        while (jabber_get_connection_status() == JABBER_DISCONNECTING) {
            jabber_process_events(10);
        }
        _connection_free_saved_account();
        _connection_free_saved_details();
        _connection_free_session_data();
        if (jabber_conn.conn) {
            xmpp_conn_release(jabber_conn.conn);
            jabber_conn.conn = NULL;
        }
        if (jabber_conn.ctx) {
            xmpp_ctx_free(jabber_conn.ctx);
            jabber_conn.ctx = NULL;
        }
    }

    jabber_conn.conn_status = JABBER_STARTED;
    FREE_SET_NULL(jabber_conn.presence_message);
    FREE_SET_NULL(jabber_conn.domain);
}
Beispiel #8
0
void
jabber_autoping_fail(void)
{
    if (jabber_conn.conn_status == JABBER_CONNECTED) {
        log_info("Closing connection");
        char *account_name = jabber_get_account_name();
        const char *fulljid = jabber_get_fulljid();
        plugins_on_disconnect(account_name, fulljid);
        accounts_set_last_activity(jabber_get_account_name());
        jabber_conn.conn_status = JABBER_DISCONNECTING;
        xmpp_disconnect(jabber_conn.conn);

        while (jabber_get_connection_status() == JABBER_DISCONNECTING) {
            jabber_process_events(10);
        }
        if (jabber_conn.conn) {
            xmpp_conn_release(jabber_conn.conn);
            jabber_conn.conn = NULL;
        }
        if (jabber_conn.ctx) {
            xmpp_ctx_free(jabber_conn.ctx);
            jabber_conn.ctx = NULL;
        }
    }

    FREE_SET_NULL(jabber_conn.presence_message);
    FREE_SET_NULL(jabber_conn.domain);

    jabber_conn.conn_status = JABBER_DISCONNECTED;
    _jabber_lost_connection();
}
Beispiel #9
0
char*
chatwin_get_string(ProfChatWin *chatwin)
{
    assert(chatwin != NULL);

    GString *res = g_string_new("Chat ");

    jabber_conn_status_t conn_status = jabber_get_connection_status();
    if (conn_status == JABBER_CONNECTED) {
        PContact contact = roster_get_contact(chatwin->barejid);
        if (contact == NULL) {
            g_string_append(res, chatwin->barejid);
        } else {
            const char *display_name = p_contact_name_or_jid(contact);
            g_string_append(res, display_name);
            g_string_append_printf(res, " - %s", p_contact_presence(contact));
        }
    } else {
        g_string_append(res, chatwin->barejid);
    }

    if (chatwin->unread > 0) {
        g_string_append_printf(res, ", %d unread", chatwin->unread);
    }

    char *resstr = res->str;
    g_string_free(res, FALSE);

    return resstr;
}
Beispiel #10
0
void
prof_handle_activity(void)
{
    win_type_t win_type = ui_current_win_type();
    jabber_conn_status_t status = jabber_get_connection_status();

    if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) {
        ProfChatWin *chatwin = wins_get_current_chat();
        chat_state_handle_typing(chatwin->barejid, chatwin->state);
    }
}
Beispiel #11
0
void
prof_handle_activity(void)
{
    jabber_conn_status_t status = jabber_get_connection_status();
    ProfWin *current = wins_get_current();

    if ((status == JABBER_CONNECTED) && (current->type == WIN_CHAT)) {
        ProfChatWin *chatwin = (ProfChatWin*)current;
        assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
        chat_state_handle_typing(chatwin->barejid, chatwin->state);
    }
}
Beispiel #12
0
static void
_check_autoaway()
{
    jabber_conn_status_t conn_status = jabber_get_connection_status();
    if (conn_status != JABBER_CONNECTED) {
        return;
    }

    gint prefs_time = prefs_get_autoaway_time() * 60000;
    unsigned long idle_ms = ui_get_idle_time();
    char *pref_autoaway_mode = prefs_get_string(PREF_AUTOAWAY_MODE);

    if (!idle) {
        resource_presence_t current_presence = accounts_get_last_presence(jabber_get_account_name());
        if ((current_presence == RESOURCE_ONLINE) || (current_presence == RESOURCE_CHAT)) {
            if (idle_ms >= prefs_time) {
                idle = TRUE;
                char *pref_autoaway_message = prefs_get_string(PREF_AUTOAWAY_MESSAGE);

                // handle away mode
                if (strcmp(pref_autoaway_mode, "away") == 0) {
                    presence_update(RESOURCE_AWAY, pref_autoaway_message, 0);
                    ui_auto_away();

                // handle idle mode
                } else if (strcmp(pref_autoaway_mode, "idle") == 0) {
                    presence_update(RESOURCE_ONLINE, pref_autoaway_message, idle_ms / 1000);
                }

                prefs_free_string(pref_autoaway_message);
            }
        }

    } else {
        if (idle_ms < prefs_time) {
            idle = FALSE;

            // handle check
            if (prefs_get_boolean(PREF_AUTOAWAY_CHECK)) {
                if (strcmp(pref_autoaway_mode, "away") == 0) {
                    presence_update(RESOURCE_ONLINE, NULL, 0);
                    ui_end_auto_away();
                } else if (strcmp(pref_autoaway_mode, "idle") == 0) {
                    presence_update(RESOURCE_ONLINE, NULL, 0);
                    ui_titlebar_presence(CONTACT_ONLINE);
                }
            }
        }
    }

    prefs_free_string(pref_autoaway_mode);
}
Beispiel #13
0
static void
_ui_draw_win_title(void)
{
    char new_win_title[100];

    GString *version_str = g_string_new("");

    if (prefs_get_boolean(PREF_TITLEBARVERSION)) {
        g_string_append(version_str, " ");
        g_string_append(version_str, PACKAGE_VERSION);
        if (strcmp(PACKAGE_STATUS, "development") == 0) {
#ifdef HAVE_GIT_VERSION
            g_string_append(version_str, "dev.");
            g_string_append(version_str, PROF_GIT_BRANCH);
            g_string_append(version_str, ".");
            g_string_append(version_str, PROF_GIT_REVISION);
#else
            g_string_append(version_str, "dev");
#endif
        }
    }

    jabber_conn_status_t status = jabber_get_connection_status();

    if (status == JABBER_CONNECTED) {
        const char * const jid = jabber_get_fulljid();
        gint unread = ui_unread();

        if (unread != 0) {
            snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s (%d) - %s%c", '\033', "Profanity", version_str->str, unread, jid, '\007');
        } else {
            snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s - %s%c", '\033', "Profanity", version_str->str, jid, '\007');
        }
    } else {
        snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s%c", '\033', "Profanity", version_str->str, '\007');
    }

    g_string_free(version_str, TRUE);

    if (g_strcmp0(win_title, new_win_title) != 0) {
        // print to x-window title bar
        printf("%s", new_win_title);
        if (win_title != NULL) {
            free(win_title);
        }
        win_title = strdup(new_win_title);
    }
}
Beispiel #14
0
static void
_iq_set_autoping(const int seconds)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();

    if (jabber_get_connection_status() == JABBER_CONNECTED) {
        xmpp_timed_handler_delete(conn, _ping_timed_handler);

        if (seconds != 0) {
            int millis = seconds * 1000;
            xmpp_timed_handler_add(conn, _ping_timed_handler, millis,
                ctx);
        }
    }
}
Beispiel #15
0
static void
_presence_update(const resource_presence_t presence_type, const char * const msg,
    const int idle)
{
    if (jabber_get_connection_status() != JABBER_CONNECTED) {
        log_warning("Error setting presence, not connected.");
        return;
    }

    if (msg != NULL) {
        log_debug("Updating presence: %s, \"%s\"",
            string_from_resource_presence(presence_type), msg);
    } else {
        log_debug("Updating presence: %s",
            string_from_resource_presence(presence_type));
    }

    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_conn_t * const conn = connection_get_conn();
    const int pri =
        accounts_get_priority_for_presence_type(jabber_get_account_name(),
                                                presence_type);
    const char *show = stanza_get_presence_string_from_type(presence_type);

    connection_set_presence_message(msg);
    connection_set_priority(pri);

    xmpp_stanza_t *presence = stanza_create_presence(ctx);
    char *id = create_unique_id("presence");
    xmpp_stanza_set_id(presence, id);
    stanza_attach_show(ctx, presence, show);
    stanza_attach_status(ctx, presence, msg);
    stanza_attach_priority(ctx, presence, pri);
    stanza_attach_last_activity(ctx, presence, idle);
    stanza_attach_caps(ctx, presence);
    xmpp_send(conn, presence);
    _send_room_presence(conn, presence);
    xmpp_stanza_release(presence);

    // set last presence for account
    const char *last = show;
    if (last == NULL) {
        last = STANZA_TEXT_ONLINE;
    }
    accounts_set_last_presence(jabber_get_account_name(), last);
    free(id);
}
Beispiel #16
0
void
prof_handle_activity(void)
{
    win_type_t win_type = ui_current_win_type();
    jabber_conn_status_t status = jabber_get_connection_status();

    if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) {
        char *recipient = ui_current_recipient();
        if (chat_session_get_recipient_supports(recipient)) {
            chat_session_set_composing(recipient);
            if (!chat_session_get_sent(recipient) ||
                    chat_session_is_paused(recipient)) {
                message_send_composing(recipient);
            }
        }
    }
}
Beispiel #17
0
static void
_shutdown(void)
{
    if (prefs_get_boolean(PREF_TITLEBAR_SHOW)) {
        if (prefs_get_boolean(PREF_TITLEBAR_GOODBYE)) {
            ui_goodbye_title();
        } else {
            ui_clear_win_title();
        }
    }

    jabber_conn_status_t conn_status = jabber_get_connection_status();
    if (conn_status == JABBER_CONNECTED) {
        cl_ev_disconnect();
    }
#ifdef PROF_HAVE_GTK
    if (gtk_ready) {
        destroy_tray();
    }
#endif
    jabber_shutdown();
    plugins_on_shutdown();
    muc_close();
    caps_close();
    ui_close();
#ifdef PROF_HAVE_LIBOTR
    otr_shutdown();
#endif
#ifdef PROF_HAVE_LIBGPGME
    p_gpg_close();
#endif
    chat_log_close();
    theme_close();
    accounts_close();
    tlscerts_close();
    cmd_uninit();
    log_stderr_close();
    log_close();
    plugins_shutdown();
    prefs_close();
    if (saved_status) {
        free(saved_status);
    }
}
Beispiel #18
0
void
ui_prune_wins(void)
{
    jabber_conn_status_t conn_status = jabber_get_connection_status();
    gboolean pruned = FALSE;

    GSList *recipients = wins_get_prune_recipients();
    if (recipients != NULL) {
        pruned = TRUE;
    }
    GSList *curr = recipients;
    while (curr != NULL) {
        char *recipient = curr->data;

        if (conn_status == JABBER_CONNECTED) {
            if (prefs_get_boolean(PREF_STATES)) {

                // send <gone/> chat state before closing
                if (chat_session_get_recipient_supports(recipient)) {
                    chat_session_set_gone(recipient);
                    message_send_gone(recipient);
                    chat_session_end(recipient);
                }
            }
        }

        ProfWin *window = wins_get_by_recipient(recipient);
        int num = wins_get_num(window);
        ui_close_win(num);

        curr = g_slist_next(curr);
    }

    if (recipients != NULL) {
        g_slist_free(recipients);
    }

    wins_tidy();
    if (pruned) {
        cons_show("Windows pruned.");
    } else {
        cons_show("No prune needed.");
    }
}
Beispiel #19
0
static int
_ping_timed_handler(xmpp_conn_t * const conn, void * const userdata)
{
    xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;

    if (jabber_get_connection_status() == JABBER_CONNECTED) {

        xmpp_stanza_t *iq = stanza_create_ping_iq(ctx, NULL);
        char *id = xmpp_stanza_get_id(iq);

        // add pong handler
        xmpp_id_handler_add(conn, _pong_handler, id, ctx);

        xmpp_send(conn, iq);
        xmpp_stanza_release(iq);
    }

    return 1;
}
Beispiel #20
0
void
prof_handle_idle(void)
{
    jabber_conn_status_t status = jabber_get_connection_status();
    if (status == JABBER_CONNECTED) {
        GSList *recipients = ui_get_chat_recipients();
        GSList *curr = recipients;

        while (curr) {
            char *barejid = curr->data;
            ProfChatWin *chatwin = wins_get_chat(barejid);
            chat_state_handle_idle(chatwin->barejid, chatwin->state);
            curr = g_slist_next(curr);
        }

        if (recipients) {
            g_slist_free(recipients);
        }
    }
}
Beispiel #21
0
void
cons_show_account(ProfAccount *account)
{
    cons_show("");
    cons_show("Account %s:", account->name);
    if (account->enabled) {
        cons_show   ("enabled        : TRUE");
    } else {
        cons_show   ("enabled        : FALSE");
    }
    cons_show       ("jid            : %s", account->jid);
    if (account->resource != NULL) {
        cons_show   ("resource       : %s", account->resource);
    }
    if (account->server != NULL) {
        cons_show   ("server         : %s", account->server);
    }
    if (account->last_presence != NULL) {
        cons_show   ("Last presence  : %s", account->last_presence);
    }
    if (account->login_presence != NULL) {
        cons_show   ("Login presence : %s", account->login_presence);
    }
    cons_show       ("Priority       : chat:%d, online:%d, away:%d, xa:%d, dnd:%d",
        account->priority_chat, account->priority_online, account->priority_away,
        account->priority_xa, account->priority_dnd);

    if ((jabber_get_connection_status() == JABBER_CONNECTED) &&
            (g_strcmp0(jabber_get_account_name(), account->name) == 0)) {
        GList *resources = jabber_get_available_resources();
        GList *ordered_resources = NULL;

        WINDOW *win = console->win;
        if (resources != NULL) {
            win_print_time(console, '-');
            wprintw(win, "Resources:\n");

            // sort in order of availabiltiy
            while (resources != NULL) {
                Resource *resource = resources->data;
                ordered_resources = g_list_insert_sorted(ordered_resources,
                    resource, (GCompareFunc)resource_compare_availability);
                resources = g_list_next(resources);
            }
        }

        while (ordered_resources != NULL) {
            Resource *resource = ordered_resources->data;
            const char *resource_presence = string_from_resource_presence(resource->presence);
            win_print_time(console, '-');
            win_presence_colour_on(console, resource_presence);
            wprintw(win, "  %s (%d), %s", resource->name, resource->priority, resource_presence);
            if (resource->status != NULL) {
                wprintw(win, ", \"%s\"", resource->status);
            }
            wprintw(win, "\n");
            win_presence_colour_off(console, resource_presence);

            if (resource->caps_str != NULL) {
                Capabilities *caps = caps_get(resource->caps_str);
                if (caps != NULL) {
                    // show identity
                    if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
                        win_print_time(console, '-');
                        wprintw(win, "    Identity: ");
                        if (caps->name != NULL) {
                            wprintw(win, "%s", caps->name);
                            if ((caps->category != NULL) || (caps->type != NULL)) {
                                wprintw(win, " ");
                            }
                        }
                        if (caps->type != NULL) {
                            wprintw(win, "%s", caps->type);
                            if (caps->category != NULL) {
                                wprintw(win, " ");
                            }
                        }
                        if (caps->category != NULL) {
                            wprintw(win, "%s", caps->category);
                        }
                        wprintw(win, "\n");
                    }
                    if (caps->software != NULL) {
                        win_print_time(console, '-');
                        wprintw(win, "    Software: %s", caps->software);
                    }
                    if (caps->software_version != NULL) {
                        wprintw(win, ", %s", caps->software_version);
                    }
                    if ((caps->software != NULL) || (caps->software_version != NULL)) {
                        wprintw(win, "\n");
                    }
                    if (caps->os != NULL) {
                        win_print_time(console, '-');
                        wprintw(win, "    OS: %s", caps->os);
                    }
                    if (caps->os_version != NULL) {
                        wprintw(win, ", %s", caps->os_version);
                    }
                    if ((caps->os != NULL) || (caps->os_version != NULL)) {
                        wprintw(win, "\n");
                    }
                }
            }

            ordered_resources = g_list_next(ordered_resources);
        }
    }

    ui_console_dirty();
    cons_alert();
}
Beispiel #22
0
static void
_check_autoaway()
{
    jabber_conn_status_t conn_status = jabber_get_connection_status();
    if (conn_status != JABBER_CONNECTED) {
        return;
    }

    char *mode = prefs_get_string(PREF_AUTOAWAY_MODE);
    gboolean check = prefs_get_boolean(PREF_AUTOAWAY_CHECK);
    gint away_time = prefs_get_autoaway_time();
    gint xa_time = prefs_get_autoxa_time();
    int away_time_ms = away_time * 60000;
    int xa_time_ms = xa_time * 60000;

    char *account = jabber_get_account_name();
    resource_presence_t curr_presence = accounts_get_last_presence(account);
    char *curr_status = accounts_get_last_status(account);

    unsigned long idle_ms = ui_get_idle_time();

    switch (activity_state) {
    case ACTIVITY_ST_ACTIVE:
        if (idle_ms >= away_time_ms) {
            if (g_strcmp0(mode, "away") == 0) {
                if ((curr_presence == RESOURCE_ONLINE) || (curr_presence == RESOURCE_CHAT) || (curr_presence == RESOURCE_DND)) {
                    activity_state = ACTIVITY_ST_AWAY;

                    // save current presence
                    saved_presence = curr_presence;
                    if (saved_status) {
                        free(saved_status);
                    }
                    saved_status = curr_status;

                    // send away presence with last activity
                    char *message = prefs_get_string(PREF_AUTOAWAY_MESSAGE);
                    if (prefs_get_boolean(PREF_LASTACTIVITY)) {
                        cl_ev_presence_send(RESOURCE_AWAY, message, idle_ms / 1000);
                    } else {
                        cl_ev_presence_send(RESOURCE_AWAY, message, 0);
                    }

                    int pri = accounts_get_priority_for_presence_type(account, RESOURCE_AWAY);
                    if (message) {
                        cons_show("Idle for %d minutes, status set to away (priority %d), \"%s\".", away_time, pri, message);
                    } else {
                        cons_show("Idle for %d minutes, status set to away (priority %d).", away_time, pri);
                    }
                    prefs_free_string(message);

                    ui_titlebar_presence(CONTACT_AWAY);
                }
            } else if (g_strcmp0(mode, "idle") == 0) {
                activity_state = ACTIVITY_ST_IDLE;

                // send current presence with last activity
                cl_ev_presence_send(curr_presence, curr_status, idle_ms / 1000);
            }
        }
        break;
    case ACTIVITY_ST_IDLE:
        if (check && (idle_ms < away_time_ms)) {
            activity_state = ACTIVITY_ST_ACTIVE;

            cons_show("No longer idle.");

            // send current presence without last activity
            cl_ev_presence_send(curr_presence, curr_status, 0);
        }
        break;
    case ACTIVITY_ST_AWAY:
        if (xa_time_ms > 0 && (idle_ms >= xa_time_ms)) {
            activity_state = ACTIVITY_ST_XA;

            // send extended away presence with last activity
            char *message = prefs_get_string(PREF_AUTOXA_MESSAGE);
            if (prefs_get_boolean(PREF_LASTACTIVITY)) {
                cl_ev_presence_send(RESOURCE_XA, message, idle_ms / 1000);
            } else {
                cl_ev_presence_send(RESOURCE_XA, message, 0);
            }

            int pri = accounts_get_priority_for_presence_type(account, RESOURCE_XA);
            if (message) {
                cons_show("Idle for %d minutes, status set to xa (priority %d), \"%s\".", xa_time, pri, message);
            } else {
                cons_show("Idle for %d minutes, status set to xa (priority %d).", xa_time, pri);
            }
            prefs_free_string(message);

            ui_titlebar_presence(CONTACT_XA);
        } else if (check && (idle_ms < away_time_ms)) {
            activity_state = ACTIVITY_ST_ACTIVE;

            cons_show("No longer idle.");

            // send saved presence without last activity
            cl_ev_presence_send(saved_presence, saved_status, 0);
            contact_presence_t contact_pres = contact_presence_from_resource_presence(saved_presence);
            ui_titlebar_presence(contact_pres);
        }
        break;
    case ACTIVITY_ST_XA:
        if (check && (idle_ms < away_time_ms)) {
            activity_state = ACTIVITY_ST_ACTIVE;

            cons_show("No longer idle.");

            // send saved presence without last activity
            cl_ev_presence_send(saved_presence, saved_status, 0);
            contact_presence_t contact_pres = contact_presence_from_resource_presence(saved_presence);
            ui_titlebar_presence(contact_pres);
        }
        break;
    }

    prefs_free_string(mode);
}