diff options
author | James Booth <boothj5@gmail.com> | 2013-01-21 02:18:03 +0000 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2013-01-21 02:18:03 +0000 |
commit | df790e247cb9573add96e39b49162ad20a47534e (patch) | |
tree | 40a2a58613cebe5c12c00c755d59bb03d3603095 | |
parent | 97a497c355a4a80be1dc6e31c41dc587c6dda629 (diff) | |
download | profani-tty-df790e247cb9573add96e39b49162ad20a47534e.tar.gz |
Respond to iq requests for capabilities
-rw-r--r-- | src/jabber.c | 122 | ||||
-rw-r--r-- | src/stanza.c | 28 | ||||
-rw-r--r-- | src/stanza.h | 2 |
3 files changed, 145 insertions, 7 deletions
diff --git a/src/jabber.c b/src/jabber.c index 31eaa854..a8440a30 100644 --- a/src/jabber.c +++ b/src/jabber.c @@ -39,8 +39,6 @@ #include "muc.h" #include "stanza.h" -#include "ui.h" - static struct _jabber_conn_t { xmpp_log_t *log; xmpp_ctx_t *ctx; @@ -88,7 +86,9 @@ static int _iq_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _roster_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); -static int _disco_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, +static int _disco_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, + void * const userdata); +static int _disco_request_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); @@ -548,6 +548,51 @@ jabber_update_presence(jabber_presence_t status, const char * const msg, xmpp_stanza_add_child(presence, query); } + // add caps + xmpp_stanza_t *caps = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(caps, STANZA_NAME_C); + xmpp_stanza_set_ns(caps, STANZA_NS_CAPS); + xmpp_stanza_set_attribute(caps, STANZA_ATTR_HASH, "sha-1"); + xmpp_stanza_set_attribute(caps, STANZA_ATTR_NODE, "http://www.profanity.im"); + + xmpp_stanza_t *query = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, XMPP_NS_DISCO_INFO); + + xmpp_stanza_t *identity = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(identity, "identity"); + xmpp_stanza_set_attribute(identity, "category", "client"); + xmpp_stanza_set_attribute(identity, "type", "pc"); + + GString *name_str = g_string_new("Profanity "); + g_string_append(name_str, PACKAGE_VERSION); + if (strcmp(PACKAGE_STATUS, "development") == 0) { + g_string_append(name_str, "dev"); + } + xmpp_stanza_set_attribute(identity, "name", name_str->str); + + xmpp_stanza_t *feature_caps = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(feature_caps, STANZA_NAME_FEATURE); + xmpp_stanza_set_attribute(feature_caps, STANZA_ATTR_VAR, STANZA_NS_CAPS); + + xmpp_stanza_t *feature_disoinfo = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(feature_disoinfo, STANZA_NAME_FEATURE); + xmpp_stanza_set_attribute(feature_disoinfo, STANZA_ATTR_VAR, XMPP_NS_DISCO_INFO); + + xmpp_stanza_t *feature_muc = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(feature_muc, STANZA_NAME_FEATURE); + xmpp_stanza_set_attribute(feature_muc, STANZA_ATTR_VAR, STANZA_NS_MUC); + + xmpp_stanza_add_child(query, identity); + xmpp_stanza_add_child(query, feature_muc); + xmpp_stanza_add_child(query, feature_disoinfo); + xmpp_stanza_add_child(query, feature_caps); + + char *sha1 = sha1_caps_str(query); + xmpp_stanza_set_attribute(caps, STANZA_ATTR_VER, sha1); + + xmpp_stanza_add_child(presence, caps); + xmpp_send(jabber_conn.conn, presence); // send presence for each room @@ -923,9 +968,13 @@ _iq_handler(xmpp_conn_t * const conn, if (g_strcmp0(id, "roster") == 0) { return _roster_handler(conn, stanza, userdata); - // handle diso requests + // handle disco responses } else if ((g_str_has_prefix(id, "disco")) && (g_strcmp0(type, "result") == 0)) { - return _disco_handler(conn, stanza, userdata); + return _disco_response_handler(conn, stanza, userdata); + + // handle disco requests + } else if (stanza_is_caps_request(stanza)) { + return _disco_request_handler(conn, stanza, userdata); // handle iq } else { @@ -1060,7 +1109,67 @@ _roster_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, } static int -_disco_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, +_disco_request_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 *incoming_query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); + char *node_str = xmpp_stanza_get_attribute(incoming_query, STANZA_ATTR_NODE); + char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); + + if (from != NULL) { + xmpp_stanza_t *response = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(response, STANZA_NAME_IQ); + xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza)); + xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from); + xmpp_stanza_set_type(response, STANZA_TYPE_RESULT); + + xmpp_stanza_t *query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, XMPP_NS_DISCO_INFO); + xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, node_str); + + xmpp_stanza_t *identity = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(identity, "identity"); + xmpp_stanza_set_attribute(identity, "category", "client"); + xmpp_stanza_set_attribute(identity, "type", "pc"); + + GString *name_str = g_string_new("Profanity "); + g_string_append(name_str, PACKAGE_VERSION); + if (strcmp(PACKAGE_STATUS, "development") == 0) { + g_string_append(name_str, "dev"); + } + xmpp_stanza_set_attribute(identity, "name", name_str->str); + + xmpp_stanza_t *feature_caps = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(feature_caps, STANZA_NAME_FEATURE); + xmpp_stanza_set_attribute(feature_caps, STANZA_ATTR_VAR, STANZA_NS_CAPS); + + xmpp_stanza_t *feature_disoinfo = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(feature_disoinfo, STANZA_NAME_FEATURE); + xmpp_stanza_set_attribute(feature_disoinfo, STANZA_ATTR_VAR, XMPP_NS_DISCO_INFO); + + xmpp_stanza_t *feature_muc = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(feature_muc, STANZA_NAME_FEATURE); + xmpp_stanza_set_attribute(feature_muc, STANZA_ATTR_VAR, STANZA_NS_MUC); + + xmpp_stanza_add_child(query, identity); + + xmpp_stanza_add_child(query, feature_muc); + xmpp_stanza_add_child(query, feature_disoinfo); + xmpp_stanza_add_child(query, feature_caps); + + xmpp_stanza_add_child(response, query); + + xmpp_send(conn, response); + } + + return 1; +} + +static int +_disco_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *type = xmpp_stanza_get_type(stanza); @@ -1094,7 +1203,6 @@ _disco_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, // non supported hash, or legacy caps } else { caps_key = id + 6; - cons_show(caps_key); } // already cached diff --git a/src/stanza.c b/src/stanza.c index 4274ed22..dd71d277 100644 --- a/src/stanza.c +++ b/src/stanza.c @@ -431,6 +431,34 @@ stanza_contains_caps(xmpp_stanza_t * const stanza) return TRUE; } +gboolean +stanza_is_caps_request(xmpp_stanza_t * const stanza) +{ + char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); + + if (g_strcmp0(type, STANZA_TYPE_GET) != 0) { + return FALSE; + } + + xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); + + if (query == NULL) { + return FALSE; + } + + char *ns = xmpp_stanza_get_ns(query); + + if (ns == NULL) { + return FALSE; + } + + if (strcmp(ns, XMPP_NS_DISCO_INFO) != 0) { + return FALSE; + } + + return TRUE; +} + char * stanza_caps_get_hash(xmpp_stanza_t * const stanza) { diff --git a/src/stanza.h b/src/stanza.h index a61f4639..f75906bd 100644 --- a/src/stanza.h +++ b/src/stanza.h @@ -77,6 +77,7 @@ #define STANZA_ATTR_SECONDS "seconds" #define STANZA_ATTR_NODE "node" #define STANZA_ATTR_VER "ver" +#define STANZA_ATTR_VAR "var" #define STANZA_ATTR_HASH "hash" #define STANZA_TEXT_AWAY "away" @@ -141,6 +142,7 @@ int stanza_get_idle_time(xmpp_stanza_t * const stanza); char * stanza_get_caps_str(xmpp_stanza_t * const stanza); gboolean stanza_contains_caps(xmpp_stanza_t * const stanza); char * stanza_caps_get_hash(xmpp_stanza_t * const stanza); +gboolean stanza_is_caps_request(xmpp_stanza_t * const stanza); DataForm * stanza_get_form(xmpp_stanza_t * const stanza); |