/pidgin/main: 3fd636f586dc: Merge with release-2.x.y

Daniel Atallah datallah at pidgin.im
Sat Jan 19 14:54:52 EST 2013


Changeset: 3fd636f586dca7b82bf8f4e6fad76aa052dc432e
Author:	 Daniel Atallah <datallah at pidgin.im>
Date:	 2013-01-19 14:54 -0500
Branch:	 default
URL: http://hg.pidgin.im/pidgin/main/rev/3fd636f586dc

Description:

Merge with release-2.x.y

diffstat:

 ChangeLog                                |    5 +
 Makefile.mingw                           |    3 +-
 libpurple/protocols/bonjour/bonjour_ft.c |  166 ++++++++++++++++++++++++++----
 libpurple/protocols/bonjour/bonjour_ft.h |    2 +
 libpurple/win32/global.mak               |    2 +-
 pidgin/win32/gtkwin32dep.c               |   15 ++-
 6 files changed, 166 insertions(+), 27 deletions(-)

diffs (truncated from 367 to 300 lines):

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -96,6 +96,11 @@ version 2.10.7:
 	  them from normal messages.
 	* Add support for typing notification.
 	* Add support for the Relationship Status profile attribute.
+	* Remove all reference to Hidden Number.
+	* Ignore new invites to join a GroupChat if you're already joined, or
+	  still have a pending invite.
+	* The buddy's name was not centered vertically in the buddy-list if they
+	  did not have a status-message or mood set.
 
 	Yahoo!:
 	* Fix a double-free in profile/picture loading code. (Mihai Serban)
