about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/jid.c14
-rw-r--r--src/jid.h2
-rw-r--r--src/xmpp/presence.c73
-rw-r--r--src/xmpp/stanza.c86
-rw-r--r--src/xmpp/stanza.h13
-rw-r--r--tests/test_jid.c18
-rw-r--r--tests/test_jid.h2
-rw-r--r--tests/testsuite.c2
8 files changed, 111 insertions, 99 deletions
diff --git a/src/jid.c b/src/jid.c
index 8e3813bc..690f36ca 100644
--- a/src/jid.c
+++ b/src/jid.c
@@ -176,3 +176,17 @@ get_nick_from_full_jid(const char * const full_room_jid)
 
     return nick_part;
 }
+
+
+/*
+ * get the fulljid, fall back to the barejid
+ */
+char *
+jid_fulljid_or_barejid(Jid *jid)
+{
+    if (jid->fulljid) {
+        return jid->fulljid;
+    } else {
+        return jid->barejid;
+    }
+}
\ No newline at end of file
diff --git a/src/jid.h b/src/jid.h
index 39a4585a..64c147f9 100644
--- a/src/jid.h
+++ b/src/jid.h
@@ -56,4 +56,6 @@ gboolean jid_is_valid_room_form(Jid *jid);
 char * create_fulljid(const char * const barejid, const char * const resource);
 char * get_nick_from_full_jid(const char * const full_room_jid);
 
+char * jid_fulljid_or_barejid(Jid *jid);
+
 #endif
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c
index 389540e8..963815a8 100644
--- a/src/xmpp/presence.c
+++ b/src/xmpp/presence.c
@@ -500,43 +500,30 @@ _unavailable_handler(xmpp_conn_t * const conn,
 }
 
 static void
-_handle_caps(xmpp_stanza_t *const stanza)
+_handle_caps(char *jid, XMPPCaps *caps)
 {
-    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
-
-    if (from) {
-        char *hash = stanza_caps_get_hash(stanza);
-
-        // hash supported xep-0115
-        if (g_strcmp0(hash, "sha-1") == 0) {
-            log_info("Hash %s supported");
-
-            char *ver = stanza_get_caps_ver(stanza);
-            if (ver) {
-                if (caps_contains(ver)) {
-                    log_info("Capabilities cached: %s", ver);
-                    caps_map(from, ver);
-                } else {
-                    log_info("Capabilities not cached: %s, sending service discovery request", ver);
-                    char *node = stanza_caps_get_node(stanza);
-                    char *id = create_unique_id("caps");
-
-                    iq_send_caps_request(from, id, node, ver);
-
-                    free(id);
-                }
-            }
-
-        // no hash, or not supported
-        } else {
-            if (hash) {
-                log_info("Hash %s not supported, not sending service discovery request");
-                // send service discovery request, cache against from full jid
+    // hash supported xep-0115
+    if (g_strcmp0(caps->hash, "sha-1") == 0) {
+        log_info("Hash %s supported", caps->hash);
+        if (caps->ver) {
+            if (caps_contains(caps->ver)) {
+                log_info("Capabilities cached: %s", caps->ver);
+                caps_map(jid, caps->ver);
             } else {
-                log_info("No hash specified, not sending service discovery request");
-                // do legacy
+                log_info("Capabilities not cached: %s, sending service discovery request", caps->ver);
+                char *id = create_unique_id("caps");
+                iq_send_caps_request(jid, id, caps->node, caps->ver);
+                free(id);
             }
         }
+
+    // no hash, or not supported
+    } else if (caps->hash) {
+        log_info("Hash %s not supported, not sending service discovery request", caps->hash);
+        // send service discovery request, cache against from full jid
+    } else {
+        log_info("No hash specified, not sending service discovery request");
+        // do legacy
     }
 }
 
@@ -580,18 +567,21 @@ _available_handler(xmpp_conn_t * const conn,
                 break;
         }
         return 1;
-    } else if (xmpp_presence->jid->fulljid) {
-        log_debug("Presence available handler fired for: %s", xmpp_presence->jid->fulljid);
     } else {
-        log_debug("Presence available handler fired for: %s", xmpp_presence->jid->barejid);
+        char *jid = jid_fulljid_or_barejid(xmpp_presence->jid);
+        log_debug("Presence available handler fired for: %s", jid);
     }
 
     const char *my_jid_str = xmpp_conn_get_jid(conn);
     Jid *my_jid = jid_create(my_jid_str);
-    if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && (stanza_contains_caps(stanza))) {
+
+    XMPPCaps *caps = stanza_parse_caps(stanza);
+    if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && caps) {
         log_info("Presence contains capabilities.");
-        _handle_caps(stanza);
+        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);
 
@@ -627,6 +617,7 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
         log_debug("No node string, not sending discovery IQ.");
     }
 }
