/soc/2015/koosha/main: 9c71168e8a68: XEP-0280: parse incoming me...

Koosha Khajehmoogahi koosha at posteo.de
Tue Aug 4 13:11:09 EDT 2015


Changeset: 9c71168e8a68c7c8debf5d152fc1842251c60a42
Author:	 Koosha Khajehmoogahi <koosha at posteo.de>
Date:	 2015-08-04 02:50 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/koosha/main/rev/9c71168e8a68

Description:

XEP-0280: parse incoming messages and notify accordingly


This commit is essentially from the patch in https://developer.pidgin.im/ticket/15508
with some tweaks to make it compatible with the current code of libpurple

diffstat:

 libpurple/protocols/jabber/message.c    |  139 +++++++++++++++++++++----------
 libpurple/protocols/jabber/message.h    |    1 +
 libpurple/protocols/jabber/namespaces.h |    3 +
 libpurple/server.c                      |    5 -
 4 files changed, 99 insertions(+), 49 deletions(-)

diffs (262 lines):

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
@@ -118,7 +118,8 @@ static const char *jabber_get_last_recv_
 
 static void handle_chat(JabberMessage *jm)
 {
-	JabberID *jid = jabber_id_new(jm->from);
+	gchar *contact = jm->outgoing ? jm->to : jm->from;
+	JabberID *jid = jabber_id_new(contact);
 
 	PurpleConnection *gc;
 	PurpleAccount *account;
@@ -132,48 +133,50 @@ static void handle_chat(JabberMessage *j
 	gc = jm->js->gc;
 	account = purple_connection_get_account(gc);
 
-	jb = jabber_buddy_find(jm->js, jm->from, TRUE);
+	jb = jabber_buddy_find(jm->js, contact, TRUE);
 	jbr = jabber_buddy_find_resource(jb, jid->resource);
 	flags = 0;
 	if(!jm->xhtml && !jm->body) {
-		if (jbr && jm->chat_state != JM_STATE_NONE)
-			jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
+		if (!jm->outgoing) {
+			if (jbr && jm->chat_state != JM_STATE_NONE)
+				jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
 
-		if(JM_STATE_COMPOSING == jm->chat_state) {
-			purple_serv_got_typing(gc, jm->from, 0, PURPLE_IM_TYPING);
-		} else if(JM_STATE_PAUSED == jm->chat_state) {
-			purple_serv_got_typing(gc, jm->from, 0, PURPLE_IM_TYPED);
-		} else if(JM_STATE_GONE == jm->chat_state) {
-			PurpleIMConversation *im = purple_conversations_find_im_with_account(
-					jm->from, account);
-			if (im && jid->node && jid->domain) {
-				char buf[256];
-				PurpleBuddy *buddy;
+			if(JM_STATE_COMPOSING == jm->chat_state) {
+				purple_serv_got_typing(gc, contact, 0, PURPLE_IM_TYPING);
+			} else if(JM_STATE_PAUSED == jm->chat_state) {
+				purple_serv_got_typing(gc, contact, 0, PURPLE_IM_TYPED);
+			} else if(JM_STATE_GONE == jm->chat_state) {
+				PurpleIMConversation *im = purple_conversations_find_im_with_account(
+						contact, account);
+				if (im && jid->node && jid->domain) {
+					char buf[256];
+					PurpleBuddy *buddy;
 
-				g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain);
+					g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain);
 
-				if ((buddy = purple_blist_find_buddy(account, buf))) {
-					const char *who;
-					char *escaped;
+					if ((buddy = purple_blist_find_buddy(account, buf))) {
+						const char *who;
+						char *escaped;
 
-					who = purple_buddy_get_alias(buddy);
-					escaped = g_markup_escape_text(who, -1);
+						who = purple_buddy_get_alias(buddy);
+						escaped = g_markup_escape_text(who, -1);
 
-					g_snprintf(buf, sizeof(buf),
-					           _("%s has left the conversation."), escaped);
-					g_free(escaped);
+						g_snprintf(buf, sizeof(buf),
+							   _("%s has left the conversation."), escaped);
+						g_free(escaped);
 
-					/* At some point when we restructure PurpleConversation,
-					 * this should be able to be implemented by removing the
-					 * user from the conversation like we do with chats now. */
-					purple_conversation_write_system_message(
-						PURPLE_CONVERSATION(im), buf, 0);
+						/* At some point when we restructure PurpleConversation,
+						 * this should be able to be implemented by removing the
+						 * user from the conversation like we do with chats now. */
+						purple_conversation_write_system_message(
+							PURPLE_CONVERSATION(im), buf, 0);
+					}
 				}
+				purple_serv_got_typing_stopped(gc, contact);
+
+			} else {
+				purple_serv_got_typing_stopped(gc, contact);
 			}
-			purple_serv_got_typing_stopped(gc, jm->from);
-
-		} else {
-			purple_serv_got_typing_stopped(gc, jm->from);
 		}
 	} else {
 		if (jid->resource) {
@@ -188,12 +191,12 @@ static void handle_chat(JabberMessage *j
 			 */
 			PurpleIMConversation *im;
 
-			im = purple_conversations_find_im_with_account(jm->from, account);
-			if (im && !g_str_equal(jm->from,
+			im = purple_conversations_find_im_with_account(contact, account);
+			if (im && !g_str_equal(contact,
 					purple_conversation_get_name(PURPLE_CONVERSATION(im)))) {
 				purple_debug_info("jabber", "Binding conversation to %s\n",
-				                  jm->from);
-				purple_conversation_set_name(PURPLE_CONVERSATION(im), jm->from);
+				                  contact);
+				purple_conversation_set_name(PURPLE_CONVERSATION(im), contact);
 			}
 		}
 
@@ -227,7 +230,9 @@ static void handle_chat(JabberMessage *j
 			jm->body = jabber_google_format_to_html(jm->body);
 			g_free(tmp);
 		}
-		purple_serv_got_im(gc, jm->from, jm->xhtml ? jm->xhtml : jm->body, flags, jm->sent);
+
+		flags |= jm->outgoing ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV;
+		purple_serv_got_im(gc, contact, jm->xhtml ? jm->xhtml : jm->body, flags, jm->sent);
 	}
 
 	jabber_id_free(jid);
@@ -623,7 +628,47 @@ void jabber_message_parse(JabberStream *
 	JabberMessage *jm;
 	const char *id, *from, *to, *type;
 	PurpleXmlNode *child;
-	gboolean signal_return;
+	gboolean signal_return, is_outgoing = FALSE;
+	time_t message_timestamp = time(NULL);
+	gboolean delayed = FALSE;
+
+	/* Check if this is a carbon-copy of a message.
+	 * If so, use that instead for the rest of this function,
+	 * but keep track of whether the 'from' and 'to' must be swapped.
+	 */
+	from = purple_xmlnode_get_attrib(packet, "from");
+
+	if (jabber_is_own_account(js, from)) {
+		PurpleXmlNode *received = purple_xmlnode_get_child_with_namespace(packet, "received", NS_CARBONS);
+		PurpleXmlNode *sent = purple_xmlnode_get_child_with_namespace(packet, "sent", NS_CARBONS);
+
+		if (sent)
+			is_outgoing = TRUE;
+
+		if (received || sent) {
+			PurpleXmlNode *forwarded = purple_xmlnode_get_child_with_namespace(received ?
+					received : sent, "forwarded", NS_FORWARD);
+
+			if (forwarded) {
+				PurpleXmlNode *message = purple_xmlnode_get_child_with_namespace(forwarded, "message", NS_XMPP_CLIENT);
+				PurpleXmlNode *delay = purple_xmlnode_get_child_with_namespace(forwarded, "delay", NS_DELAYED_DELIVERY);
+
+				if (message) {
+					purple_debug_info("jabber", "It's a carbon-copy message, using the wrapped message instead.\n");
+					packet = message;
+
+					if (delay) {
+						const char *timestamp = purple_xmlnode_get_attrib(delay, "stamp");
+						if(timestamp) {
+							purple_debug_info("jabber", "Found a delay stamp: %s\n", timestamp);
+							delayed = TRUE;
+							message_timestamp = purple_str_to_time(timestamp, TRUE, NULL, NULL, NULL);
+						}
+					}
+				}
+			}
+		}
+	}
 
 	from = purple_xmlnode_get_attrib(packet, "from");
 	id   = purple_xmlnode_get_attrib(packet, "id");
@@ -637,10 +682,11 @@ void jabber_message_parse(JabberStream *
 
 	jm = g_new0(JabberMessage, 1);
 	jm->js = js;
-	jm->sent = time(NULL);
-	jm->delayed = FALSE;
+	jm->sent = message_timestamp;
+	jm->delayed = delayed;
 	jm->receipt = FALSE;
 	jm->chat_state = JM_STATE_NONE;
+	jm->outgoing = is_outgoing;
 
 	if(type) {
 		if(!strcmp(type, "normal"))
@@ -749,11 +795,13 @@ void jabber_message_parse(JabberStream *
 						} else if (jm->type == JABBER_MESSAGE_NORMAL ||
 						           jm->type == JABBER_MESSAGE_CHAT) {
 							conv =
-								purple_conversations_find_with_account(from, account);
+								purple_conversations_find_with_account(
+										is_outgoing ? to : from, account);
 							if (!conv) {
 								/* we need to create the conversation here */
 								conv = PURPLE_CONVERSATION(
-									purple_im_conversation_new(account, from));
+									purple_im_conversation_new(account,
+										is_outgoing ? to : from));
 							}
 						}
 					}
@@ -826,6 +874,9 @@ void jabber_message_parse(JabberStream *
 			if (msg_id && *msg_id && last_id && g_strcmp0(msg_id, last_id) == 0)
 				jm->replace_last = TRUE;
 		} else if(!strcmp(child->name, "delay") && !strcmp(xmlns, NS_DELAYED_DELIVERY)) {
+			/* Carbons/Stanza fowarding might have already set jm->delayed.
+			   However, this timestamp was certainly applied earlier, so it overrides Carbons.
+			 */
 			const char *timestamp = purple_xmlnode_get_attrib(child, "stamp");
 			jm->delayed = TRUE;
 			if(timestamp)
@@ -923,8 +974,8 @@ void jabber_message_parse(JabberStream *
 
 static gboolean
 jabber_conv_support_custom_smileys(JabberStream *js,
-								   PurpleConversation *conv,
-								   const gchar *who)
+				   PurpleConversation *conv,
+				   const gchar *who)
 {
 	JabberBuddy *jb;
 	JabberChat *chat;
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
@@ -45,6 +45,7 @@ typedef struct _JabberMessage {
 	gboolean hasBuzz;
 	gboolean receipt;
 	gboolean replace_last;
+	gboolean outgoing;
 	char *id;
 	char *from;
 	char *to;
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
@@ -101,6 +101,9 @@
 /* XEP-0280 Message Carbons */
 #define NS_CARBONS "urn:xmpp:carbons:2"
 
+/* XEP-0297 Stanza Forwarding */
+#define NS_FORWARD "urn:xmpp:forward:0"
+
 /* XEP-0308 Last Message Correction */
 #define NS_MSG_REPLACE "urn:xmpp:message-correct:0"
 
diff --git a/libpurple/server.c b/libpurple/server.c
--- a/libpurple/server.c
+++ b/libpurple/server.c
@@ -492,11 +492,6 @@ void purple_serv_got_im(PurpleConnection
 		mtime = time(NULL);
 	}
 
-	/*
-	 * XXX: Should we be setting this here, or relying on protocols to set it?
-	 */
-	flags |= PURPLE_MESSAGE_RECV;
-
 	if (!purple_account_privacy_check(account, who)) {
 		purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
 				account, who, msg, flags, (unsigned int)mtime);



More information about the Commits mailing list