From 1cea320a0cff2a763a47322283886facfd9c9c29 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sun, 3 Feb 2013 20:09:56 +0000 Subject: [PATCH] Send entity capabilities and status when joining room --- src/config/accounts.c | 3 + src/xmpp/presence.c | 186 +++++++++++++++++------------------------- src/xmpp/stanza.c | 77 ++++++++++++++++- src/xmpp/stanza.h | 7 +- 4 files changed, 162 insertions(+), 111 deletions(-) diff --git a/src/config/accounts.c b/src/config/accounts.c index b94f27c2..c51e01f5 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -428,6 +428,9 @@ accounts_get_priority_for_presence_type(const char * const account_name, result = 0; break; } + + if (result < JABBER_PRIORITY_MIN || result > JABBER_PRIORITY_MAX) + result = 0; return result; } diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index 0d50a080..f30a701c 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -43,6 +43,7 @@ static int _presence_handler(xmpp_conn_t * const conn, static char* _handle_presence_caps(xmpp_stanza_t * const stanza); static int _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza); +static const char * _get_presence_stanza_string_from_type(jabber_presence_t presence_type); void presence_init(void) @@ -104,12 +105,70 @@ presence_free_sub_requests(void) g_hash_table_remove_all(sub_requests); } +void +presence_update(jabber_presence_t presence_type, const char * const msg, + int idle) +{ + xmpp_ctx_t *ctx = jabber_get_ctx(); + xmpp_conn_t *conn = jabber_get_conn(); + int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), + presence_type); + const char *show = _get_presence_stanza_string_from_type(presence_type); + + // don't send presence when disconnected + if (jabber_get_connection_status() != JABBER_CONNECTED) + return; + + jabber_conn_set_presence_type(presence_type); + jabber_conn_set_presence_message(msg); + jabber_conn_set_priority(pri); + + xmpp_stanza_t *presence = stanza_create_presence(ctx, show, msg); + stanza_attach_priority(ctx, presence, pri); + stanza_attach_last_activity(ctx, presence, idle); + stanza_attach_caps(ctx, presence); + + xmpp_send(conn, presence); + + // send presence for each room + GList *rooms = muc_get_active_room_list(); + while (rooms != NULL) { + char *room = rooms->data; + char *nick = muc_get_room_nick(room); + char *full_room_jid = create_fulljid(room, nick); + + xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); + xmpp_send(conn, presence); + + rooms = g_list_next(rooms); + } + g_list_free(rooms); + + xmpp_stanza_release(presence); + + // set last presence for account + const char *last = show; + if (last == NULL) { + last = STANZA_TEXT_ONLINE; + } + accounts_set_last_presence(jabber_get_account_name(), last); +} + void presence_join_room(Jid *jid) { xmpp_ctx_t *ctx = jabber_get_ctx(); xmpp_conn_t *conn = jabber_get_conn(); - xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid); + jabber_presence_t presence_type = jabber_get_presence_type(); + const char *show = _get_presence_stanza_string_from_type(presence_type); + char *status = jabber_get_presence_message(); + int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), + presence_type); + + xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid, show, status); + stanza_attach_priority(ctx, presence, pri); + stanza_attach_caps(ctx, presence); + xmpp_send(conn, presence); xmpp_stanza_release(presence); @@ -142,114 +201,6 @@ presence_leave_chat_room(const char * const room_jid) xmpp_stanza_release(presence); } -void -presence_update(jabber_presence_t presence_type, const char * const msg, - int idle) -{ - xmpp_ctx_t *ctx = jabber_get_ctx(); - xmpp_conn_t *conn = jabber_get_conn(); - int pri; - char *show, *last; - - // don't send presence when disconnected - if (jabber_get_connection_status() != JABBER_CONNECTED) - return; - - pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), - presence_type); - if (pri < JABBER_PRIORITY_MIN || pri > JABBER_PRIORITY_MAX) - pri = 0; - - jabber_conn_set_presence_type(presence_type); - jabber_conn_set_presence_message(msg); - jabber_conn_set_priority(pri); - - switch(presence_type) - { - case PRESENCE_AWAY: - show = STANZA_TEXT_AWAY; - last = STANZA_TEXT_AWAY; - break; - case PRESENCE_DND: - show = STANZA_TEXT_DND; - last = STANZA_TEXT_DND; - break; - case PRESENCE_CHAT: - show = STANZA_TEXT_CHAT; - last = STANZA_TEXT_CHAT; - break; - case PRESENCE_XA: - show = STANZA_TEXT_XA; - last = STANZA_TEXT_XA; - break; - default: // PRESENCE_ONLINE - show = NULL; - last = STANZA_TEXT_ONLINE; - break; - } - - - xmpp_stanza_t *presence = stanza_create_presence(ctx, show, msg); - - // servers must treat no priority as 0 - if (pri != 0) { - xmpp_stanza_t *priority, *value; - char pri_str[10]; - - snprintf(pri_str, sizeof(pri_str), "%d", pri); - priority = xmpp_stanza_new(ctx); - value = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(priority, STANZA_NAME_PRIORITY); - xmpp_stanza_set_text(value, pri_str); - xmpp_stanza_add_child(priority, value); - xmpp_stanza_add_child(presence, priority); - } - - if (idle > 0) { - xmpp_stanza_t *query = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(query, STANZA_NAME_QUERY); - xmpp_stanza_set_ns(query, STANZA_NS_LASTACTIVITY); - char idle_str[10]; - snprintf(idle_str, sizeof(idle_str), "%d", idle); - xmpp_stanza_set_attribute(query, STANZA_ATTR_SECONDS, idle_str); - xmpp_stanza_add_child(presence, query); - } - - // add caps - xmpp_stanza_t *caps = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(caps, STANZA_NAME_C); - xmpp_stanza_set_ns(caps, STANZA_NS_CAPS); - xmpp_stanza_t *query = caps_create_query_response_stanza(ctx); - - char *sha1 = caps_create_sha1_str(query); - xmpp_stanza_set_attribute(caps, STANZA_ATTR_HASH, "sha-1"); - xmpp_stanza_set_attribute(caps, STANZA_ATTR_NODE, "http://www.profanity.im"); - xmpp_stanza_set_attribute(caps, STANZA_ATTR_VER, sha1); - xmpp_stanza_add_child(presence, caps); - - xmpp_send(conn, presence); - - // send presence for each room - GList *rooms = muc_get_active_room_list(); - while (rooms != NULL) { - char *room = rooms->data; - char *nick = muc_get_room_nick(room); - char *full_room_jid = create_fulljid(room, nick); - - xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); - xmpp_send(conn, presence); - - rooms = g_list_next(rooms); - } - g_list_free(rooms); - - xmpp_stanza_release(presence); - - FREE_SET_NULL(sha1); - - // set last presence for account - accounts_set_last_presence(jabber_get_account_name(), last); -} static int @@ -513,3 +464,20 @@ _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) return 1; } +static const char * +_get_presence_stanza_string_from_type(jabber_presence_t presence_type) +{ + switch(presence_type) + { + case PRESENCE_AWAY: + return STANZA_TEXT_AWAY; + case PRESENCE_DND: + return STANZA_TEXT_DND; + case PRESENCE_CHAT: + return STANZA_TEXT_CHAT; + case PRESENCE_XA: + return STANZA_TEXT_XA; + default: // PRESENCE_ONLINE + return NULL; + } +} diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 5b0aab3f..5a19a576 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -28,6 +28,7 @@ #include "common.h" #include "xmpp/stanza.h" +#include "xmpp/capabilities.h" static int _field_compare(FormField *f1, FormField *f2); @@ -86,7 +87,8 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient, xmpp_stanza_t * stanza_create_room_join_presence(xmpp_ctx_t *ctx, - const char * const full_room_jid) + const char * const full_room_jid, const char * const show, + const char * const status) { xmpp_stanza_t *presence = xmpp_stanza_new(ctx); xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE); @@ -98,6 +100,28 @@ stanza_create_room_join_presence(xmpp_ctx_t *ctx, xmpp_stanza_add_child(presence, x); + if (show != NULL) { + xmpp_stanza_t *show_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(show_stanza, STANZA_NAME_SHOW); + xmpp_stanza_t *text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text, show); + xmpp_stanza_add_child(show_stanza, text); + xmpp_stanza_add_child(presence, show_stanza); + xmpp_stanza_release(text); + xmpp_stanza_release(show_stanza); + } + + if (status != NULL) { + xmpp_stanza_t *status_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(status_stanza, STANZA_NAME_STATUS); + xmpp_stanza_t *text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text, status); + xmpp_stanza_add_child(status_stanza, text); + xmpp_stanza_add_child(presence, status_stanza); + xmpp_stanza_release(text); + xmpp_stanza_release(status_stanza); + } + return presence; } @@ -601,6 +625,57 @@ stanza_destroy_form(DataForm *form) } } +void +stanza_attach_priority(xmpp_ctx_t *ctx, xmpp_stanza_t *presence, int pri) +{ + if (pri != 0) { + xmpp_stanza_t *priority, *value; + char pri_str[10]; + + snprintf(pri_str, sizeof(pri_str), "%d", pri); + priority = xmpp_stanza_new(ctx); + value = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(priority, STANZA_NAME_PRIORITY); + xmpp_stanza_set_text(value, pri_str); + xmpp_stanza_add_child(priority, value); + xmpp_stanza_add_child(presence, priority); + xmpp_stanza_release(priority); + } +} + +void +stanza_attach_last_activity(xmpp_ctx_t *ctx, xmpp_stanza_t *presence, int idle) +{ + if (idle > 0) { + xmpp_stanza_t *query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, STANZA_NS_LASTACTIVITY); + char idle_str[10]; + snprintf(idle_str, sizeof(idle_str), "%d", idle); + xmpp_stanza_set_attribute(query, STANZA_ATTR_SECONDS, idle_str); + xmpp_stanza_add_child(presence, query); + xmpp_stanza_release(query); + } +} + +void +stanza_attach_caps(xmpp_ctx_t *ctx, xmpp_stanza_t *presence) +{ + xmpp_stanza_t *caps = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(caps, STANZA_NAME_C); + xmpp_stanza_set_ns(caps, STANZA_NS_CAPS); + xmpp_stanza_t *query = caps_create_query_response_stanza(ctx); + + char *sha1 = caps_create_sha1_str(query); + xmpp_stanza_set_attribute(caps, STANZA_ATTR_HASH, "sha-1"); + xmpp_stanza_set_attribute(caps, STANZA_ATTR_NODE, "http://www.profanity.im"); + xmpp_stanza_set_attribute(caps, STANZA_ATTR_VER, sha1); + xmpp_stanza_add_child(presence, caps); + xmpp_stanza_release(caps); + xmpp_stanza_release(query); + FREE_SET_NULL(sha1); +} + static int _field_compare(FormField *f1, FormField *f2) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index ab5f79a5..f3d25cb2 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -112,7 +112,8 @@ xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx, const char * const message, const char * const state); xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t *ctx, - const char * const full_room_jid); + const char * const full_room_jid, const char * const show, + const char * const status); xmpp_stanza_t* stanza_create_room_newnick_presence(xmpp_ctx_t *ctx, const char * const full_room_jid); @@ -149,4 +150,8 @@ gboolean stanza_is_version_request(xmpp_stanza_t * const stanza); DataForm * stanza_create_form(xmpp_stanza_t * const stanza); void stanza_destroy_form(DataForm *form); +void stanza_attach_priority(xmpp_ctx_t *ctx, xmpp_stanza_t *presence, int pri); +void stanza_attach_last_activity(xmpp_ctx_t *ctx, xmpp_stanza_t *presence, int idle); +void stanza_attach_caps(xmpp_ctx_t *ctx, xmpp_stanza_t *presence); + #endif