/soc/2015/koosha/main: cd0d929093ab: XMPP: add back-end support ...
Koosha Khajehmoogahi <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: cd0d929093abf2a2f5a61e84d1eccce5eb90b977 Author: Koosha Khajehmoogahi <[email protected]> Date: 2015-06-11 02:37 +0200 Branch: default URL: https://hg.pidgin.im/soc/2015/koosha/main/rev/cd0d929093ab Description: XMPP: add back-end support for XEP-0184 "Message Delivery Receipts" diffstat: libpurple/protocols/jabber/disco.c | 2 + libpurple/protocols/jabber/jabber.c | 1 + libpurple/protocols/jabber/jabber.h | 2 +- libpurple/protocols/jabber/message.c | 77 ++++++++++++++++++++++++++++++++- libpurple/protocols/jabber/message.h | 2 + libpurple/protocols/jabber/namespaces.h | 3 + 6 files changed, 85 insertions(+), 2 deletions(-) diffs (202 lines): diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c +++ b/libpurple/protocols/jabber/disco.c @@ -302,6 +302,8 @@ static void jabber_disco_info_cb(JabberS purple_debug_info("jabber", "remote supports IBB\n"); capabilities |= JABBER_CAP_IBB; } + else if(!strcmp(var, NS_MSG_DELIVERY)) + capabilities |= JABBER_MSG_DELIVERY; } } diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c +++ b/libpurple/protocols/jabber/jabber.c @@ -3941,6 +3941,7 @@ jabber_do_init(void) jabber_add_feature(NS_SI_FILE_TRANSFER, NULL); jabber_add_feature(NS_XHTML_IM, NULL); jabber_add_feature(NS_PING, NULL); + jabber_add_feature(NS_MSG_DELIVERY, NULL); /* Buzz/Attention */ jabber_add_feature(NS_ATTENTION, jabber_buzz_isenabled); diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h +++ b/libpurple/protocols/jabber/jabber.h @@ -50,7 +50,7 @@ typedef enum { JABBER_CAP_ROSTER_VERSIONING = 1 << 15, JABBER_CAP_FACEBOOK = 1 << 16, - + JABBER_MSG_DELIVERY = 1 << 17, JABBER_CAP_RETRIEVED = 1 << 31 } JabberCapabilities; diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c +++ b/libpurple/protocols/jabber/message.c @@ -52,12 +52,54 @@ void jabber_message_free(JabberMessage * g_free(jm->password); g_free(jm->error); g_free(jm->thread_id); + g_free(jm->receipt_id); g_list_free(jm->etc); g_list_free(jm->eventitems); g_free(jm); } +static GHashTable *pending_receipts; + +static void add_pending_receipt(JabberMessage *jm) { + if (!pending_receipts) + pending_receipts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + + g_hash_table_insert(pending_receipts, g_strdup(jm->id), jm); +} + +static gboolean remove_pending_receipt(JabberMessage *jm) { + JabberMessage *pending_msg; + + if (!pending_receipts) + return FALSE; + + pending_msg = (JabberMessage *) g_hash_table_lookup(pending_receipts, jm->id); + if (pending_msg != NULL) { + g_hash_table_remove(pending_receipts, jm->id); + return TRUE; + } + + return FALSE; +} + +static void handle_receipt_request(JabberMessage *jm) { + JabberMessage *response; + + response = g_new0(JabberMessage, 1); + response->type = JABBER_MESSAGE_OTHER; + response->receipt = TRUE; + response->delayed = jm->delayed; + response->from = g_strdup(jm->to); + response->to = g_strdup(jm->from); + response->id = jabber_get_next_id(jm->js); + response->receipt_id = g_strdup(jm->id); + response->chat_state = JM_STATE_NONE; + response->js = g_memdup(jm->js, sizeof(*(jm->js))); + + jabber_message_send(response); +} + static void handle_chat(JabberMessage *jm) { JabberID *jid = jabber_id_new(jm->from); @@ -152,6 +194,9 @@ static void handle_chat(JabberMessage *j jbr->thread_id = g_strdup(jbr->thread_id); } + if (jm->receipt) + handle_receipt_request(jm); + if (jm->js->googletalk && jm->xhtml == NULL) { char *tmp = jm->body; jm->body = jabber_google_format_to_html(jm->body); @@ -552,7 +597,7 @@ void jabber_message_parse(JabberStream * { JabberMessage *jm; const char *id, *from, *to, *type; - PurpleXmlNode *child; + PurpleXmlNode *child, *sibling; gboolean signal_return; from = purple_xmlnode_get_attrib(packet, "from"); @@ -569,6 +614,7 @@ void jabber_message_parse(JabberStream * jm->js = js; jm->sent = time(NULL); jm->delayed = FALSE; + jm->receipt = FALSE; jm->chat_state = JM_STATE_NONE; if(type) { @@ -640,6 +686,19 @@ void jabber_message_parse(JabberStream * char *msg = purple_xmlnode_get_data(child); char *escaped = purple_markup_escape_text(msg, -1); jm->body = purple_strdup_withhtml(escaped); + if (jm->type == JABBER_MESSAGE_NORMAL || + jm->type == JABBER_MESSAGE_CHAT) + { + for (sibling = packet->child; sibling; sibling = sibling->next) { + if (!strcmp(sibling->name, "request")) { + const char *sibling_xmlns = purple_xmlnode_get_namespace(sibling); + if (!strcmp(sibling_xmlns, "urn:xmpp:receipts")) { + jm->receipt = TRUE; + break; + } + } + } + } g_free(escaped); g_free(msg); } @@ -741,6 +800,10 @@ void jabber_message_parse(JabberStream * jm->eventitems = g_list_append(jm->eventitems, items); } else if(!strcmp(child->name, "attention") && !strcmp(xmlns, NS_ATTENTION)) { jm->hasBuzz = TRUE; + } else if(!strcmp(child->name, "received") && !strcmp(xmlns, NS_MSG_DELIVERY)) { + const char *msg_id = purple_xmlnode_get_attrib(child, "id"); + if (msg_id) + remove_pending_receipt(jm); } else if(!strcmp(child->name, "delay") && !strcmp(xmlns, NS_DELAYED_DELIVERY)) { const char *timestamp = purple_xmlnode_get_attrib(child, "stamp"); jm->delayed = TRUE; @@ -1065,6 +1128,18 @@ void jabber_message_send(JabberMessage * if(jm->body) { child = purple_xmlnode_new_child(message, "body"); purple_xmlnode_insert_data(child, jm->body, -1); + + if (jm->type == JABBER_MESSAGE_NORMAL || jm->type == JABBER_MESSAGE_CHAT) { + child = purple_xmlnode_new_child(message, "request"); + purple_xmlnode_set_attrib(child, "xmlns", "urn:xmpp:receipts"); + } + } + + if (jm->receipt) { + child = purple_xmlnode_new_child(message, "received"); + purple_xmlnode_set_attrib(child, "xmlns", "urn:xmpp:receipts"); + purple_xmlnode_set_attrib(child, "id", jm->receipt_id); + add_pending_receipt(jm); } if(jm->xhtml) { diff --git a/libpurple/protocols/jabber/message.h b/libpurple/protocols/jabber/message.h --- a/libpurple/protocols/jabber/message.h +++ b/libpurple/protocols/jabber/message.h @@ -43,6 +43,7 @@ typedef struct _JabberMessage { time_t sent; gboolean delayed; gboolean hasBuzz; + gboolean receipt; char *id; char *from; char *to; @@ -52,6 +53,7 @@ typedef struct _JabberMessage { char *password; char *error; char *thread_id; + char *receipt_id; enum { JM_STATE_NONE, JM_STATE_ACTIVE, diff --git a/libpurple/protocols/jabber/namespaces.h b/libpurple/protocols/jabber/namespaces.h --- a/libpurple/protocols/jabber/namespaces.h +++ b/libpurple/protocols/jabber/namespaces.h @@ -67,6 +67,9 @@ /* XEP-0124 Bidirectional-streams Over Synchronous HTTP (BOSH) */ #define NS_BOSH "http://jabber.org/protocol/httpbind" +/* XEP-0184 Message Delivery Receipts */ +#define NS_MSG_DELIVERY "urn:xmpp:receipts" + /* XEP-0191 Simple Communications Blocking */ #define NS_SIMPLE_BLOCKING "urn:xmpp:blocking"