diff --git a/Makefile.mingw b/Makefile.mingw
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -45,6 +45,7 @@ gpg_sign = $(GPG_SIGN) -ab $(1) && $(GPG
 STRIPPED_RELEASE_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-win32bin
 DEBUG_SYMBOLS_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-dbgsym
 
+PIDGIN_INST_DEP_DIR="$(WIN32_DEV_TOP)/pidgin-inst-deps-20120910"
 
 # Any *.dll or *.exe files included in win32-install-dir that we don't compile
 # should be included in this list so they don't get stripped
@@ -108,7 +109,7 @@ endif
 	cp $(GTKSPELL_TOP)/bin/libgtkspell-0.dll $(PIDGIN_INSTALL_DIR)/spellcheck
 	cp $(ENCHANT_TOP)/bin/libenchant.dll $(PIDGIN_INSTALL_DIR)/spellcheck
 	cp -R $(ENCHANT_TOP)/lib/enchant/*.dll $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
-	cp $(WIN32_DEV_TOP)/pidgin-inst-deps-20100315/exchndl.dll $(PIDGIN_INSTALL_DIR)
+	cp $(PIDGIN_INST_DEP_DIR)/exchndl.dll $(PIDGIN_INSTALL_DIR)
 	cp $(GCC_SSP_TOP)/bin/libssp-0.dll $(PIDGIN_INSTALL_DIR)
 
 gtk_runtime_zip:
diff --git a/libpurple/protocols/bonjour/bonjour_ft.c b/libpurple/protocols/bonjour/bonjour_ft.c
--- a/libpurple/protocols/bonjour/bonjour_ft.c
+++ b/libpurple/protocols/bonjour/bonjour_ft.c
@@ -33,7 +33,7 @@
 static void
 bonjour_bytestreams_init(PurpleXfer *xfer);
 static void
-bonjour_bytestreams_connect(PurpleXfer *xfer, PurpleBuddy *pb);
+bonjour_bytestreams_connect(PurpleXfer *xfer);
 static void
 bonjour_xfer_init(PurpleXfer *xfer);
 static void
@@ -280,6 +280,25 @@ xep_ft_si_result(PurpleXfer *xfer, const
 	xep_iq_send_and_free(iq);
 }
 
+/**
+ * Frees the whole tree of an xml node
+ *
+ * First determines the root of the xml tree and then frees the whole tree
+ * from there.
+ *
+ * @param node	The node to free the tree from
+ */
+static void
+xmlnode_free_tree(xmlnode *node)
+{
+	g_return_if_fail(node != NULL);
+
+	while(xmlnode_get_parent(node))
+		node = xmlnode_get_parent(node);
+
+	xmlnode_free(node);
+}
+
 static void
 bonjour_free_xfer(PurpleXfer *xfer)
 {
@@ -310,6 +329,9 @@ bonjour_free_xfer(PurpleXfer *xfer)
 		g_free(xf->proxy_host);
 		g_free(xf->buddy_ip);
 		g_free(xf->sid);
+
+		xmlnode_free_tree(xf->streamhost);
+
 		g_free(xf);
 		purple_xfer_set_protocol_data(xfer, NULL);
 	}
@@ -441,7 +463,7 @@ xep_si_parse(PurpleConnection *pc, xmlno
 		if (si && (profile = xmlnode_get_attrib(si, "profile"))
 				&& !strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) {
 			const char *filename = NULL, *filesize_str = NULL;
-			int filesize = 0;
+			goffset filesize = 0;
 			xmlnode *file;
 
 			const char *sid = xmlnode_get_attrib(si, "id");
@@ -449,7 +471,7 @@ xep_si_parse(PurpleConnection *pc, xmlno
 			if ((file = xmlnode_get_child(si, "file"))) {
 				filename = xmlnode_get_attrib(file, "name");
 				if((filesize_str = xmlnode_get_attrib(file, "size")))
-					filesize = atoi(filesize_str);
+					filesize = g_ascii_strtoll(filesize_str, NULL, 10);
 			}
 
 			/* TODO: Make sure that it is advertising a bytestreams transfer */
@@ -547,19 +569,97 @@ out:
 	return !strcmp(host, buddy_ip);
 }
 
+static inline gint
+xep_addr_differ(const char *buddy_ip, const char *host)
+{
+	return !xep_cmp_addr(host, buddy_ip);
+}
+
+/**
+ * Create and insert an identical twin
+ *
+ * Creates a copy of the specified node and inserts it right after
+ * this original node.
+ *
+ * @param node	The node to clone
+ * @return	A pointer to the new, cloned twin if successful
+ *		or NULL otherwise.
+ */
+static xmlnode *
+xmlnode_insert_twin_copy(xmlnode *node) {
+	xmlnode *copy;
+
+	g_return_val_if_fail(node != NULL, NULL);
+
+	copy = xmlnode_copy(node);
+	g_return_val_if_fail(copy != NULL, NULL);
+
+	copy->next = node->next;
+	node->next = copy;
+
+	return copy;
+}
+
+/**
+ * Tries to append an interface scope to an IPv6 link local address.
+ *
+ * If the given address is a link local IPv6 address (with no
+ * interface scope) then we try to determine all fitting interfaces
+ * from our Bonjour IP address list.
+ *
+ * For any such found matches we insert a copy of our current xml
+ * streamhost entry right after this streamhost entry and append
+ * the determined interface to the host address of this copy.
+ *
+ * @param cur_streamhost	The XML streamhost node we examine
+ * @param host	The host address to examine in text form
+ * @param pb	Buddy to get the list of link local IPv6 addresses
+ *		and their interface from
+ * @return	Returns TRUE if the specified 'host' address is a
+ *		link local IPv6 address with no interface scope.
+ *		Otherwise returns FALSE.
+ */
 static gboolean
-__xep_bytestreams_parse(PurpleBuddy *pb, PurpleXfer *xfer, xmlnode *query,
+add_ipv6_link_local_ifaces(xmlnode *cur_streamhost, const char *host,
+			   const PurpleBuddy *pb) {
+	xmlnode *new_streamhost = NULL;
+	struct in6_addr in6_addr;
+	BonjourBuddy *bb;
+	GSList *ip_elem;
+
+	if (inet_pton(AF_INET6, host, &in6_addr) != 1 ||
+	    !IN6_IS_ADDR_LINKLOCAL(&in6_addr) ||
+	    strchr(host, '%'))
+		return FALSE;
+
+	bb = purple_buddy_get_protocol_data(pb);
+
+	for (ip_elem = bb->ips;
+	     (ip_elem = g_slist_find_custom(ip_elem, host, (GCompareFunc)&xep_addr_differ));
+	     ip_elem = ip_elem->next) {
+		purple_debug_info("bonjour", "Inserting an xmlnode twin copy for %s with new host address %s\n",
+				  host, (char*)ip_elem->data);
+		new_streamhost = xmlnode_insert_twin_copy(cur_streamhost);
+		xmlnode_set_attrib(new_streamhost, "host", ip_elem->data);
+	}
+
+	if (!new_streamhost)
+		purple_debug_info("bonjour", "No interface for this IPv6 link local address found: %s\n",
+				  host);
+
+	return TRUE;
+}
+
+static gboolean
+__xep_bytestreams_parse(PurpleBuddy *pb, PurpleXfer *xfer, xmlnode *streamhost,
 			const char *iq_id)
 {
+	char *tmp_iq_id;
 	const char *jid, *host, *port;
 	int portnum;
-	xmlnode *streamhost;
 	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
 
-	for(streamhost = xmlnode_get_child(query, "streamhost");
-			streamhost;
-			streamhost = xmlnode_get_next_twin(streamhost)) {
-
+	for(; streamhost; streamhost = xmlnode_get_next_twin(streamhost)) {
 		if(!(jid = xmlnode_get_attrib(streamhost, "jid")) ||
 		   !(host = xmlnode_get_attrib(streamhost, "host")) ||
 		   !(port = xmlnode_get_attrib(streamhost, "port")) ||
@@ -568,29 +668,36 @@ static gboolean
 			continue;
 		}
 
-		if(!xep_cmp_addr(host, xf->buddy_ip))
+		/* skip IPv6 link local addresses with no interface scope
+		 * (but try to add a new one with an interface scope then) */
+		if(add_ipv6_link_local_ifaces(streamhost, host, pb))
 			continue;
 
+		tmp_iq_id = g_strdup(iq_id);
 		g_free(xf->iq_id);
-		xf->iq_id = g_strdup(iq_id);
+		g_free(xf->jid);
+		g_free(xf->proxy_host);
+
+		xf->iq_id = tmp_iq_id;
 		xf->jid = g_strdup(jid);
-		xf->proxy_host = g_strdup(xf->buddy_ip);
+		xf->proxy_host = g_strdup(host);
 		xf->proxy_port = portnum;
+		xf->streamhost = streamhost;
+		xf->pb = pb;
 		purple_debug_info("bonjour", "bytestream offer parse"
 				  "jid=%s host=%s port=%d.\n", jid, host, portnum);
-		bonjour_bytestreams_connect(xfer, pb);
+		bonjour_bytestreams_connect(xfer);
 		return TRUE;
 	}
 
 	return FALSE;
 }
 
-
 void
 xep_bytestreams_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb)
 {
 	const char *type, *from, *iq_id, *sid;
-	xmlnode *query;
+	xmlnode *query, *streamhost;
 	BonjourData *bd;
 	PurpleXfer *xfer;
 
@@ -610,6 +717,10 @@ xep_bytestreams_parse(PurpleConnection *
 	if(!type)
 		return;
 
+	query = xmlnode_copy(query);
+	if (!query)
+		return;
+
 	if(strcmp(type, "set")) {
 		purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
 		return;
@@ -621,7 +732,9 @@ xep_bytestreams_parse(PurpleConnection *
 
 	sid = xmlnode_get_attrib(query, "sid");
 	xfer = bonjour_si_xfer_find(bd, sid, from);
-	if(xfer && __xep_bytestreams_parse(pb, xfer, query, iq_id))
+	streamhost = xmlnode_get_child(query, "streamhost");
+
+	if(xfer && streamhost && __xep_bytestreams_parse(pb, xfer, streamhost, iq_id))
 		return; /* success */
 
 	purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
@@ -864,15 +977,22 @@ bonjour_bytestreams_connect_cb(gpointer 
 	XepIq *iq;
 	xmlnode *q_node, *tmp_node;
 	BonjourData *bd;
+	gboolean ret = FALSE;
 
 	xf->proxy_connection = NULL;
 
 	if(source < 0) {
-		purple_debug_error("bonjour", "Error connecting via SOCKS5 - %s\n",
-			error_message ? error_message : "(null)");
-		xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
-		/* Cancel the connection */
-		purple_xfer_cancel_local(xfer);
+		purple_debug_error("bonjour", "Error connecting via SOCKS5 to %s - %s\n",
+			xf->proxy_host, error_message ? error_message : "(null)");
+
+		tmp_node = xmlnode_get_next_twin(xf->streamhost);
+		ret = __xep_bytestreams_parse(xf->pb, xfer, tmp_node, xf->iq_id);
+
+		if (!ret) {
+			xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
+			/* Cancel the connection */
+			purple_xfer_cancel_local(xfer);
+		}
 		return;
 	}
 
@@ -894,8 +1014,9 @@ bonjour_bytestreams_connect_cb(gpointer 
 }



More information about the Commits mailing list