about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/command/command.c37
-rw-r--r--src/profanity.c14
-rw-r--r--src/profanity.h1
-rw-r--r--src/xmpp/iq.c51
-rw-r--r--src/xmpp/stanza.c20
-rw-r--r--src/xmpp/stanza.h2
-rw-r--r--src/xmpp/xmpp.h1
7 files changed, 126 insertions, 0 deletions
diff --git a/src/command/command.c b/src/command/command.c
index fd8747d9..b5f8fe40 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -101,6 +101,7 @@ static gboolean _cmd_tiny(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_close(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_clear(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_join(gchar **args, struct cmd_help_t help);
+static gboolean _cmd_rooms(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_set_beep(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_set_notify(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_set_log(gchar **args, struct cmd_help_t help);
@@ -334,6 +335,19 @@ static struct cmd_t main_commands[] =
           "Example : /join jdev@conference.jabber.org mynick",
           NULL } } },
 
+    { "/rooms",
+        _cmd_rooms, parse_args, 0, 1,
+        { "/rooms [conference-node]", "List chat rooms.",
+        { "/rooms [conference-node]",
+          "------------------------",
+          "List the chat rooms available at the specified conference node",
+          "If no argument is supplied, the domainpart of the current logged in JID is used,",
+          "with a prefix of 'conference'.",
+          "",
+          "Example : /rooms conference.jabber.org",
+          "Example : /rooms (if logged in as me@server.org, is equivalent to /rooms conference.server.org)",
+          NULL } } },
+
     { "/nick",
         _cmd_nick, parse_args_with_freetext, 1, 1,
         { "/nick nickname", "Change nickname in chat room.",
@@ -2058,6 +2072,29 @@ _cmd_join(gchar **args, struct cmd_help_t help)
 }
 
 static gboolean
+_cmd_rooms(gchar **args, struct cmd_help_t help)
+{
+    jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are currenlty connect.");
+        return TRUE;
+    }
+
+    if (args[0] == NULL) {
+        Jid *jid = jid_create(jabber_get_jid());
+        GString *conference_node = g_string_new("conference.");
+        g_string_append(conference_node, jid->domainpart);
+        iq_room_list_request(conference_node->str);
+        g_string_free(conference_node, TRUE);
+    } else {
+        iq_room_list_request(args[0]);
+    }
+
+    return TRUE;
+}
+
+static gboolean
 _cmd_nick(gchar **args, struct cmd_help_t help)
 {
     jabber_conn_status_t conn_status = jabber_get_connection_status();
diff --git a/src/profanity.c b/src/profanity.c
index 71ff971e..a91a80d1 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -401,6 +401,20 @@ prof_handle_version_result(const char * const jid, const char * const  presence,
     win_current_page_off();
 }
 
+void
+prof_handle_room_list(GSList *rooms, const char *conference_node)
+{
+    if ((rooms != NULL) && (g_slist_length(rooms) > 0)) {
+        cons_show("Chat rooms at %s:", conference_node);
+        while (rooms != NULL) {
+            cons_show("  %s", rooms->data);
+            rooms = g_slist_next(rooms);
+        }
+    } else {
+        cons_show("No chat rooms at %s", conference_node);
+    }
+}
+
 /*
  * 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 5363670c..851cb2d3 100644
--- a/src/profanity.h
+++ b/src/profanity.h
@@ -71,5 +71,6 @@ void prof_handle_activity(void);
 void prof_handle_version_result(const char * const jid,
     const char * const presence, const char * const name,
     const char * const version, const char * const os);
+void prof_handle_room_list(GSList *rooms, const char *conference_node);
 
 #endif
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index c587d918..67db8d22 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -39,6 +39,8 @@
 #include "xmpp/stanza.h"
 #include "xmpp/xmpp.h"
 
+#include "ui/ui.h"
+
 #define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_IQ, type, ctx)
 
 static int _iq_handle_error(xmpp_conn_t * const conn,
@@ -57,6 +59,8 @@ static int _iq_handle_discoinfo_result(xmpp_conn_t * const conn,
     xmpp_stanza_t * const stanza, void * const userdata);
 static int _iq_handle_version_result(xmpp_conn_t * const conn,
     xmpp_stanza_t * const stanza, void * const userdata);
+static int _iq_handle_discoitems_result(xmpp_conn_t * const conn,
+    xmpp_stanza_t * const stanza, void * const userdata);
 
 void
 iq_add_handlers(void)
@@ -68,6 +72,7 @@ iq_add_handlers(void)
     HANDLE(XMPP_NS_ROSTER,      STANZA_TYPE_RESULT, _iq_handle_roster_result);
     HANDLE(XMPP_NS_DISCO_INFO,  STANZA_TYPE_GET,    _iq_handle_discoinfo_get);
     HANDLE(XMPP_NS_DISCO_INFO,  STANZA_TYPE_RESULT, _iq_handle_discoinfo_result);
+    HANDLE(XMPP_NS_DISCO_ITEMS, STANZA_TYPE_RESULT, _iq_handle_discoitems_result);
     HANDLE(STANZA_NS_VERSION,   STANZA_TYPE_GET,    _iq_handle_version_get);
     HANDLE(STANZA_NS_VERSION,   STANZA_TYPE_RESULT, _iq_handle_version_result);
     HANDLE(STANZA_NS_PING,      STANZA_TYPE_GET,    _iq_handle_ping_get);
@@ -84,6 +89,16 @@ iq_roster_request(void)
 }
 
 void
+iq_room_list_request(gchar *conferencejid)
+{
+    xmpp_conn_t * const conn = connection_get_conn();
+    xmpp_ctx_t * const ctx = connection_get_ctx();
+    xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, "confreq", conferencejid);
+    xmpp_send(conn, iq);
+    xmpp_stanza_release(iq);
+}
+
+void
 iq_send_software_version(const char * const fulljid)
 {
     xmpp_conn_t * const conn = connection_get_conn();
@@ -448,3 +463,39 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
         return 1;
     }
 }
+
+static int
+_iq_handle_discoitems_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
+    void * const userdata)
+{
+    GSList *rooms = NULL;
+
+    log_debug("Recieved diso#items response");
+    const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
+    const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+
+    if ((id != NULL) && (g_strcmp0(id, "confreq") == 0)) {
+        log_debug("Response to query: %s", id);
+
+        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 *name = xmpp_stanza_get_name(child);
+                if ((name != NULL) && (g_strcmp0(name, STANZA_NAME_ITEM) == 0)) {
+                    const char *jid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID);
+                    if (jid != NULL) {
+                       rooms = g_slist_append(rooms, strdup(jid));
+                    }
+                }
+
+                child = xmpp_stanza_get_next(child);
+            }
+        }
+    }
+
+    prof_handle_room_list(rooms, from);
+    g_slist_free_full(rooms, free);
+
+    return 1;
+}
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 4ee3badd..34f9d784 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -198,6 +198,26 @@ stanza_create_disco_iq(xmpp_ctx_t *ctx, const char * const id, const char * cons
     return iq;
 }
 
+xmpp_stanza_t *
+stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char * const id,
+    const char * const jid)
+{
+    xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
+    xmpp_stanza_set_type(iq, STANZA_TYPE_GET);
+    xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, jid);
+    xmpp_stanza_set_id(iq, id);
+
+    xmpp_stanza_t *query = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
+    xmpp_stanza_set_ns(query, XMPP_NS_DISCO_ITEMS);
+
+    xmpp_stanza_add_child(iq, query);
+    xmpp_stanza_release(query);
+
+    return iq;
+}
+
 gboolean
 stanza_contains_chat_state(xmpp_stanza_t *stanza)
 {
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index d07568a7..18f9b045 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -163,5 +163,7 @@ void stanza_attach_status(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence
 
 const char * stanza_get_presence_string_from_type(resource_presence_t presence_type);
 xmpp_stanza_t * stanza_create_software_version_iq(xmpp_ctx_t *ctx, const char * const fulljid);
+xmpp_stanza_t * stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char * const id,
+    const char * const jid);
 
 #endif
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 5efbdf00..ba8c1a2f 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -92,6 +92,7 @@ void presence_update(resource_presence_t status, const char * const msg,
 
 // iq functions
 void iq_send_software_version(const char * const fulljid);
+void iq_room_list_request(gchar *conferencejid);
 
 // caps functions
 Capabilities* caps_get(const char * const caps_str);