From d300e8e763420e826578d1c6395b29a9ca6db8d9 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 19 May 2013 02:07:01 +0100 Subject: [PATCH] Added /roster command with nick option to change handle --- src/command/command.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/contact.c | 33 ++++++++++----------------------- src/contact.h | 3 +-- src/xmpp/roster.c | 26 +++++++++++++++++++++++--- src/xmpp/roster.h | 2 +- src/xmpp/stanza.c | 23 +++++++++++++++++++++++ src/xmpp/stanza.h | 3 +++ src/xmpp/xmpp.h | 1 + 8 files changed, 102 insertions(+), 29 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 673a1956..281c303f 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -139,6 +139,7 @@ static gboolean _cmd_nick(gchar **args, struct cmd_help_t help); static gboolean _cmd_theme(gchar **args, struct cmd_help_t help); static gboolean _cmd_status(gchar **args, struct cmd_help_t help); static gboolean _cmd_duck(gchar **args, struct cmd_help_t help); +static gboolean _cmd_roster(gchar **args, struct cmd_help_t help); /* * The commands are broken down into three groups: @@ -272,6 +273,17 @@ static struct cmd_t main_commands[] = "Example : /msg \"My Friend\" Hi, how are you?", NULL } } }, + { "/roster", + _cmd_roster, parse_args_with_freetext, 3, 3, + { "/roster nick jid handle", "Add or change a contacts handle.", + { "/roster nick jid handle", + "-----------------------", + "Change the nickname (handle) associated with a contact in your roster." + "", + "Example : /roster nick bob.smith@server.com bobby", + "Example : /roster nick myfriend@chat.org My Friend", + NULL } } }, + { "/info", _cmd_info, parse_args, 0, 1, { "/info [jid|nick]", "Show basic information about a contact, or room member.", @@ -1971,6 +1983,34 @@ _cmd_msg(gchar **args, struct cmd_help_t help) } } +static gboolean +_cmd_roster(gchar **args, struct cmd_help_t help) +{ + if (strcmp(args[0], "nick") != 0) { + cons_show("Usage: %s", help.usage); + return TRUE; + } else { + char *jid = args[1]; + char *handle = args[2]; + jabber_conn_status_t conn_status = jabber_get_connection_status(); + + if (conn_status != JABBER_CONNECTED) { + cons_show("You are not currently connected."); + return TRUE; + } + + // contact does not exist + PContact contact = roster_get_contact(jid); + if (contact == NULL) { + cons_show("Contact not found in roster: %s", jid); + return TRUE; + } + + roster_change_handle(jid, handle); + return TRUE; + } +} + static gboolean _cmd_duck(gchar **args, struct cmd_help_t help) { diff --git a/src/contact.c b/src/contact.c index 6a8dc7d3..32313fcb 100644 --- a/src/contact.c +++ b/src/contact.c @@ -73,35 +73,22 @@ p_contact_new(const char * const barejid, const char * const name, return contact; } +void +p_contact_set_name(const PContact contact, const char * const name) +{ + if (contact->name != NULL) { + FREE_SET_NULL(contact->name); + } + + contact->name = strdup(name); +} + gboolean p_contact_remove_resource(PContact contact, const char * const resource) { return g_hash_table_remove(contact->available_resources, resource); } -PContact -p_contact_new_subscription(const char * const barejid, - const char * const subscription, gboolean pending_out) -{ - PContact contact = malloc(sizeof(struct p_contact_t)); - contact->barejid = strdup(barejid); - - contact->name = NULL; - - if (subscription != NULL) - contact->subscription = strdup(subscription); - else - contact->subscription = strdup("none"); - - contact->pending_out = pending_out; - contact->last_activity = NULL; - - contact->available_resources = g_hash_table_new_full(g_str_hash, g_str_equal, free, - (GDestroyNotify)resource_destroy); - - return contact; -} - void p_contact_free(PContact contact) { diff --git a/src/contact.h b/src/contact.h index 13b97043..5915fbbf 100644 --- a/src/contact.h +++ b/src/contact.h @@ -30,8 +30,6 @@ typedef struct p_contact_t *PContact; PContact p_contact_new(const char * const barejid, const char * const name, const char * const subscription, const char * const offline_message, gboolean pending_out); -PContact p_contact_new_subscription(const char * const barejid, - const char * const subscription, gboolean pending_out); void p_contact_add_resource(PContact contact, Resource *resource); gboolean p_contact_remove_resource(PContact contact, const char * const resource); void p_contact_free(PContact contact); @@ -45,6 +43,7 @@ GDateTime* p_contact_last_activity(const PContact contact); gboolean p_contact_pending_out(const PContact contact); void p_contact_set_presence(const PContact contact, Resource *resource); void p_contact_set_status(const PContact contact, const char * const status); +void p_contact_set_name(const PContact contact, const char * const name); void p_contact_set_subscription(const PContact contact, const char * const subscription); void p_contact_set_pending_out(const PContact contact, gboolean pending_out); void p_contact_set_last_activity(const PContact contact, GDateTime *last_activity); diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index 15ac5621..2d66f4a0 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -79,6 +79,7 @@ _roster_handle_set(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, } const char *jid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID); + const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME); const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION); if (g_strcmp0(sub, "remove") == 0) { roster_remove(jid); @@ -91,7 +92,7 @@ _roster_handle_set(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, pending_out = TRUE; } - roster_update_subscription(jid, sub, pending_out); + roster_update(jid, name, sub, pending_out); return 1; } @@ -238,17 +239,36 @@ roster_contact_offline(const char * const barejid, } void -roster_update_subscription(const char * const barejid, +roster_change_handle(const char * const barejid, const char * const handle) +{ + PContact contact = g_hash_table_lookup(contacts, barejid); + + if (contact != NULL) { + p_contact_set_name(contact, handle); + } + + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_create_roster_set(ctx, barejid, handle); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); +} + +void +roster_update(const char * const barejid, const char * const name, const char * const subscription, gboolean pending_out) { PContact contact = g_hash_table_lookup(contacts, barejid); if (contact == NULL) { - contact = p_contact_new_subscription(barejid, subscription, pending_out); + contact = p_contact_new(barejid, name, subscription, NULL, pending_out); g_hash_table_insert(contacts, strdup(barejid), contact); } else { p_contact_set_subscription(contact, subscription); p_contact_set_pending_out(contact, pending_out); + if (name != NULL) { + p_contact_set_name(contact, name); + } } } diff --git a/src/xmpp/roster.h b/src/xmpp/roster.h index 1b1860a3..1b16763f 100644 --- a/src/xmpp/roster.h +++ b/src/xmpp/roster.h @@ -27,7 +27,7 @@ void roster_add_handlers(void); void roster_request(void); void roster_remove(const char * const barejid); -void roster_update_subscription(const char * const barejid, +void roster_update(const char * const barejid, const char * const name, const char * const subscription, gboolean pending_out); #endif diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 528f2055..b368dd7f 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -89,6 +89,29 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient, return msg; } +xmpp_stanza_t * +stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const jid, + const char * const handle) +{ + xmpp_stanza_t *iq = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_SET); + + xmpp_stanza_t *query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, XMPP_NS_ROSTER); + + xmpp_stanza_t *item = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(item, STANZA_NAME_ITEM); + xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid); + xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, handle); + + xmpp_stanza_add_child(query, item); + xmpp_stanza_add_child(iq, query); + + return iq; +} + xmpp_stanza_t * stanza_create_invite(xmpp_ctx_t *ctx, const char * const room, const char * const contact, const char * const reason) diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 8fb21deb..a79be3cd 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -177,4 +177,7 @@ xmpp_stanza_t * stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char * const char * stanza_get_status(xmpp_stanza_t *stanza, char *def); char * stanza_get_show(xmpp_stanza_t *stanza, char *def); +xmpp_stanza_t * stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const jid, + const char * const handle); + #endif diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index adab4f50..1f3558a9 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -140,5 +140,6 @@ char * roster_find_resource(char *search_str); gboolean roster_add(const char * const barejid, const char * const name, const char * const subscription, const char * const offline_message, gboolean pending_out); +void roster_change_handle(const char * const barejid, const char * const handle); #endif