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.", @@ -2057,6 +2071,29 @@ _cmd_join(gchar **args, struct cmd_help_t help) return TRUE; } +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) { 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); @@ -83,6 +88,16 @@ iq_roster_request(void) xmpp_stanza_release(iq); } +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) { @@ -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);