+
 static int
 _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
 {
@@ -757,10 +748,12 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
         // room occupant online
         } else {
             // send disco info for capabilities, if not cached
-            if (stanza_contains_caps(stanza)) {
+            XMPPCaps *caps = stanza_parse_caps(stanza);
+            if (caps) {
                 log_info("Presence contains capabilities.");
-                _handle_caps(stanza);
+                _handle_caps(from, caps);
             }
+            stanza_free_caps(caps);
 
             char *actor = stanza_get_actor(stanza);
             char *reason = stanza_get_reason(stanza);
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index e0943b1f..1766fe26 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -1313,72 +1313,30 @@ stanza_get_idle_time(xmpp_stanza_t * const stanza)
     }
 }
 
-gboolean
-stanza_contains_caps(xmpp_stanza_t * const stanza)
-{
-    xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
-
-    if (!caps) {
-        return FALSE;
-    }
-
-    char *ns = xmpp_stanza_get_ns(caps);
-    if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-char *
-stanza_caps_get_hash(xmpp_stanza_t * const stanza)
+XMPPCaps*
+stanza_parse_caps(xmpp_stanza_t * const stanza)
 {
-    xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
+    xmpp_stanza_t *caps_st = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
 
-    if (!caps) {
+    if (!caps_st) {
         return NULL;
     }
 
-    char *ns = xmpp_stanza_get_ns(caps);
+    char *ns = xmpp_stanza_get_ns(caps_st);
     if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
         return NULL;
     }
 
-    return xmpp_stanza_get_attribute(caps, STANZA_ATTR_HASH);
-}
-
-char *
-stanza_caps_get_node(xmpp_stanza_t * const stanza)
-{
-    xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
+    char *hash = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_HASH);
+    char *node = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_NODE);
+    char *ver = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_VER);
 
-    if (!caps) {
-        return NULL;
-    }
+    XMPPCaps *caps = (XMPPCaps *)malloc(sizeof(XMPPCaps));
+    caps->hash = hash ? strdup(hash) : NULL;
+    caps->node = node ? strdup(node) : NULL;
+    caps->ver = ver ? strdup(ver) : NULL;
 
-    char *ns = xmpp_stanza_get_ns(caps);
-    if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
-        return NULL;
-    }
-
-    return xmpp_stanza_get_attribute(caps, STANZA_ATTR_NODE);
-}
-
-char *
-stanza_get_caps_ver(xmpp_stanza_t * const stanza)
-{
-    xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C);
-
-    if (!caps) {
-        return NULL;
-    }
-
-    char *ns = xmpp_stanza_get_ns(caps);
-    if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) {
-        return NULL;
-    }
-
-    return xmpp_stanza_get_attribute(caps, STANZA_ATTR_VER);
+    return caps;
 }
 
 char *
@@ -1594,6 +1552,23 @@ stanza_resource_from_presence(XMPPPresence *presence)
 }
 
 void
