about summary refs log tree commit diff stats
path: root/src/xmpp/capabilities.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp/capabilities.c')
-rw-r--r--src/xmpp/capabilities.c93
1 files changed, 72 insertions, 21 deletions
diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c
index 1d6907b8..cbacae9b 100644
--- a/src/xmpp/capabilities.c
+++ b/src/xmpp/capabilities.c
@@ -55,14 +55,17 @@
 static gchar *cache_loc;
 static GKeyFile *cache;
 
-static GHashTable *jid_lookup;
+static GHashTable *jid_to_ver;
+static GHashTable *jid_to_caps;
 
 static char *my_sha1;
 
 static void _caps_destroy(Capabilities *caps);
 static gchar* _get_cache_file(void);
 static void _save_cache(void);
-static Capabilities * _caps_get(const char * const caps_str);
+static Capabilities * _caps_by_ver(const char * const ver);
+static Capabilities * _caps_by_jid(const char * const jid);
+Capabilities * _caps_copy(Capabilities *caps);
 
 void
 caps_init(void)
@@ -78,13 +81,14 @@ caps_init(void)
     g_key_file_load_from_file(cache, cache_loc, G_KEY_FILE_KEEP_COMMENTS,
         NULL);
 
-    jid_lookup = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+    jid_to_ver = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+    jid_to_caps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_caps_destroy);
 
     my_sha1 = NULL;
 }
 
 void
-caps_add(const char * const ver, Capabilities *caps)
+caps_add_by_ver(const char * const ver, Capabilities *caps)
 {
     gboolean cached = g_key_file_has_group(cache, ver);
     if (!cached) {
@@ -126,66 +130,72 @@ caps_add(const char * const ver, Capabilities *caps)
 }
 
 void
-caps_map(const char * const jid, const char * const ver)
+caps_add_by_jid(const char * const jid, Capabilities *caps)
 {
-    g_hash_table_insert(jid_lookup, strdup(jid), strdup(ver));
+    g_hash_table_insert(jid_to_caps, strdup(jid), caps);
+}
+
+void
+caps_map_jid_to_ver(const char * const jid, const char * const ver)
+{
+    g_hash_table_insert(jid_to_ver, strdup(jid), strdup(ver));
 }
 
 gboolean
-caps_contains(const char * const caps_ver)
+caps_contains(const char * const ver)
 {
-    return (g_key_file_has_group(cache, caps_ver));
+    return (g_key_file_has_group(cache, ver));
 }
 
 static Capabilities *
-_caps_get(const char * const caps_str)
+_caps_by_ver(const char * const ver)
 {
-    if (g_key_file_has_group(cache, caps_str)) {
+    if (g_key_file_has_group(cache, ver)) {
         Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
 
-        char *category = g_key_file_get_string(cache, caps_str, "category", NULL);
+        char *category = g_key_file_get_string(cache, ver, "category", NULL);
         if (category) {
             new_caps->category = strdup(category);
         } else {
             new_caps->category = NULL;
         }
 
-        char *type = g_key_file_get_string(cache, caps_str, "type", NULL);
+        char *type = g_key_file_get_string(cache, ver, "type", NULL);
         if (type) {
             new_caps->type = strdup(type);
         } else {
             new_caps->type = NULL;
         }
 
-        char *name = g_key_file_get_string(cache, caps_str, "name", NULL);
+        char *name = g_key_file_get_string(cache, ver, "name", NULL);
         if (name) {
             new_caps->name = strdup(name);
         } else {
             new_caps->name = NULL;
         }
 
-        char *software = g_key_file_get_string(cache, caps_str, "software", NULL);
+        char *software = g_key_file_get_string(cache, ver, "software", NULL);
         if (software) {
             new_caps->software = strdup(software);
         } else {
             new_caps->software = NULL;
         }
 
-        char *software_version = g_key_file_get_string(cache, caps_str, "software_version", NULL);
+        char *software_version = g_key_file_get_string(cache, ver, "software_version", NULL);
         if (software_version) {
             new_caps->software_version = strdup(software_version);
         } else {
             new_caps->software_version = NULL;
         }
 
-        char *os = g_key_file_get_string(cache, caps_str, "os", NULL);
+        char *os = g_key_file_get_string(cache, ver, "os", NULL);
         if (os) {
             new_caps->os = strdup(os);
         } else {
             new_caps->os = NULL;
         }
 
-        char *os_version = g_key_file_get_string(cache, caps_str, "os_version", NULL);
+        char *os_version = g_key_file_get_string(cache, ver, "os_version", NULL);
         if (os_version) {
             new_caps->os_version = strdup(os_version);
         } else {
@@ -193,7 +203,7 @@ _caps_get(const char * const caps_str)
         }
 
         gsize features_len = 0;
-        gchar **features = g_key_file_get_string_list(cache, caps_str, "features", &features_len, NULL);
+        gchar **features = g_key_file_get_string_list(cache, ver, "features", &features_len, NULL);
         if (features != NULL && features_len > 0) {
             GSList *features_list = NULL;
             int i;
@@ -212,19 +222,59 @@ _caps_get(const char * const caps_str)
 }
 
 static Capabilities *
+_caps_by_jid(const char * const jid)
+{
+    return g_hash_table_lookup(jid_to_caps, jid);
+}
+
+static Capabilities *
 _caps_lookup(const char * const jid)
 {
-    char *ver = g_hash_table_lookup(jid_lookup, jid);
+    char *ver = g_hash_table_lookup(jid_to_ver, jid);
     if (ver) {
-        Capabilities *caps = _caps_get(ver);
+        Capabilities *caps = _caps_by_ver(ver);
         if (caps) {
+            log_debug("Capabilities lookup %s, found by verification string %s.", jid, ver);
             return caps;
         }
+    } else {
+        Capabilities *caps = _caps_by_jid(jid);
+        if (caps) {
+            log_debug("Capabilities lookup %s, found by JID.", jid);
+            return _caps_copy(caps);
+        }
     }
 
+    log_debug("Capabilities lookup %s, none found.", jid);
     return NULL;
 }
 
+Capabilities *
+_caps_copy(Capabilities *caps)
+{
+    if (!caps) {
+        return NULL;
+    } else {
+        Capabilities *result = (Capabilities *)malloc(sizeof(Capabilities));
+        result->category = caps->category ? strdup(caps->category) : NULL;
+        result->type = caps->type ? strdup(caps->type) : NULL;
+        result->name = caps->name ? strdup(caps->name) : NULL;
+        result->software = caps->software ? strdup(caps->software) : NULL;
+        result->software_version = caps->software_version ? strdup(caps->software_version) : NULL;
+        result->os = caps->os ? strdup(caps->os) : NULL;
+        result->os_version = caps->os_version ? strdup(caps->os_version) : NULL;
+
+        result->features = NULL;
+        GSList *curr = caps->features;
+        while (curr) {
+            result->features = g_slist_append(result->features, strdup(curr->data));
+            curr = g_slist_next(curr);
+        }
+
+        return result;
+    }
+}
+
 char *
 caps_create_sha1_str(xmpp_stanza_t * const query)
 {
@@ -579,7 +629,8 @@ _caps_close(void)
 {
     g_key_file_free(cache);
     cache = NULL;
-    g_hash_table_destroy(jid_lookup);
+    g_hash_table_destroy(jid_to_ver);
+    g_hash_table_destroy(jid_to_caps);
 }
 
 static void