コード例 #1
0
int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
    xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;
    xmpp_stanza_t *reply;
    char *intext, *replytext;

    if (!xmpp_stanza_get_child_by_name(stanza, "body"))
        return 1;
    if (xmpp_stanza_get_type(stanza) != NULL && !strcmp(xmpp_stanza_get_type(stanza), "error"))
        return 1;

    intext = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body"));

    printf("Incoming message from %s: %s\n", xmpp_stanza_get_from(stanza), intext);

    reply = xmpp_stanza_reply(stanza);
    if (xmpp_stanza_get_type(reply) == NULL)
        xmpp_stanza_set_type(reply, "chat");

    replytext = (char *) malloc(strlen(" to you too!") + strlen(intext) + 1);
    strcpy(replytext, intext);
    strcat(replytext, " to you too!");
    xmpp_free(ctx, intext);
    xmpp_message_set_body(reply, replytext);

    xmpp_send(conn, reply);
    xmpp_stanza_release(reply);
    free(replytext);
    return 1;
}
コード例 #2
0
ファイル: stanza.c プロジェクト: apophys/libstrophe
/** Create a stanza object in reply to another.
 *  This function makes a copy of a stanza object with the attribute “to” set
 *  its original “from”.
 *  The stanza will have a reference count of one, so the caller does not
 *  need to clone it.
 *
 *  @param stanza a Strophe stanza object
 *
 *  @return a new Strophe stanza object
 *
 *  @ingroup Stanza
 */
xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza)
{
    xmpp_stanza_t *copy = NULL;
    const char *from;
    int rc;

    from = xmpp_stanza_get_from(stanza);
    if (!from) goto copy_error;

    copy = xmpp_stanza_new(stanza->ctx);
    if (!copy) goto copy_error;

    copy->type = stanza->type;

    if (stanza->data) {
        copy->data = xmpp_strdup(stanza->ctx, stanza->data);
        if (!copy->data) goto copy_error;
    }

    if (stanza->attributes) {
        if (_stanza_copy_attributes(copy, stanza) < 0)
            goto copy_error;
    }

    xmpp_stanza_del_attribute(copy, "to");
    xmpp_stanza_del_attribute(copy, "from");
    rc = xmpp_stanza_set_to(copy, from);
    if (rc != XMPP_EOK) goto copy_error;

    return copy;

copy_error:
    if (copy) xmpp_stanza_release(copy);
    return NULL;
}
コード例 #3
0
ファイル: stanza.c プロジェクト: 1Project/SafeBoardMessenger
/** Create a stanza object in reply to another.
 *  This function makes a copy of a stanza object with the attribute “to” set
 *  its original “from”.
 *  The stanza will have a reference count of one, so the caller does not
 *  need to clone it.
 *
 *  @param stanza a Strophe stanza object
 *
 *  @return a new Strophe stanza object
 *
 *  @ingroup Stanza
 */
xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza)
{
    xmpp_stanza_t *copy;

    copy = xmpp_stanza_new(stanza->ctx);
    if (!copy) goto copy_error;

    copy->type = stanza->type;

    if (stanza->data) {
        copy->data = xmpp_strdup(stanza->ctx, stanza->data);
        if (!copy->data) goto copy_error;
    }

    if (stanza->attributes) {
        if (_stanza_copy_attributes(copy, stanza) == -1)
            goto copy_error;
    }

    xmpp_stanza_set_to(copy, xmpp_stanza_get_from(stanza));
    xmpp_stanza_del_attribute(copy, "from");

    return copy;

copy_error:
    if (copy) xmpp_stanza_release(copy);
    return NULL;
}
コード例 #4
0
ファイル: presence.c プロジェクト: anossov/profanity
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);
    }
}
コード例 #5
0
ファイル: presence.c プロジェクト: anossov/profanity
static void
_subscribed_handler(xmpp_stanza_t *const stanza)
{
    const char *from = xmpp_stanza_get_from(stanza);
    if (!from) {
        log_warning("Subscribed presence handler received with no from attribute");
        return;
    }
    log_debug("Subscribed presence handler fired for %s", from);

    Jid *from_jid = jid_create(from);
    sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED);
    autocomplete_remove(sub_requests_ac, from_jid->barejid);

    jid_destroy(from_jid);
}
コード例 #6
0
int version_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
    xmpp_stanza_t *reply, *query, *name, *version, *text;
    const char *ns;
    xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;

    printf("Received version request from %s\n", xmpp_stanza_get_from(stanza));

    reply = xmpp_stanza_reply(stanza);
    xmpp_stanza_set_type(reply, "result");

    query = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(query, "query");
    ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza));
    if (ns) {
        xmpp_stanza_set_ns(query, ns);
    }

    name = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(name, "name");
    xmpp_stanza_add_child(query, name);
    xmpp_stanza_release(name);

    text = xmpp_stanza_new(ctx);
    xmpp_stanza_set_text(text, "libstrophe example bot");
    xmpp_stanza_add_child(name, text);
    xmpp_stanza_release(text);

    version = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(version, "version");
    xmpp_stanza_add_child(query, version);
    xmpp_stanza_release(version);

    text = xmpp_stanza_new(ctx);
    xmpp_stanza_set_text(text, "1.0");
    xmpp_stanza_add_child(version, text);
    xmpp_stanza_release(text);

    xmpp_stanza_add_child(reply, query);
    xmpp_stanza_release(query);

    xmpp_send(conn, reply);
    xmpp_stanza_release(reply);
    return 1;
}
コード例 #7
0
ファイル: presence.c プロジェクト: anossov/profanity
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);
}
コード例 #8
0
ファイル: presence.c プロジェクト: anossov/profanity
static void
_muc_user_occupant_handler(xmpp_stanza_t *stanza)
{
    const char *from = xmpp_stanza_get_from(stanza);
    Jid *from_jid = jid_create(from);

    log_debug("Room presence received from %s", from_jid->fulljid);

    char *room = from_jid->barejid;
    char *nick = from_jid->resourcepart;
    char *status_str = stanza_get_status(stanza, NULL);

    const char *type = xmpp_stanza_get_type(stanza);
    if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) {

        // handle nickname change
        const char *new_nick = stanza_get_new_nick(stanza);
        if (new_nick) {
            muc_occupant_nick_change_start(room, new_nick, nick);

        // handle left room
        } else {
            GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER);

            // kicked from room
            if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) {
                const char *actor = stanza_get_actor(stanza);
                char *reason = stanza_get_reason(stanza);
                sv_ev_room_occupent_kicked(room, nick, actor, reason);
                free(reason);

            // banned from room
            } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) {
                const char *actor = stanza_get_actor(stanza);
                char *reason = stanza_get_reason(stanza);
                sv_ev_room_occupent_banned(room, nick, actor, reason);
                free(reason);

            // normal exit
            } else {
                sv_ev_room_occupant_offline(room, nick, "offline", status_str);
            }

            g_slist_free_full(status_codes, free);
        }

    // room occupant online
    } else {
        // send disco info for capabilities, if not cached
        XMPPCaps *caps = stanza_parse_caps(stanza);
        if (caps) {
            log_info("Presence contains capabilities.");
            _handle_caps(from, caps);
        }
        stanza_free_caps(caps);

        const char *actor = stanza_get_actor(stanza);
        char *show_str = stanza_get_show(stanza, "online");
        char *reason = stanza_get_reason(stanza);
        const char *jid = NULL;
        const char *role = NULL;
        const char *affiliation = NULL;
        xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
        if (x) {
            xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
            if (item) {
                jid = xmpp_stanza_get_attribute(item, "jid");
                role = xmpp_stanza_get_attribute(item, "role");
                affiliation = xmpp_stanza_get_attribute(item, "affiliation");
            }
        }
        sv_ev_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str);
        free(show_str);
        free(reason);
    }

    jid_destroy(from_jid);
    free(status_str);
}
コード例 #9
0
ファイル: presence.c プロジェクト: anossov/profanity
static void
_muc_user_self_handler(xmpp_stanza_t *stanza)
{
    const char *from = xmpp_stanza_get_from(stanza);
    Jid *from_jid = jid_create(from);

    log_debug("Room self presence received from %s", from_jid->fulljid);

    char *room = from_jid->barejid;

    const char *type = xmpp_stanza_get_type(stanza);
    if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) {

        // handle nickname change
        const char *new_nick = stanza_get_new_nick(stanza);
        if (new_nick) {
            muc_nick_change_start(room, new_nick);

        // handle left room
        } else {
            GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER);

            // room destroyed
            if (stanza_room_destroyed(stanza)) {
                const char *new_jid = stanza_get_muc_destroy_alternative_room(stanza);
                char *password = stanza_get_muc_destroy_alternative_password(stanza);
                char *reason = stanza_get_muc_destroy_reason(stanza);
                sv_ev_room_destroyed(room, new_jid, password, reason);
                free(password);
                free(reason);

            // kicked from room
            } else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) {
                const char *actor = stanza_get_actor(stanza);
                char *reason = stanza_get_reason(stanza);
                sv_ev_room_kicked(room, actor, reason);
                free(reason);

            // banned from room
            } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) {
                const char *actor = stanza_get_actor(stanza);
                char *reason = stanza_get_reason(stanza);
                sv_ev_room_banned(room, actor, reason);
                free(reason);

            // normal exit
            } else {
                sv_ev_leave_room(room);
            }

            g_slist_free_full(status_codes, free);
        }
    } else {
        gboolean config_required = stanza_muc_requires_config(stanza);
        const char *actor = stanza_get_actor(stanza);
        char *reason = stanza_get_reason(stanza);
        char *nick = from_jid->resourcepart;
        char *show_str = stanza_get_show(stanza, "online");
        char *status_str = stanza_get_status(stanza, NULL);
        const char *jid = NULL;
        const char *role = NULL;
        const char *affiliation = NULL;
        xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
        if (x) {
            xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
            if (item) {
                jid = xmpp_stanza_get_attribute(item, "jid");
                role = xmpp_stanza_get_attribute(item, "role");
                affiliation = xmpp_stanza_get_attribute(item, "affiliation");
            }
        }
        sv_ev_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str);
        free(show_str);
        free(status_str);
        free(reason);
    }

    jid_destroy(from_jid);
}
コード例 #10
0
ファイル: presence.c プロジェクト: anossov/profanity
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);
}
コード例 #11
0
ファイル: presence.c プロジェクト: anossov/profanity
static void
_presence_error_handler(xmpp_stanza_t *const stanza)
{
    const char *xmlns = NULL;
    xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
    if (x) {
        xmlns = xmpp_stanza_get_ns(x);
    }

    const char *from = xmpp_stanza_get_from(stanza);
    xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);

    // handle MUC join errors
    if (g_strcmp0(xmlns, STANZA_NS_MUC) == 0) {
        const char *error_cond = NULL;
        xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS);
        if (reason_st) {
            error_cond = xmpp_stanza_get_name(reason_st);
        }
        if (error_cond == NULL) {
            error_cond = "unknown";
        }

        Jid *fulljid = jid_create(from);
        log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond);
        if (muc_active(fulljid->barejid)) {
            muc_leave(fulljid->barejid);
        }
        cons_show_error("Error joining room %s, reason: %s", fulljid->barejid, error_cond);
        jid_destroy(fulljid);

        return;
    }

    GString *log_msg = g_string_new("presence stanza error received");
    const char *id = xmpp_stanza_get_id(stanza);
    if (id) {
        g_string_append(log_msg, " id=");
        g_string_append(log_msg, id);
    }
    if (from) {
        g_string_append(log_msg, " from=");
        g_string_append(log_msg, from);
    }

    const char *type = NULL;
    if (error_stanza) {
        type = xmpp_stanza_get_type(error_stanza);
    }
    if (type) {
        g_string_append(log_msg, " type=");
        g_string_append(log_msg, type);
    }

    // stanza_get_error never returns NULL
    char *err_msg = stanza_get_error_message(stanza);
    g_string_append(log_msg, " error=");
    g_string_append(log_msg, err_msg);

    log_info(log_msg->str);

    g_string_free(log_msg, TRUE);

    if (from) {
        ui_handle_recipient_error(from, err_msg);
    } else {
        ui_handle_error(err_msg);
    }

    free(err_msg);
}