Exemplo n.º 1
0
void
iq_add_handlers(void)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();

    HANDLE(NULL,                STANZA_TYPE_ERROR,  _error_handler);

    HANDLE(XMPP_NS_DISCO_INFO,  STANZA_TYPE_GET,    _disco_info_get_handler);
    HANDLE(XMPP_NS_DISCO_INFO,  STANZA_TYPE_RESULT, _disco_info_result_handler);

    HANDLE(XMPP_NS_DISCO_ITEMS, STANZA_TYPE_GET,    _disco_items_get_handler);
    HANDLE(XMPP_NS_DISCO_ITEMS, STANZA_TYPE_RESULT, _disco_items_result_handler);

    HANDLE(STANZA_NS_VERSION,   STANZA_TYPE_GET,    _version_get_handler);
    HANDLE(STANZA_NS_VERSION,   STANZA_TYPE_RESULT, _version_result_handler);

    HANDLE(STANZA_NS_PING,      STANZA_TYPE_GET,    _ping_get_handler);

    if (prefs_get_autoping() != 0) {
        int millis = prefs_get_autoping() * 1000;
        xmpp_timed_handler_add(conn, _ping_timed_handler, millis, ctx);
    }
}
Exemplo n.º 2
0
static int
_captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
    void * const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);

    if (from == NULL) {
        log_warning("Message received with no from attribute, ignoring");
        return 1;
    }

    // XEP-0158
    xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
    if (body != NULL) {
        char *message = xmpp_stanza_get_text(body);
        if (message != NULL) {
            handle_room_broadcast(from, message);
            xmpp_free(ctx, message);
        }
    }

    return 1;
}
Exemplo n.º 3
0
void
_private_chat_handler(xmpp_stanza_t *const stanza, const char *const fulljid)
{
    xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
    if (!body) {
        return;
    }

    char *message = xmpp_stanza_get_text(body);
    if (!message) {
        return;
    }

    GDateTime *timestamp = stanza_get_delay(stanza);
    if (timestamp) {
        sv_ev_delayed_private_message(fulljid, message, timestamp);
        g_date_time_unref(timestamp);
    } else {
        sv_ev_incoming_private_message(fulljid, message);
    }

    xmpp_ctx_t *ctx = connection_get_ctx();
    xmpp_free(ctx, message);
}
Exemplo n.º 4
0
static gboolean
_bookmark_add(const char *jid, const char *nick, gboolean autojoin)
{
    gboolean added = TRUE;
    if (autocomplete_contains(bookmark_ac, jid)) {
        added = FALSE;
    }

    xmpp_conn_t *conn = connection_get_conn();
    xmpp_ctx_t *ctx = connection_get_ctx();

    /* TODO: send request */
    xmpp_stanza_t *stanza = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(stanza, STANZA_NAME_IQ);
    char *id = generate_unique_id("bookmark_add");
    xmpp_stanza_set_id(stanza, id);
    xmpp_stanza_set_type(stanza, STANZA_TYPE_SET);

    xmpp_stanza_t *pubsub = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB);
    xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB);
    xmpp_stanza_add_child(stanza, pubsub);

    xmpp_stanza_t *publish = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(publish, STANZA_NAME_PUBLISH);
    xmpp_stanza_set_attribute(publish, STANZA_ATTR_NODE, "storage:bookmarks");
    xmpp_stanza_add_child(pubsub, publish);

    xmpp_stanza_t *item = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(item, STANZA_NAME_ITEM);
    xmpp_stanza_add_child(publish, item);

    xmpp_stanza_t *storage = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(storage, STANZA_NAME_STORAGE);
    xmpp_stanza_set_ns(storage, "storage;bookmarks");
    xmpp_stanza_add_child(item, storage);

    xmpp_stanza_t *conference = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(conference, STANZA_NAME_CONFERENCE);
    xmpp_stanza_set_attribute(conference, STANZA_ATTR_JID, jid);

    if (autojoin) {
        xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "true");
    } else {
        xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
    }

    xmpp_stanza_add_child(storage, conference);

    if (nick != NULL) {
        xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
        xmpp_stanza_set_text(nick_st, nick);
        xmpp_stanza_add_child(conference, nick_st);
    }

    xmpp_stanza_t *publish_options = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(publish_options, STANZA_NAME_PUBLISH_OPTIONS);
    xmpp_stanza_add_child(pubsub, publish_options);

    xmpp_stanza_t *x = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(x, STANZA_NAME_X);
    xmpp_stanza_set_ns(x, STANZA_NS_DATA);
    xmpp_stanza_set_attribute(x, STANZA_ATTR_TYPE, "submit");
    xmpp_stanza_add_child(publish_options, x);

    xmpp_stanza_t *form_type = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(form_type, STANZA_NAME_FIELD);
    xmpp_stanza_set_attribute(form_type, STANZA_ATTR_VAR, "FORM_TYPE");
    xmpp_stanza_set_attribute(form_type, STANZA_ATTR_TYPE, "hidden");
    xmpp_stanza_t *form_type_value = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(form_type_value, STANZA_NAME_VALUE);
    xmpp_stanza_t *form_type_value_text = xmpp_stanza_new(ctx);
    xmpp_stanza_set_text(form_type_value_text, "http://jabber.org/protocol/pubsub#publish-options");
    xmpp_stanza_add_child(form_type_value, form_type_value_text);
    xmpp_stanza_add_child(form_type, form_type_value);
    xmpp_stanza_add_child(x, form_type);

    xmpp_stanza_t *persist_items = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(persist_items, STANZA_NAME_FIELD);
    xmpp_stanza_set_attribute(persist_items, STANZA_ATTR_VAR, "pubsub#persist_items");
    xmpp_stanza_t *persist_items_value = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(persist_items_value, STANZA_NAME_VALUE);
    xmpp_stanza_t *persist_items_value_text = xmpp_stanza_new(ctx);
    xmpp_stanza_set_text(persist_items_value_text, "true");
    xmpp_stanza_add_child(persist_items_value, persist_items_value_text);
    xmpp_stanza_add_child(persist_items, persist_items_value);
    xmpp_stanza_add_child(x, persist_items);

    xmpp_stanza_t *access_model = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(access_model, STANZA_NAME_FIELD);
    xmpp_stanza_set_attribute(access_model, STANZA_ATTR_VAR, "pubsub#access_model");
    xmpp_stanza_t *access_model_value = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(access_model_value, STANZA_NAME_VALUE);
    xmpp_stanza_t *access_model_value_text = xmpp_stanza_new(ctx);
    xmpp_stanza_set_text(access_model_value_text, "whitelist");
    xmpp_stanza_add_child(access_model_value, access_model_value_text);
    xmpp_stanza_add_child(access_model, access_model_value);
    xmpp_stanza_add_child(x, access_model);

    xmpp_send(conn, stanza);
    xmpp_stanza_release(stanza);

    /* TODO: manage bookmark_list */

    /* this may be command for modifying */
    autocomplete_remove(bookmark_ac, jid);
    autocomplete_add(bookmark_ac, jid);

    return added;
}
Exemplo n.º 5
0
static int
_bookmark_handle_result(xmpp_conn_t * const conn,
    xmpp_stanza_t * const stanza, void * const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *id = (char *)userdata;
    xmpp_stanza_t *ptr;
    xmpp_stanza_t *nick;
    char *name;
    char *jid;
    char *autojoin;
    gboolean autojoin_val;
    Jid *my_jid;
    Bookmark *item;

    xmpp_timed_handler_delete(conn, _bookmark_handle_delete);
    g_free(id);

    name = xmpp_stanza_get_name(stanza);
    if (!name || strcmp(name, STANZA_NAME_IQ) != 0) {
        return 0;
    }

    ptr = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
    if (!ptr) {
        return 0;
    }
    ptr = xmpp_stanza_get_child_by_name(ptr, STANZA_NAME_STORAGE);
    if (!ptr) {
        return 0;
    }

    if (bookmark_ac == NULL) {
        bookmark_ac = autocomplete_new();
    }
    my_jid = jid_create(jabber_get_fulljid());

    ptr = xmpp_stanza_get_children(ptr);
    while (ptr) {
        name = xmpp_stanza_get_name(ptr);
        if (!name || strcmp(name, STANZA_NAME_CONFERENCE) != 0) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }
        jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID);
        if (!jid) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }

        log_debug("Handle bookmark for %s", jid);

        name = NULL;
        nick = xmpp_stanza_get_child_by_name(ptr, "nick");
        if (nick) {
            char *tmp;
            tmp = xmpp_stanza_get_text(nick);
            if (tmp) {
                name = strdup(tmp);
                xmpp_free(ctx, tmp);
            }
        }

        autojoin = xmpp_stanza_get_attribute(ptr, "autojoin");
        if (autojoin && (strcmp(autojoin, "1") == 0 || strcmp(autojoin, "true") == 0)) {
            autojoin_val = TRUE;
        } else {
            autojoin_val = FALSE;
        }

        autocomplete_add(bookmark_ac, jid);
        item = malloc(sizeof(*item));
        item->jid = strdup(jid);
        item->nick = name;
        item->autojoin = autojoin_val;
        bookmark_list = g_list_append(bookmark_list, item);


        /* TODO: preference whether autojoin */
        if (autojoin_val) {
            if (autojoin_count < BOOKMARK_AUTOJOIN_MAX) {
                Jid *room_jid;

                ++autojoin_count;

                if (name == NULL) {
                    name = my_jid->localpart;
                }

                log_debug("Autojoin %s with nick=%s", jid, name);
                room_jid = jid_create_from_bare_and_resource(jid, name);
                if (!muc_room_is_active(room_jid)) {
                    presence_join_room(room_jid);
                    /* TODO: this should be removed after fixing #195 */
                    ui_room_join(room_jid);
                }
                jid_destroy(room_jid);
            } else {
                log_debug("Rejected autojoin %s (maximum has been reached)", jid);
            }
        }

        ptr = xmpp_stanza_get_next(ptr);
    }

    jid_destroy(my_jid);

    return 0;
}
Exemplo n.º 6
0
static void
_send_bookmarks(void)
{
    xmpp_conn_t *conn = connection_get_conn();
    xmpp_ctx_t *ctx = connection_get_ctx();

    xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
    char *id = create_unique_id("bookmarks_update");
    xmpp_stanza_set_id(iq, id);
    free(id);
    xmpp_stanza_set_type(iq, STANZA_TYPE_SET);

    xmpp_stanza_t *query = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
    xmpp_stanza_set_ns(query, "jabber:iq:private");

    xmpp_stanza_t *storage = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(storage, STANZA_NAME_STORAGE);
    xmpp_stanza_set_ns(storage, "storage:bookmarks");

    GList *curr = bookmark_list;
    while (curr) {
        Bookmark *bookmark = curr->data;
        xmpp_stanza_t *conference = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(conference, STANZA_NAME_CONFERENCE);
        xmpp_stanza_set_attribute(conference, STANZA_ATTR_JID, bookmark->jid);

        Jid *jidp = jid_create(bookmark->jid);
        if (jidp->localpart) {
            xmpp_stanza_set_attribute(conference, STANZA_ATTR_NAME, jidp->localpart);
        }
        jid_destroy(jidp);

        if (bookmark->autojoin) {
            xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "true");
        } else {
            xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
        }

        if (bookmark->nick) {
            xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
            xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
            xmpp_stanza_t *nick_text = xmpp_stanza_new(ctx);
            xmpp_stanza_set_text(nick_text, bookmark->nick);
            xmpp_stanza_add_child(nick_st, nick_text);
            xmpp_stanza_add_child(conference, nick_st);

            xmpp_stanza_release(nick_text);
            xmpp_stanza_release(nick_st);
        }

        if (bookmark->password) {
            xmpp_stanza_t *password_st = xmpp_stanza_new(ctx);
            xmpp_stanza_set_name(password_st, STANZA_NAME_PASSWORD);
            xmpp_stanza_t *password_text = xmpp_stanza_new(ctx);
            xmpp_stanza_set_text(password_text, bookmark->password);
            xmpp_stanza_add_child(password_st, password_text);
            xmpp_stanza_add_child(conference, password_st);

            xmpp_stanza_release(password_text);
            xmpp_stanza_release(password_st);
        }

        xmpp_stanza_add_child(storage, conference);
        xmpp_stanza_release(conference);

        curr = curr->next;
    }

    xmpp_stanza_add_child(query, storage);
    xmpp_stanza_add_child(iq, query);
    xmpp_stanza_release(storage);
    xmpp_stanza_release(query);

    xmpp_send(conn, iq);
    xmpp_stanza_release(iq);
}
Exemplo n.º 7
0
static int
_bookmark_handle_result(xmpp_conn_t *const conn,
    xmpp_stanza_t *const stanza, void *const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *id = (char *)userdata;
    xmpp_stanza_t *ptr;
    xmpp_stanza_t *nick;
    xmpp_stanza_t *password_st;
    char *name;
    char *jid;
    char *autojoin;
    char *password;
    gboolean autojoin_val;
    Jid *my_jid;
    Bookmark *item;

    xmpp_timed_handler_delete(conn, _bookmark_handle_delete);
    g_free(id);

    name = xmpp_stanza_get_name(stanza);
    if (!name || strcmp(name, STANZA_NAME_IQ) != 0) {
        return 0;
    }

    ptr = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
    if (!ptr) {
        return 0;
    }
    ptr = xmpp_stanza_get_child_by_name(ptr, STANZA_NAME_STORAGE);
    if (!ptr) {
        return 0;
    }

    if (bookmark_ac == NULL) {
        bookmark_ac = autocomplete_new();
    }
    my_jid = jid_create(jabber_get_fulljid());

    ptr = xmpp_stanza_get_children(ptr);
    while (ptr) {
        name = xmpp_stanza_get_name(ptr);
        if (!name || strcmp(name, STANZA_NAME_CONFERENCE) != 0) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }
        jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID);
        if (!jid) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }

        log_debug("Handle bookmark for %s", jid);

        name = NULL;
        nick = xmpp_stanza_get_child_by_name(ptr, "nick");
        if (nick) {
            char *tmp;
            tmp = xmpp_stanza_get_text(nick);
            if (tmp) {
                name = strdup(tmp);
                xmpp_free(ctx, tmp);
            }
        }

        password = NULL;
        password_st = xmpp_stanza_get_child_by_name(ptr, "password");
        if (password_st) {
            char *tmp;
            tmp = xmpp_stanza_get_text(password_st);
            if (tmp) {
                password = strdup(tmp);
                xmpp_free(ctx, tmp);
            }
        }

        autojoin = xmpp_stanza_get_attribute(ptr, "autojoin");
        if (autojoin && (strcmp(autojoin, "1") == 0 || strcmp(autojoin, "true") == 0)) {
            autojoin_val = TRUE;
        } else {
            autojoin_val = FALSE;
        }

        autocomplete_add(bookmark_ac, jid);
        item = malloc(sizeof(*item));
        item->jid = strdup(jid);
        item->nick = name;
        item->password = password;
        item->autojoin = autojoin_val;
        bookmark_list = g_list_append(bookmark_list, item);

        if (autojoin_val) {
            Jid *room_jid;

            char *account_name = jabber_get_account_name();
            ProfAccount *account = accounts_get_account(account_name);
            if (name == NULL) {
                name = account->muc_nick;
            }

            log_debug("Autojoin %s with nick=%s", jid, name);
            room_jid = jid_create_from_bare_and_resource(jid, name);
            if (!muc_active(room_jid->barejid)) {
                presence_join_room(jid, name, password);
                muc_join(jid, name, password, TRUE);
            }
            jid_destroy(room_jid);
            account_free(account);
        }

        ptr = xmpp_stanza_get_next(ptr);
    }

    jid_destroy(my_jid);

    return 0;
}
Exemplo n.º 8
0
static int
_chat_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
{
    // ignore if type not chat or absent
    char *type = xmpp_stanza_get_type(stanza);
    if (!(g_strcmp0(type, "chat") == 0 || type == NULL)) {
        return 1;
    }

    // check if carbon message
    gboolean res = _handle_carbons(stanza);
    if (res) {
        return 1;
    }

    // ignore handled namespaces
    xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
    xmpp_stanza_t *captcha = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CAPTCHA);
    if (conf || captcha) {
        return 1;
    }

    // some clients send the mucuser namespace with private messages
    // if the namespace exists, and the stanza contains a body element, assume its a private message
    // otherwise exit the handler
    xmpp_stanza_t *mucuser = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
    xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
    if (mucuser && body == NULL) {
        return 1;
    }

    gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
    Jid *jid = jid_create(from);

    // private message from chat room use full jid (room/nick)
    if (muc_active(jid->barejid)) {
        _private_chat_handler(stanza, jid->fulljid);
        jid_destroy(jid);
        return 1;
    }

    // standard chat message, use jid without resource
    xmpp_ctx_t *ctx = connection_get_ctx();
    GDateTime *timestamp = stanza_get_delay(stanza);
    if (body) {
        char *message = xmpp_stanza_get_text(body);
        if (message) {
            char *enc_message = NULL;
            xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_ENCRYPTED);
            if (x) {
                enc_message = xmpp_stanza_get_text(x);
            }
            sv_ev_incoming_message(jid->barejid, jid->resourcepart, message, enc_message, timestamp);
            xmpp_free(ctx, enc_message);

            _receipt_request_handler(stanza);

            xmpp_free(ctx, message);
        }
    }

    // handle chat sessions and states
    if (!timestamp && jid->resourcepart) {
        gboolean gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
        gboolean typing = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL;
        gboolean paused = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL;
        gboolean inactive = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL;
        if (gone) {
            sv_ev_gone(jid->barejid, jid->resourcepart);
        } else if (typing) {
            sv_ev_typing(jid->barejid, jid->resourcepart);
        } else if (paused) {
            sv_ev_paused(jid->barejid, jid->resourcepart);
        } else if (inactive) {
            sv_ev_inactive(jid->barejid, jid->resourcepart);
        } else if (stanza_contains_chat_state(stanza)) {
            sv_ev_activity(jid->barejid, jid->resourcepart, TRUE);
        } else {
            sv_ev_activity(jid->barejid, jid->resourcepart, FALSE);
        }
    }

    if (timestamp) g_date_time_unref(timestamp);
    jid_destroy(jid);
    return 1;
}
Exemplo n.º 9
0
static int
_groupchat_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *message = NULL;
    char *room_jid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
    Jid *jid = jid_create(room_jid);

    // handle room subject
    xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT);
    if (subject) {
        message = xmpp_stanza_get_text(subject);
        sv_ev_room_subject(jid->barejid, jid->resourcepart, message);
        xmpp_free(ctx, message);

        jid_destroy(jid);
        return 1;
    }

    // handle room broadcasts
    if (!jid->resourcepart) {
        xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
        if (!body) {
            jid_destroy(jid);
            return 1;
        }

        message = xmpp_stanza_get_text(body);
        if (!message) {
            jid_destroy(jid);
            return 1;
        }

        sv_ev_room_broadcast(room_jid, message);
        xmpp_free(ctx, message);

        jid_destroy(jid);
        return 1;
    }

    if (!jid_is_valid_room_form(jid)) {
        log_error("Invalid room JID: %s", jid->str);
        jid_destroy(jid);
        return 1;
    }

    // room not active in profanity
    if (!muc_active(jid->barejid)) {
        log_error("Message received for inactive chat room: %s", jid->str);
        jid_destroy(jid);
        return 1;
    }

    xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);

    // check for and deal with message
    if (!body) {
        jid_destroy(jid);
        return 1;
    }

    message = xmpp_stanza_get_text(body);
    if (!message) {
        jid_destroy(jid);
        return 1;
    }

    // determine if the notifications happened whilst offline
    GDateTime *timestamp = stanza_get_delay(stanza);
    if (timestamp) {
        sv_ev_room_history(jid->barejid, jid->resourcepart, timestamp, message);
        g_date_time_unref(timestamp);
    } else {
        sv_ev_room_message(jid->barejid, jid->resourcepart, message);
    }

    xmpp_free(ctx, message);
    jid_destroy(jid);

    return 1;
}
Exemplo n.º 10
0
static int
_chat_message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
    void * const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
    Jid *jid = jid_create(from);

    // handle ddg searches
    if (strcmp(jid->barejid, "*****@*****.**") == 0) {
        xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
        if (body != NULL) {
            char *message = xmpp_stanza_get_text(body);
            if (message != NULL) {
                prof_handle_duck_result(message);
                xmpp_free(ctx, message);
            }
        }

        jid_destroy(jid);
        return 1;

    // private message from chat room use full jid (room/nick)
    } else if (muc_room_is_active(jid)) {
        // determine if the notifications happened whilst offline
        GTimeVal tv_stamp;
        gboolean delayed = stanza_get_delay(stanza, &tv_stamp);

        // check for and deal with message
        xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
        if (body != NULL) {
            char *message = xmpp_stanza_get_text(body);
            if (message != NULL) {
                if (delayed) {
                    prof_handle_delayed_message(jid->str, message, tv_stamp, TRUE);
                } else {
                    prof_handle_incoming_message(jid->str, message, TRUE);
                }
                xmpp_free(ctx, message);
            }
        }

        jid_destroy(jid);
        return 1;

    // standard chat message, use jid without resource
    } else {
        // determine chatstate support of recipient
        gboolean recipient_supports = FALSE;
        if (stanza_contains_chat_state(stanza)) {
            recipient_supports = TRUE;
        }

        // create or update chat session
        if (!chat_session_exists(jid->barejid)) {
            chat_session_start(jid->barejid, recipient_supports);
        } else {
            chat_session_set_recipient_supports(jid->barejid, recipient_supports);
        }

        // determine if the notifications happened whilst offline
        GTimeVal tv_stamp;
        gboolean delayed = stanza_get_delay(stanza, &tv_stamp);

        // deal with chat states if recipient supports them
        if (recipient_supports && (!delayed)) {
            if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL) {
                if (prefs_get_boolean(PREF_NOTIFY_TYPING) || prefs_get_boolean(PREF_INTYPE)) {
                    prof_handle_typing(jid->barejid);
                }
            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL) {
                prof_handle_gone(jid->barejid);
            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL) {
                // do something
            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL) {
                // do something
            } else { // handle <active/>
                // do something
            }
        }

        // check for and deal with message
        xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
        if (body != NULL) {
            char *message = xmpp_stanza_get_text(body);
            if (message != NULL) {
                if (delayed) {
                    prof_handle_delayed_message(jid->barejid, message, tv_stamp, FALSE);
                } else {
                    prof_handle_incoming_message(jid->barejid, message, FALSE);
                }
                xmpp_free(ctx, message);
            }
        }

        jid_destroy(jid);
        return 1;
    }
}
Exemplo n.º 11
0
static int
_groupchat_message_handler(xmpp_conn_t * const conn,
    xmpp_stanza_t * const stanza, void * const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *message = NULL;
    char *room_jid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
    Jid *jid = jid_create(room_jid);

    // handle room broadcasts
    if (jid->resourcepart == NULL) {
        xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT);

        // handle subject
        if (subject != NULL) {
            message = xmpp_stanza_get_text(subject);
            if (message != NULL) {
                prof_handle_room_subject(jid->barejid, message);
            }

            jid_destroy(jid);
            return 1;

        // handle other room broadcasts
        } else {
            xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
            if (body != NULL) {
                message = xmpp_stanza_get_text(body);
                if (message != NULL) {
                    prof_handle_room_broadcast(room_jid, message);
                    xmpp_free(ctx, message);
                }
            }

            jid_destroy(jid);
            return 1;
        }
    }


    if (!jid_is_valid_room_form(jid)) {
        log_error("Invalid room JID: %s", jid->str);
        jid_destroy(jid);
        return 1;
    }

    // room not active in profanity
    if (!muc_room_is_active(jid)) {
        log_error("Message recieved for inactive chat room: %s", jid->str);
        jid_destroy(jid);
        return 1;
    }

    // determine if the notifications happened whilst offline
    GTimeVal tv_stamp;
    gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
    xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);

    // check for and deal with message
    if (body != NULL) {
        message = xmpp_stanza_get_text(body);
        if (message != NULL) {
            if (delayed) {
                prof_handle_room_history(jid->barejid, jid->resourcepart, tv_stamp, message);
            } else {
                prof_handle_room_message(jid->barejid, jid->resourcepart, message);
            }
            xmpp_free(ctx, message);
        }
    }

    jid_destroy(jid);

    return 1;
}
Exemplo n.º 12
0
static int
_conference_message_handler(xmpp_conn_t * const conn,
    xmpp_stanza_t * const stanza, void * const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    xmpp_stanza_t *x_muc = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
    xmpp_stanza_t *x_groupchat = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
    xmpp_stanza_t *captcha = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CAPTCHA);
    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
    char *room = NULL;
    char *invitor = NULL;
    char *reason = NULL;

    if (from == NULL) {
        log_warning("Message received with no from attribute, ignoring");
        return 1;
    }

    // XEP-0045
    if (x_muc != NULL) {
        room = from;

        xmpp_stanza_t *invite = xmpp_stanza_get_child_by_name(x_muc, STANZA_NAME_INVITE);
        if (invite == NULL) {
            return 1;
        }

        char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM);
        if (invitor_jid == NULL) {
            log_warning("Chat room invite received with no from attribute");
            return 1;
        }

        Jid *jidp = jid_create(invitor_jid);
        invitor = jidp->barejid;

        xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON);
        if (reason_st != NULL) {
            reason = xmpp_stanza_get_text(reason_st);
        }

        prof_handle_room_invite(INVITE_MEDIATED, invitor, room, reason);
        jid_destroy(jidp);
        if (reason != NULL) {
            xmpp_free(ctx, reason);
        }

    // XEP-0429
    } else if (x_groupchat != NULL) {
        room = xmpp_stanza_get_attribute(x_groupchat, STANZA_ATTR_JID);
        if (room == NULL) {
            return 1;
        }

        Jid *jidp = jid_create(from);
        invitor = jidp->barejid;

        reason = xmpp_stanza_get_attribute(x_groupchat, STANZA_ATTR_REASON);

        prof_handle_room_invite(INVITE_DIRECT, invitor, room, reason);

        jid_destroy(jidp);

    // XEP-0158
    } else if (captcha != NULL) {
        xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
        if (body != NULL) {
            char *message = xmpp_stanza_get_text(body);
            if (message != NULL) {
                prof_handle_room_broadcast(from, message);
                xmpp_free(ctx, message);
            }
        }
    }

    return 1;
}
Exemplo n.º 13
0
xmpp_stanza_t*
form_create_submission(DataForm *form)
{
    xmpp_ctx_t *ctx = connection_get_ctx();

    xmpp_stanza_t *x = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(x, STANZA_NAME_X);
    xmpp_stanza_set_ns(x, STANZA_NS_DATA);
    xmpp_stanza_set_type(x, "submit");

    GSList *curr_field = form->fields;
    while (curr_field) {
        FormField *field = curr_field->data;

        if (field->type_t != FIELD_FIXED) {
            xmpp_stanza_t *field_stanza = xmpp_stanza_new(ctx);
            xmpp_stanza_set_name(field_stanza, "field");
            xmpp_stanza_set_attribute(field_stanza, "var", field->var);

            xmpp_stanza_t *value_stanza = NULL;
            GSList *curr_value = NULL;

            switch (field->type_t) {
                case FIELD_HIDDEN:
                case FIELD_TEXT_SINGLE:
                case FIELD_TEXT_PRIVATE:
                case FIELD_BOOLEAN:
                case FIELD_LIST_SINGLE:
                case FIELD_JID_SINGLE:
                    value_stanza = xmpp_stanza_new(ctx);
                    xmpp_stanza_set_name(value_stanza, "value");
                    if (field->values) {
                        if (field->values->data) {
                            xmpp_stanza_t *text_stanza = xmpp_stanza_new(ctx);
                            xmpp_stanza_set_text(text_stanza, field->values->data);
                            xmpp_stanza_add_child(value_stanza, text_stanza);
                            xmpp_stanza_release(text_stanza);
                        }
                    }
                    xmpp_stanza_add_child(field_stanza, value_stanza);
                    xmpp_stanza_release(value_stanza);

                    break;

                case FIELD_TEXT_MULTI:
                case FIELD_LIST_MULTI:
                case FIELD_JID_MULTI:
                    curr_value = field->values;
                    while (curr_value) {
                        char *value = curr_value->data;

                        value_stanza = xmpp_stanza_new(ctx);
                        xmpp_stanza_set_name(value_stanza, "value");
                        if (value) {
                            xmpp_stanza_t *text_stanza = xmpp_stanza_new(ctx);
                            xmpp_stanza_set_text(text_stanza, value);
                            xmpp_stanza_add_child(value_stanza, text_stanza);
                            xmpp_stanza_release(text_stanza);
                        }

                        xmpp_stanza_add_child(field_stanza, value_stanza);
                        xmpp_stanza_release(value_stanza);

                        curr_value = g_slist_next(curr_value);
                    }
                    break;
                case FIELD_FIXED:
                default:
                    break;
            }

            xmpp_stanza_add_child(x, field_stanza);
            xmpp_stanza_release(field_stanza);
        }

        curr_field = g_slist_next(curr_field);
    }

    return x;
}
Exemplo n.º 14
0
DataForm*
form_create(xmpp_stanza_t *const form_stanza)
{
    xmpp_ctx_t *ctx = connection_get_ctx();

    if (!_is_valid_form_element(form_stanza)) {
        return NULL;
    }

    DataForm *form = _form_new();
    form->type = _get_attr(form_stanza, "type");
    form->title = _get_property(form_stanza, "title");
    form->instructions = _get_property(form_stanza, "instructions");
    form->var_to_tag = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
    form->tag_to_var = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
    form->tag_ac = autocomplete_new();
    form->modified = FALSE;

    int tag_num = 1;

    // get fields
    xmpp_stanza_t *form_child = xmpp_stanza_get_children(form_stanza);
    while (form_child) {
        const char *child_name = xmpp_stanza_get_name(form_child);
        if (g_strcmp0(child_name, "field") == 0) {
            xmpp_stanza_t *field_stanza = form_child;

            FormField *field = _field_new();
            field->label = _get_attr(field_stanza, "label");
            field->type = _get_attr(field_stanza, "type");
            field->type_t = _get_field_type(field->type);
            field->value_ac = autocomplete_new();

            field->var = _get_attr(field_stanza, "var");

            if (field->type_t != FIELD_HIDDEN && field->var) {
                GString *tag = g_string_new("");
                g_string_printf(tag, "field%d", tag_num++);
                g_hash_table_insert(form->var_to_tag, strdup(field->var), strdup(tag->str));
                g_hash_table_insert(form->tag_to_var, strdup(tag->str), strdup(field->var));
                autocomplete_add(form->tag_ac, tag->str);
                g_string_free(tag, TRUE);
            }

            field->description = _get_property(field_stanza, "desc");
            field->required = _is_required(field_stanza);

            // handle repeated field children
            xmpp_stanza_t *field_child = xmpp_stanza_get_children(field_stanza);
            int value_index = 1;
            while (field_child) {
                child_name = xmpp_stanza_get_name(field_child);

                // handle values
                if (g_strcmp0(child_name, "value") == 0) {
                    char *value = xmpp_stanza_get_text(field_child);
                    if (value) {
                        field->values = g_slist_append(field->values, strdup(value));

                        if (field->type_t == FIELD_TEXT_MULTI) {
                            GString *ac_val = g_string_new("");
                            g_string_printf(ac_val, "val%d", value_index++);
                            autocomplete_add(field->value_ac, ac_val->str);
                            g_string_free(ac_val, TRUE);
                        }
                        if (field->type_t == FIELD_JID_MULTI) {
                            autocomplete_add(field->value_ac, value);
                        }

                        xmpp_free(ctx, value);
                    }

                // handle options
                } else if (g_strcmp0(child_name, "option") == 0) {
                    FormOption *option = malloc(sizeof(FormOption));
                    option->label = _get_attr(field_child, "label");
                    option->value = _get_property(field_child, "value");

                    if ((field->type_t == FIELD_LIST_SINGLE) || (field->type_t == FIELD_LIST_MULTI)) {
                        autocomplete_add(field->value_ac, option->value);
                    }

                    field->options = g_slist_append(field->options, option);
                }

                field_child = xmpp_stanza_get_next(field_child);
            }

            form->fields = g_slist_append(form->fields, field);
        }

        form_child = xmpp_stanza_get_next(form_child);
    }

    return form;
}
Exemplo n.º 15
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);
}
Exemplo n.º 16
0
void
presence_send(const resource_presence_t presence_type, const int idle, char *signed_status)
{
    if (connection_get_status() != JABBER_CONNECTED) {
        log_warning("Error setting presence, not connected.");
        return;
    }

    char *msg = connection_get_presence_msg();
    if (msg) {
        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));
    }

    const int pri = accounts_get_priority_for_presence_type(session_get_account_name(), presence_type);
    connection_set_priority(pri);

    xmpp_ctx_t * const ctx = connection_get_ctx();
    xmpp_stanza_t *presence = xmpp_presence_new(ctx);

    char *id = create_unique_id("presence");
    xmpp_stanza_set_id(presence, id);
    free(id);

    const char *show = stanza_get_presence_string_from_type(presence_type);
    stanza_attach_show(ctx, presence, show);

    stanza_attach_status(ctx, presence, msg);

    if (signed_status) {
        xmpp_stanza_t *x = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(x, STANZA_NAME_X);
        xmpp_stanza_set_ns(x, STANZA_NS_SIGNED);

        xmpp_stanza_t *signed_text = xmpp_stanza_new(ctx);
        xmpp_stanza_set_text(signed_text, signed_status);

        xmpp_stanza_add_child(x, signed_text);
        xmpp_stanza_release(signed_text);

        xmpp_stanza_add_child(presence, x);
        xmpp_stanza_release(x);
    }

    stanza_attach_priority(ctx, presence, pri);

    if (idle > 0) {
        stanza_attach_last_activity(ctx, presence, idle);
    }

    stanza_attach_caps(ctx, presence);

    _send_presence_stanza(presence);
    _send_room_presence(presence);

    xmpp_stanza_release(presence);

    // set last presence for account
    const char *last = show;
    if (last == NULL) {
        last = STANZA_TEXT_ONLINE;
    }

    char *account = session_get_account_name();
    accounts_set_last_presence(account, last);
    accounts_set_last_status(account, msg);
}