+stanza_free_caps(XMPPCaps *caps)
+{
+    if (caps) {
+        if (caps->hash) {
+            free(caps->hash);
+        }
+        if (caps->node) {
+            free(caps->node);
+        }
+        if (caps->ver) {
+            free(caps->ver);
+        }
+        FREE_SET_NULL(caps);
+    }
+}
+
+void
 stanza_free_presence(XMPPPresence *presence)
 {
     if (presence) {
@@ -1609,6 +1584,7 @@ stanza_free_presence(XMPPPresence *presence)
         if (presence->status) {
             free(presence->status);
         }
+        FREE_SET_NULL(presence);
     }
 }
 
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index d6a3b042..e60e9fe1 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -157,6 +157,12 @@
 
 #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
 
+typedef struct caps_stanza_t {
+    char *hash;
+    char *node;
+    char *ver;
+} XMPPCaps;
+
 typedef struct presence_stanza_t {
     Jid *jid;
     char *show;
@@ -233,10 +239,6 @@ xmpp_stanza_t* stanza_create_room_kick_iq(xmpp_ctx_t * const ctx, const char * c
 
 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);
-char * stanza_get_caps_ver(xmpp_stanza_t * const stanza);
-char * stanza_caps_get_node(xmpp_stanza_t * const stanza);
 
 DataForm * stanza_create_form(xmpp_stanza_t * const stanza);
 void stanza_destroy_form(DataForm *form);
@@ -278,4 +280,7 @@ Resource* stanza_resource_from_presence(XMPPPresence *presence);
 XMPPPresence* stanza_parse_presence(xmpp_stanza_t *stanza, int *err);
 void stanza_free_presence(XMPPPresence *presence);
 
+XMPPCaps* stanza_parse_caps(xmpp_stanza_t * const stanza);
+void stanza_free_caps(XMPPCaps *caps);
+
 #endif
diff --git a/tests/test_jid.c b/tests/test_jid.c
index df8096d1..ff5f4c9a 100644
--- a/tests/test_jid.c
+++ b/tests/test_jid.c
@@ -165,3 +165,21 @@ void create_full_with_trailing_slash(void **state)
     assert_string_equal("room@conference.domain.org", result->barejid);
     assert_string_equal("room@conference.domain.org/nick/", result->fulljid);
 }
+
+void returns_fulljid_when_exists(void **state)
+{
+    Jid *jid = jid_create("localpart@domainpart/resourcepart");
+
+    char *result = jid_fulljid_or_barejid(jid);
+
+    assert_string_equal("localpart@domainpart/resourcepart", result);
+}
+
+void returns_barejid_when_fulljid_not_exists(void **state)
+{
+    Jid *jid = jid_create("localpart@domainpart");
+
+    char *result = jid_fulljid_or_barejid(jid);
+
+    assert_string_equal("localpart@domainpart", result);
+}
\ No newline at end of file
diff --git a/tests/test_jid.h b/tests/test_jid.h
index 95de541f..9b96d0b8 100644
--- a/tests/test_jid.h
+++ b/tests/test_jid.h
@@ -21,3 +21,5 @@ void create_with_slash_in_resource(void **state);
 void create_with_at_in_resource(void **state);
 void create_with_at_and_slash_in_resource(void **state);
 void create_full_with_trailing_slash(void **state);
+void returns_fulljid_when_exists(void **state);
+void returns_barejid_when_fulljid_not_exists(void **state);
diff --git a/tests/testsuite.c b/tests/testsuite.c
index ad6dc219..4273add5 100644
--- a/tests/testsuite.c
+++ b/tests/testsuite.c
@@ -131,6 +131,8 @@ int main(int argc, char* argv[]) {
         unit_test(create_with_at_in_resource),
         unit_test(create_with_at_and_slash_in_resource),
         unit_test(create_full_with_trailing_slash),
+        unit_test(returns_fulljid_when_exists),
+        unit_test(returns_barejid_when_fulljid_not_exists),
 
         unit_test(parse_null_returns_null),
         unit_test(parse_empty_returns_null),