about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2013-02-17 01:04:10 +0000
committerJames Booth <boothj5@gmail.com>2013-02-17 01:04:10 +0000
commit44d2f8da7a235997049bac68fea746682ae49e9f (patch)
tree084d2440cdb88815e532e5e6c526d04611bde8a0
parentab591b41b2535f454d35d7524c454dccea1b2cc5 (diff)
downloadprofani-tty-44d2f8da7a235997049bac68fea746682ae49e9f.tar.gz
Added /caps command
-rw-r--r--src/command/command.c78
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/ui/windows.c30
-rw-r--r--src/xmpp/capabilities.c12
-rw-r--r--src/xmpp/capabilities.h2
-rw-r--r--src/xmpp/iq.c12
-rw-r--r--src/xmpp/xmpp.h1
7 files changed, 130 insertions, 6 deletions
diff --git a/src/command/command.c b/src/command/command.c
index 648ab64c..58868334 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -125,6 +125,7 @@ static gboolean _cmd_dnd(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_chat(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_xa(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_info(gchar **args, struct cmd_help_t help);
+static gboolean _cmd_caps(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_wins(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_nick(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_theme(gchar **args, struct cmd_help_t help);
@@ -268,6 +269,16 @@ static struct cmd_t main_commands[] =
           "If in a chat window the parameter is not required, the current recipient will be used.",
           NULL } } },
 
+    { "/caps",
+        _cmd_caps, parse_args, 0, 1,
+        { "/caps [jid|nick]", "Find out a contacts client capabilities.",
+        { "/caps [jid|nick]",
+          "----------------",
+          "Find out a contact, or room members client capabilities.",
+          "If in a chat window the parameter is not required, the current recipient will be used.",
+          "The command output is similar to the /info command, but shows the capabilities of each available resource.",
+          NULL } } },
+
     { "/status",
         _cmd_status, parse_args, 0, 1,
         { "/status [jid|nick]", "Find out a contacts presence information.",
@@ -964,6 +975,7 @@ _cmd_complete_parameters(char *input, int *size)
         if (nick_ac != NULL) {
             _parameter_autocomplete_with_ac(input, size, "/msg", nick_ac);
             _parameter_autocomplete_with_ac(input, size, "/info", nick_ac);
+            _parameter_autocomplete_with_ac(input, size, "/caps", nick_ac);
             _parameter_autocomplete_with_ac(input, size, "/status", nick_ac);
         }
     } else {
@@ -971,6 +983,8 @@ _cmd_complete_parameters(char *input, int *size)
             contact_list_find_contact);
         _parameter_autocomplete(input, size, "/info",
             contact_list_find_contact);
+        _parameter_autocomplete(input, size, "/caps",
+            contact_list_find_contact);
         _parameter_autocomplete(input, size, "/status",
             contact_list_find_contact);
     }
@@ -1861,6 +1875,70 @@ _cmd_info(gchar **args, struct cmd_help_t help)
 }
 
 static gboolean
+_cmd_caps(gchar **args, struct cmd_help_t help)
+{
+    char *usr = args[0];
+
+    jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are not currently connected.");
+    } else {
+        if (win_current_is_groupchat()) {
+            if (usr != NULL) {
+                PContact pcontact = muc_get_participant(win_current_get_recipient(), usr);
+                if (pcontact != NULL) {
+                    cons_show_caps(pcontact);
+                } else {
+                    cons_show("No such participant \"%s\" in room.", usr);
+                }
+            } else {
+                cons_show("No nickname supplied to /info in chat room.");
+            }
+
+        } else if (win_current_is_chat()) {
+            if (usr != NULL) {
+                cons_show("No parameter required for /info in chat.");
+            } else {
+                PContact pcontact = contact_list_get_contact(win_current_get_recipient());
+                if (pcontact != NULL) {
+                    cons_show_caps(pcontact);
+                } else {
+                    cons_show("No such contact \"%s\" in roster.", win_current_get_recipient());
+                }
+            }
+
+        } else if (win_current_is_private()) {
+            if (usr != NULL) {
+                win_current_show("No parameter required when in chat.");
+            } else {
+                Jid *jid = jid_create(win_current_get_recipient());
+                PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart);
+                if (pcontact != NULL) {
+                    cons_show_caps(pcontact);
+                } else {
+                    cons_show("No such participant \"%s\" in room.", jid->resourcepart);
+                }
+                jid_destroy(jid);
+            }
+        } else {
+            if (usr != NULL) {
+                PContact pcontact = contact_list_get_contact(usr);
+                if (pcontact != NULL) {
+                    cons_show_caps(pcontact);
+                } else {
+                    cons_show("No such contact \"%s\" in roster.", usr);
+                }
+            } else {
+                cons_show("Usage: %s", help.usage);
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+static gboolean
 _cmd_join(gchar **args, struct cmd_help_t help)
 {
     jabber_conn_status_t conn_status = jabber_get_connection_status();
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 80139cc1..378cea69 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -165,6 +165,7 @@ void cons_check_version(gboolean not_available_msg);
 void cons_show_wins(void);
 void cons_show_status(const char * const contact);
 void cons_show_info(PContact pcontact);
+void cons_show_caps(PContact pcontact);
 void cons_show_themes(GSList *themes);
 void cons_show_login_success(ProfAccount *account);
 
diff --git a/src/ui/windows.c b/src/ui/windows.c
index d23257ba..a7bf5eec 100644
--- a/src/ui/windows.c
+++ b/src/ui/windows.c
@@ -103,7 +103,7 @@ static void _win_resize_all(void);
 static gint _win_get_unread(void);
 static void _win_show_history(WINDOW *win, int win_index,
     const char * const contact);
-static void _win_show_info(WINDOW *win, PContact pcontact);
+static void _win_show_info(WINDOW *win, PContact pcontact, gboolean show_caps);
 static gboolean _new_release(char *found_version);
 static void _ui_draw_win_title(void);
 static void _presence_colour_on(WINDOW *win, const char * const presence);
@@ -1184,7 +1184,19 @@ cons_show_wins(void)
 void
 cons_show_info(PContact pcontact)
 {
-    _win_show_info(console->win, pcontact);
+    _win_show_info(console->win, pcontact, FALSE);
+
+    if (current_index == 0) {
+        dirty = TRUE;
+    } else {
+        status_bar_new(0);
+    }
+}
+
+void
+cons_show_caps(PContact pcontact)
+{
+    _win_show_info(console->win, pcontact, TRUE);
 
     if (current_index == 0) {
         dirty = TRUE;
@@ -2400,7 +2412,7 @@ _win_show_history(WINDOW *win, int win_index, const char * const contact)
 }
 
 static void
-_win_show_info(WINDOW *win, PContact pcontact)
+_win_show_info(WINDOW *win, PContact pcontact, gboolean show_caps)
 {
     const char *barejid = p_contact_barejid(pcontact);
     const char *name = p_contact_name(pcontact);
@@ -2520,6 +2532,18 @@ _win_show_info(WINDOW *win, PContact pcontact)
                 if ((caps->os != NULL) || (caps->os_version != NULL)) {
                     wprintw(win, "\n");
                 }
+
+                if (show_caps && caps->features != NULL) {
+                    _win_show_time(win, '-');
+                    wprintw(win, "    Features:\n");
+                    GSList *feature = caps->features;
+                    while (feature != NULL) {
+                        _win_show_time(win, '-');
+                        wprintw(win, "      %s\n", feature->data);
+                        feature = g_slist_next(feature);
+                    }
+                }
+
             }
         }
 
diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c
index e8e45b97..a5d99633 100644
--- a/src/xmpp/capabilities.c
+++ b/src/xmpp/capabilities.c
@@ -48,7 +48,8 @@ void
 caps_add(const char * const caps_str, const char * const category,
     const char * const type, const char * const name,
     const char * const software, const char * const software_version,
-    const char * const os, const char * const os_version)
+    const char * const os, const char * const os_version,
+    GSList *features)
 {
     Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
 
@@ -87,6 +88,11 @@ caps_add(const char * const caps_str, const char * const category,
     } else {
         new_caps->os_version = NULL;
     }
+    if (features != NULL) {
+        new_caps->features = features;
+    } else {
+        new_caps->features = NULL;
+    }
 
     g_hash_table_insert(capabilities, strdup(caps_str), new_caps);
 }
@@ -284,6 +290,10 @@ _caps_destroy(Capabilities *caps)
         FREE_SET_NULL(caps->software_version);
         FREE_SET_NULL(caps->os);
         FREE_SET_NULL(caps->os_version);
+        if (caps->features != NULL) {
+            g_slist_free_full(caps->features, free);
+            caps->features = NULL;
+        }
         FREE_SET_NULL(caps);
     }
 }
diff --git a/src/xmpp/capabilities.h b/src/xmpp/capabilities.h
index f2729adc..d97b84b2 100644
--- a/src/xmpp/capabilities.h
+++ b/src/xmpp/capabilities.h
@@ -31,7 +31,7 @@ void caps_init(void);
 void caps_add(const char * const caps_str, const char * const category,
     const char * const type, const char * const name,
     const char * const software, const char * const software_version,
-    const char * const os, const char * const os_version);
+    const char * const os, const char * const os_version, GSList *features);
 gboolean caps_contains(const char * const caps_str);
 char* caps_create_sha1_str(xmpp_stanza_t * const query);
 xmpp_stanza_t* caps_create_query_response_stanza(xmpp_ctx_t * const ctx);
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index 9d0b43e9..070fefba 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -324,6 +324,7 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
         const char *software_version = NULL;
         const char *os = NULL;
         const char *os_version = NULL;
+        GSList *features = NULL;
 
         xmpp_stanza_t *identity = xmpp_stanza_get_child_by_name(query, "identity");
         if (identity != NULL) {
@@ -356,8 +357,17 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
             }
         }
 
+        xmpp_stanza_t *child = xmpp_stanza_get_children(query);
+        while (child != NULL) {
+            if (g_strcmp0(xmpp_stanza_get_name(child), "feature") == 0) {
+                features = g_slist_append(features, strdup(xmpp_stanza_get_attribute(child, "var")));
+            }
+
+            child = xmpp_stanza_get_next(child);
+        }
+
         caps_add(caps_key, category, type, name, software, software_version,
-            os, os_version);
+            os, os_version, features);
 
         //stanza_destroy_form(form);
         free(caps_key);
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 2b5cce92..5edd253e 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -54,6 +54,7 @@ typedef struct capabilities_t {
     char *software_version;
     char *os;
     char *os_version;
+    GSList *features;
 } Capabilities;
 
 // connection functions