about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2013-01-21 02:18:03 +0000
committerJames Booth <boothj5@gmail.com>2013-01-21 02:18:03 +0000
commitdf790e247cb9573add96e39b49162ad20a47534e (patch)
tree40a2a58613cebe5c12c00c755d59bb03d3603095 /src
parent97a497c355a4a80be1dc6e31c41dc587c6dda629 (diff)
downloadprofani-tty-df790e247cb9573add96e39b49162ad20a47534e.tar.gz
Respond to iq requests for capabilities
Diffstat (limited to 'src')
-rw-r--r--src/jabber.c122
-rw-r--r--src/stanza.c28
-rw-r--r--src/stanza.h2
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);