/soc/2015/koosha/main: cd0d929093ab: XMPP: add back-end support ...

Koosha Khajehmoogahi koosha at posteo.de
Wed Jun 10 20:38:29 EDT 2015


Changeset: cd0d929093abf2a2f5a61e84d1eccce5eb90b977
Author:	 Koosha Khajehmoogahi <koosha at posteo.de>
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"
 



More information about the Commits mailing list