about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/profanity.c7
-rw-r--r--src/profanity.h2
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/ui/windows.c39
-rw-r--r--src/xmpp/iq.c74
-rw-r--r--src/xmpp/stanza.h1
-rw-r--r--src/xmpp/xmpp.h6
7 files changed, 128 insertions, 2 deletions
diff --git a/src/profanity.c b/src/profanity.c
index ffa883f5..db354e29 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -415,6 +415,13 @@ prof_handle_disco_items(GSList *items, const char *jid)
     win_current_page_off();
 }
 
+void
+prof_handle_disco_info(const char *from, GSList *identities, GSList *features)
+{
+    cons_show_disco_info(from, identities, features);
+    win_current_page_off();
+}
+
 /*
  * Take a line of input and process it, return TRUE if profanity is to
  * continue, FALSE otherwise
diff --git a/src/profanity.h b/src/profanity.h
index bbf6e8c1..f55426b8 100644
--- a/src/profanity.h
+++ b/src/profanity.h
@@ -73,5 +73,7 @@ void prof_handle_version_result(const char * const jid,
     const char * const version, const char * const os);
 void prof_handle_room_list(GSList *rooms, const char *conference_node);
 void prof_handle_disco_items(GSList *items, const char *jid);
+void prof_handle_disco_info(const char *from, GSList *identities,
+    GSList *features);
 
 #endif
diff --git a/src/ui/ui.h b/src/ui/ui.h
index d9c9e473..73aa5855 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -175,6 +175,7 @@ void cons_show_software_version(const char * const jid,
 void cons_show_account_list(gchar **accounts);
 void cons_show_room_list(GSList *room, const char * const conference_node);
 void cons_show_disco_items(GSList *items, const char * const jid);
+void cons_show_disco_info(const char *from, GSList *identities, GSList *features);
 
 // status bar actions
 void status_bar_refresh(void);
diff --git a/src/ui/windows.c b/src/ui/windows.c
index b20dbeef..591bc737 100644
--- a/src/ui/windows.c
+++ b/src/ui/windows.c
@@ -1324,6 +1324,45 @@ cons_show_room_list(GSList *rooms, const char * const conference_node)
 }
 
 void
+cons_show_disco_info(const char *jid, GSList *identities, GSList *features)
+{
+    if (((identities != NULL) && (g_slist_length(identities) > 0)) ||
+        ((features != NULL) && (g_slist_length(features) > 0))) {
+        cons_show("Service disovery info for %s", jid);
+
+        if (identities != NULL) {
+            cons_show("  Identities");
+        }
+        while (identities != NULL) {
+            DiscoIdentity *identity = identities->data;  // anme trpe, cat
+            GString *identity_str = g_string_new("    ");
+            if (identity->name != NULL) {
+                identity_str = g_string_append(identity_str, strdup(identity->name));
+                identity_str = g_string_append(identity_str, " ");
+            }
+            if (identity->type != NULL) {
+                identity_str = g_string_append(identity_str, strdup(identity->type));
+                identity_str = g_string_append(identity_str, " ");
+            }
+            if (identity->category != NULL) {
+                identity_str = g_string_append(identity_str, strdup(identity->category));
+            }
+            cons_show(identity_str->str);
+            g_string_free(identity_str, FALSE);
+            identities = g_slist_next(identities);
+        }
+
+        if (features != NULL) {
+            cons_show("  Features:");
+        }
+        while (features != NULL) {
+            cons_show("    %s", features->data);
+            features = g_slist_next(features);
+        }
+    }
+}
+
+void
 cons_show_disco_items(GSList *items, const char * const jid)
 {
     if ((items != NULL) && (g_slist_length(items) > 0)) {
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index fbd1b360..4cbcf374 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -366,15 +366,85 @@ _iq_handle_discoinfo_get(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
     return 1;
 }
 
+static void
+_identity_destroy(DiscoIdentity *identity)
+{
+    if (identity != NULL) {
+        FREE_SET_NULL(identity->name);
+        FREE_SET_NULL(identity->type);
+        FREE_SET_NULL(identity->category);
+        FREE_SET_NULL(identity);
+    }
+}
+
+static void
+_item_destroy(DiscoItem *item)
+{
+    if (item != NULL) {
+        FREE_SET_NULL(item->jid);
+        FREE_SET_NULL(item->name);
+        FREE_SET_NULL(item);
+    }
+}
+
 static int
 _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
     void * const userdata)
 {
     log_debug("Recieved diso#info response");
     const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
+    const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
 
     if (g_strcmp0(id, "discoinforeq") == 0) {
-        cons_show("GOT DISO INFO RESULT");
+        GSList *identities = NULL;
+        GSList *features = NULL;
+
+        xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
+
+        if (query != NULL) {
+            xmpp_stanza_t *child = xmpp_stanza_get_children(query);
+            while (child != NULL) {
+                const char *stanza_name = xmpp_stanza_get_name(child);
+                if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
+                    const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
+                    if (var != NULL) {
+                        features = g_slist_append(features, strdup(var));
+                    }
+                } else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) {
+                    const char *name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
+                    const char *type = xmpp_stanza_get_attribute(child, STANZA_ATTR_TYPE);
+                    const char *category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY);
+
+                    if ((name != NULL) || (category != NULL) || (type != NULL)) {
+                        DiscoIdentity *identity = malloc(sizeof(struct disco_identity_t));
+
+                        if (name != NULL) {
+                            identity->name = strdup(name);
+                        } else {
+                            identity->name = NULL;
+                        }
+                        if (category != NULL) {
+                            identity->category = strdup(category);
+                        } else {
+                            identity->category = NULL;
+                        }
+                        if (type != NULL) {
+                            identity->type = strdup(type);
+                        } else {
+                            identity->type = NULL;
+                        }
+
+                        identities = g_slist_append(identities, identity);
+                    }
+                }
+
+                child = xmpp_stanza_get_next(child);
+            }
+
+            prof_handle_disco_info(from, identities, features);
+            g_slist_free_full(features, free);
+            g_slist_free_full(identities, (GDestroyNotify)_identity_destroy);
+        }
     } else if ((id != NULL) && (g_str_has_prefix(id, "disco"))) {
         log_debug("Response to query: %s", id);
         xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
@@ -531,7 +601,7 @@ _iq_handle_discoitems_result(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
         prof_handle_disco_items(items, from);
     }
 
-    g_slist_free_full(items, free);
+    g_slist_free_full(items, (GDestroyNotify)_item_destroy);
 
     return 1;
 }
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index d6fb777a..e92d3186 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -78,6 +78,7 @@
 #define STANZA_ATTR_VER "ver"
 #define STANZA_ATTR_VAR "var"
 #define STANZA_ATTR_HASH "hash"
+#define STANZA_ATTR_CATEGORY "category"
 
 #define STANZA_TEXT_AWAY "away"
 #define STANZA_TEXT_DND "dnd"
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index eb3c3c09..4a1e0b15 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -62,6 +62,12 @@ typedef struct disco_item_t {
     char *name;
 } DiscoItem;
 
+typedef struct disco_identity_t {
+    char *name;
+    char *type;
+    char *category;
+} DiscoIdentity;
+
 // connection functions
 void jabber_init(const int disable_tls);
 jabber_conn_status_t jabber_connect_with_details(const char * const jid,