diff --git a/src/command/command.c b/src/command/command.c index d88414e1..a2b280e3 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -277,7 +277,6 @@ static struct cmd_t main_commands[] = "----------------", "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 } } }, { "/software", @@ -995,7 +994,7 @@ _cmd_complete_parameters(char *input, int *size) _parameter_autocomplete(input, size, "/info", contact_list_find_contact); _parameter_autocomplete(input, size, "/caps", - contact_list_find_contact); + contact_list_find_resource); _parameter_autocomplete(input, size, "/status", contact_list_find_contact); _parameter_autocomplete(input, size, "/software", @@ -1890,60 +1889,45 @@ _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 (args[0] != NULL) { + PContact pcontact = muc_get_participant(win_current_get_recipient(), args[0]); if (pcontact != NULL) { - cons_show_caps(pcontact); + Resource *resource = p_contact_get_resource(pcontact, args[0]); + cons_show_caps(args[0], resource); } else { - cons_show("No such participant \"%s\" in room.", usr); + cons_show("No such participant \"%s\" in room.", args[0]); } } else { - cons_show("No nickname supplied to /info in chat room."); + cons_show("No nickname supplied to /caps in chat room."); } + } else if (win_current_is_chat() || win_current_is_console()) { + if (args[0] != NULL) { + Jid *jid = jid_create(args[0]); - } 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); + if (jid->fulljid == NULL) { + cons_show("You must provide a full jid to the /caps command."); } else { - cons_show("No such contact \"%s\" in roster.", win_current_get_recipient()); + PContact pcontact = contact_list_get_contact(jid->barejid); + Resource *resource = p_contact_get_resource(pcontact, jid->resourcepart); + cons_show_caps(jid->fulljid, resource); } + } else { + cons_show("You must provide a jid to the /caps command."); } - - } else if (win_current_is_private()) { - if (usr != NULL) { - win_current_show("No parameter required when in chat."); + } else { // private chat + if (args[0] != NULL) { + cons_show("No parameter needed to /caps when in private 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); + Resource *resource = p_contact_get_resource(pcontact, jid->resourcepart); + cons_show_caps(jid->resourcepart, resource); } } } @@ -1951,6 +1935,7 @@ _cmd_caps(gchar **args, struct cmd_help_t help) return TRUE; } + static gboolean _cmd_software(gchar **args, struct cmd_help_t help) { diff --git a/src/contact.c b/src/contact.c index b63ff408..6a8dc7d3 100644 --- a/src/contact.c +++ b/src/contact.c @@ -223,6 +223,12 @@ p_contact_subscription(const PContact contact) return contact->subscription; } +Resource * +p_contact_get_resource(const PContact contact, const char * const resource) +{ + return g_hash_table_lookup(contact->available_resources, resource); +} + gboolean p_contact_pending_out(const PContact contact) { diff --git a/src/contact.h b/src/contact.h index beba5725..13b97043 100644 --- a/src/contact.h +++ b/src/contact.h @@ -50,5 +50,6 @@ void p_contact_set_pending_out(const PContact contact, gboolean pending_out); void p_contact_set_last_activity(const PContact contact, GDateTime *last_activity); gboolean p_contact_is_available(const PContact contact); gboolean p_contact_has_available_resource(const PContact contact); +Resource * p_contact_get_resource(const PContact contact, const char * const resource); #endif diff --git a/src/profanity.c b/src/profanity.c index 39eb228b..8b6b560a 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -394,10 +394,10 @@ prof_handle_activity(void) } void -prof_handle_version_result(const char * const jid, const char * const name, - const char * const version, const char * const os) +prof_handle_version_result(const char * const jid, const char * const presence, + const char * const name, const char * const version, const char * const os) { - cons_show_software_version(jid, name, version, os); + cons_show_software_version(jid, presence, name, version, os); win_current_page_off(); } diff --git a/src/profanity.h b/src/profanity.h index 177b4e91..5363670c 100644 --- a/src/profanity.h +++ b/src/profanity.h @@ -68,7 +68,8 @@ void prof_handle_room_broadcast(const char *const room_jid, const char * const message); void prof_handle_idle(void); void prof_handle_activity(void); -void prof_handle_version_result(const char * const jid, const char * const name, +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); #endif diff --git a/src/ui/ui.h b/src/ui/ui.h index 14d03ef0..4ff10679 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -165,10 +165,11 @@ 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_caps(const char * const contact, Resource *resource); void cons_show_themes(GSList *themes); void cons_show_login_success(ProfAccount *account); -void cons_show_software_version(const char * const jid, const char * const name, +void cons_show_software_version(const char * const jid, + const char * const presence, const char * const name, const char * const version, const char * const os); // status bar actions diff --git a/src/ui/windows.c b/src/ui/windows.c index 7a34b17a..71aa1223 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, gboolean show_caps); +static void _win_show_info(WINDOW *win, PContact pcontact); 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,7 @@ cons_show_wins(void) void cons_show_info(PContact pcontact) { - _win_show_info(console->win, pcontact, FALSE); + _win_show_info(console->win, pcontact); if (current_index == 0) { dirty = TRUE; @@ -1194,9 +1194,74 @@ cons_show_info(PContact pcontact) } void -cons_show_caps(PContact pcontact) +cons_show_caps(const char * const contact, Resource *resource) { - _win_show_info(console->win, pcontact, TRUE); + WINDOW *win = console->win; + cons_show(""); + const char *resource_presence = string_from_resource_presence(resource->presence); + _win_show_time(win, '-'); + _presence_colour_on(win, resource_presence); + wprintw(win, "%s", contact); + _presence_colour_off(win, resource_presence); + wprintw(win, ":\n"); + + if (resource->caps_str != NULL) { + Capabilities *caps = caps_get(resource->caps_str); + if (caps != NULL) { + // show identity + if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) { + _win_show_time(win, '-'); + wprintw(win, " Identity: "); + if (caps->name != NULL) { + wprintw(win, "%s", caps->name); + if ((caps->category != NULL) || (caps->type != NULL)) { + wprintw(win, " "); + } + } + if (caps->type != NULL) { + wprintw(win, "%s", caps->type); + if (caps->category != NULL) { + wprintw(win, " "); + } + } + if (caps->category != NULL) { + wprintw(win, "%s", caps->category); + } + wprintw(win, "\n"); + } + if (caps->software != NULL) { + _win_show_time(win, '-'); + wprintw(win, " Software: %s", caps->software); + } + if (caps->software_version != NULL) { + wprintw(win, ", %s", caps->software_version); + } + if ((caps->software != NULL) || (caps->software_version != NULL)) { + wprintw(win, "\n"); + } + if (caps->os != NULL) { + _win_show_time(win, '-'); + wprintw(win, " OS: %s", caps->os); + } + if (caps->os_version != NULL) { + wprintw(win, ", %s", caps->os_version); + } + if ((caps->os != NULL) || (caps->os_version != NULL)) { + wprintw(win, "\n"); + } + + if (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); + } + } + } + } if (current_index == 0) { dirty = TRUE; @@ -1206,12 +1271,16 @@ cons_show_caps(PContact pcontact) } void -cons_show_software_version(const char * const jid, const char * const name, - const char * const version, const char * const os) +cons_show_software_version(const char * const jid, const char * const presence, + const char * const name, const char * const version, const char * const os) { if ((name != NULL) || (version != NULL) || (os != NULL)) { cons_show(""); - cons_show("%s:", jid); + _win_show_time(console->win, '-'); + _presence_colour_on(console->win, presence); + wprintw(console->win, "%s", jid); + _presence_colour_off(console->win, presence); + wprintw(console->win, ":\n"); } if (name != NULL) { cons_show(" Name : %s", name); @@ -2431,7 +2500,7 @@ _win_show_history(WINDOW *win, int win_index, const char * const contact) } static void -_win_show_info(WINDOW *win, PContact pcontact, gboolean show_caps) +_win_show_info(WINDOW *win, PContact pcontact) { const char *barejid = p_contact_barejid(pcontact); const char *name = p_contact_name(pcontact); @@ -2551,18 +2620,6 @@ _win_show_info(WINDOW *win, PContact pcontact, gboolean show_caps) 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/iq.c b/src/xmpp/iq.c index b98d3bc6..4858482c 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -29,7 +29,9 @@ #include "common.h" #include "contact_list.h" +#include "jid.h" #include "log.h" +#include "muc.h" #include "profanity.h" #include "xmpp/capabilities.h" #include "xmpp/connection.h" @@ -207,7 +209,19 @@ _iq_handle_version_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza os_str = xmpp_stanza_get_text(os); } - prof_handle_version_result(jid, name_str, version_str, os_str); + PContact contact; + Jid *jidp = jid_create(jid); + if (muc_room_is_active(jidp)) { + contact = muc_get_participant(jidp->barejid, jidp->resourcepart); + } else { + contact = contact_list_get_contact(jidp->barejid); + } + + Resource *resource = p_contact_get_resource(contact, jidp->resourcepart); + const char *presence = string_from_resource_presence(resource->presence); + prof_handle_version_result(jid, presence, name_str, version_str, os_str); + + jid_destroy(jidp); return 1; }