changeset 29541:19610ea45ff3

propagate from branch 'im.pidgin.pidgin' (head 91a6721a97381551e47347b98c8f7b596e60e3ae) to branch 'im.pidgin.cpw.rekkanoryo.ggupdate' (head d21119dede49bb8c2a1cfb45634f4d976f6f0e8b)
author John Bailey <rekkanoryo@rekkanoryo.org>
date Mon, 01 Mar 2010 03:46:33 +0000
parents 89120a5b285a (diff) c0d337670835 (current diff)
children c84ee0ff4fe6
files
diffstat 51 files changed, 473 insertions(+), 348 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Wed Feb 24 02:30:35 2010 +0000
+++ b/COPYRIGHT	Mon Mar 01 03:46:33 2010 +0000
@@ -303,6 +303,7 @@
 Peter McCurdy
 Kurt McKee
 Torrey McMahon
+Greg McNew
 Robert McQueen
 Mihály Mészáros
 Robert Mibus
--- a/ChangeLog	Wed Feb 24 02:30:35 2010 +0000
+++ b/ChangeLog	Mon Mar 01 03:46:33 2010 +0000
@@ -15,8 +15,14 @@
 	* Use GtkStatusIcon for the docklet, providing better integration in
 	  notification area.
 	* Added UI for sending attentions (buzz, nudge) on supporting protocols.
-	* Make the search dialog unobtrusive in the conversation window (by making
-	  it look and behave like the search dialog in Firefox)
+	* Make the search dialog unobtrusive in the conversation window (by
+	  making it look and behave like the search dialog in Firefox)
+	* The Recent Log Activity sort method for the Buddy List now
+	  distinguishes between no activity and a small amount of activity
+	  in the distant past.  (Greg McNew)
+
+	Bonjour:
+	* Added support for IPv6. (Thanks to T_X for testing)
 
 version 2.6.6 (02/18/2010):
 	libpurple:
--- a/libpurple/example/nullclient.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/example/nullclient.c	Mon Mar 01 03:46:33 2010 +0000
@@ -27,7 +27,11 @@
 
 #include <signal.h>
 #include <string.h>
+#ifndef _WIN32
 #include <unistd.h>
+#else
+#include "win32/win32dep.h"
+#endif
 
 #include "defines.h"
 
@@ -80,7 +84,11 @@
 	if (condition & PURPLE_INPUT_WRITE)
 		cond |= PURPLE_GLIB_WRITE_COND;
 
+#if defined _WIN32 && !defined WINPIDGIN_USE_GLIB_IO_CHANNEL
+	channel = wpurple_g_io_channel_win32_new_socket(fd);
+#else
 	channel = g_io_channel_unix_new(fd);
+#endif
 	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
 					      purple_glib_io_invoke, closure, purple_glib_io_destroy);
 
@@ -253,12 +261,14 @@
 	PurpleSavedStatus *status;
 	char *res;
 
+#ifndef _WIN32
 	/* libpurple's built-in DNS resolution forks processes to perform
 	 * blocking lookups without blocking the main process.  It does not
 	 * handle SIGCHLD itself, so if the UI does not you quickly get an army
 	 * of zombie subprocesses marching around.
 	 */
 	signal(SIGCHLD, SIG_IGN);
+#endif
 
 	init_libpurple();
 
--- a/libpurple/ft.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/ft.c	Mon Mar 01 03:46:33 2010 +0000
@@ -1085,7 +1085,7 @@
 			return;
 		}
 	} else if (xfer->type == PURPLE_XFER_SEND) {
-		size_t result;
+		size_t result = 0;
 		size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
 		PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
 
@@ -1130,13 +1130,24 @@
 
 			result = tmp;
 		} else {
-			buffer = g_malloc0(s);
-			result = fread(buffer, 1, s, xfer->dest_fp);
-			if (result != s) {
-				purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
-				purple_xfer_cancel_local(xfer);
-				g_free(buffer);
-				return;
+			gboolean read = TRUE;
+			if (priv->buffer) {
+				if (priv->buffer->len < s) {
+					s -= priv->buffer->len;
+					read = TRUE;
+				} else {
+					read = FALSE;
+				}
+			}
+			if (read) {
+				buffer = g_malloc(s);
+				result = fread(buffer, 1, s, xfer->dest_fp);
+				if (result != s) {
+					purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
+					purple_xfer_cancel_local(xfer);
+					g_free(buffer);
+					return;
+				}
 			}
 		}
 	
--- a/libpurple/log.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/log.c	Mon Mar 01 03:46:33 2010 +0000
@@ -36,6 +36,8 @@
 #include "imgstore.h"
 #include "time.h"
 
+#include <math.h>
+
 static GSList *loggers = NULL;
 
 static PurpleLogLogger *html_logger;
@@ -302,7 +304,7 @@
 			}
 		}
 
-		score = (gint)score_double;
+		score = (gint) ceil(score_double);
 		g_hash_table_replace(logsize_users_decayed, lu, GINT_TO_POINTER(score));
 	}
 	return score;
--- a/libpurple/plugins/perl/common/module.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/plugins/perl/common/module.h	Mon Mar 01 03:46:33 2010 +0000
@@ -9,6 +9,7 @@
 #include <glib.h>
 #ifdef _WIN32
 #undef pipe
+#undef STRINGIFY
 #endif
 #include <EXTERN.h>
 #include <perl.h>
--- a/libpurple/plugins/perl/perl-common.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/plugins/perl/perl-common.h	Mon Mar 01 03:46:33 2010 +0000
@@ -3,6 +3,7 @@
 
 #include <glib.h>
 #ifdef _WIN32
+#undef STRINGIFY
 #undef pipe
 #endif
 #include <EXTERN.h>
--- a/libpurple/protocols/bonjour/bonjour.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Mon Mar 01 03:46:33 2010 +0000
@@ -101,6 +101,8 @@
 
 	/* Start waiting for jabber connections (iChat style) */
 	bd->jabber_data = g_new0(BonjourJabber, 1);
+	bd->jabber_data->socket = -1;
+	bd->jabber_data->socket6 = -1;
 	bd->jabber_data->port = purple_account_get_int(account, "port", BONJOUR_DEFAULT_PORT);
 	bd->jabber_data->account = account;
 
@@ -525,7 +527,8 @@
 	sizeof(PurplePluginProtocolInfo),                        /* struct_size */
 	NULL,                                                    /* get_account_text_table */
 	NULL,                                                    /* initiate_media */
-	NULL                                                     /* can_do_media */
+	NULL,                                                    /* get_media_caps */
+	NULL                                                     /* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/bonjour/bonjour_ft.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/bonjour/bonjour_ft.c	Mon Mar 01 03:46:33 2010 +0000
@@ -747,8 +747,7 @@
 	XepIq *iq;
 	xmlnode *query, *streamhost;
 	gchar *port;
-	const char *next_ip, *local_ip;
-	const char token [] = ";";
+	GSList *local_ips;
 	BonjourData *bd;
 
 	purple_debug_info("bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock);
@@ -773,17 +772,16 @@
 
 	xfer->local_port = purple_network_get_port_from_fd(sock);
 
-	local_ip = purple_network_get_my_ip_ext2(sock);
-	/* cheat a little here - the intent of the "const" attribute is to make it clear that the string doesn't need to be freed */
-	next_ip = strtok((char *)local_ip, token);
+	local_ips = bonjour_jabber_get_local_ips(sock);
 
 	port = g_strdup_printf("%hu", xfer->local_port);
-	while(next_ip != NULL) {
+	while(local_ips) {
 		streamhost = xmlnode_new_child(query, "streamhost");
 		xmlnode_set_attrib(streamhost, "jid", xf->sid);
-		xmlnode_set_attrib(streamhost, "host", next_ip);
+		xmlnode_set_attrib(streamhost, "host", local_ips->data);
 		xmlnode_set_attrib(streamhost, "port", port);
-		next_ip = strtok(NULL, token);
+		g_free(local_ips->data);
+		local_ips = g_slist_delete_link(local_ips, local_ips);
 	}
 	g_free(port);
 
@@ -796,15 +794,17 @@
 	XepXfer *xf;
 	if(xfer == NULL)
 		return;
+
 	purple_debug_info("bonjour", "Bonjour-bytestreams-init.\n");
 	xf = xfer->data;
+
 	purple_network_listen_map_external(FALSE);
 	xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM,
 						      bonjour_bytestreams_listen, xfer);
 	purple_network_listen_map_external(TRUE);
-	if (xf->listen_data == NULL) {
+	if (xf->listen_data == NULL)
 		purple_xfer_cancel_local(xfer);
-	}
+
 	return;
 }
 
--- a/libpurple/protocols/bonjour/jabber.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Mon Mar 01 03:46:33 2010 +0000
@@ -44,6 +44,11 @@
 #endif
 #include <fcntl.h>
 
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
+
 #include "network.h"
 #include "eventloop.h"
 #include "connection.h"
@@ -623,15 +628,22 @@
 
 }
 
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
 static void
 _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition condition)
 {
 	BonjourJabber *jdata = data;
-	struct sockaddr_in their_addr; /* connector's address information */
-	socklen_t sin_size = sizeof(struct sockaddr);
+	struct sockaddr_storage their_addr; /* connector's address information */
+	socklen_t sin_size = sizeof(struct sockaddr_storage);
 	int client_socket;
 	int flags;
-	char *address_text = NULL;
+#ifdef HAVE_INET_NTOP
+	char addrstr[INET6_ADDRSTRLEN];
+#endif
+	const char *address_text;
 	struct _match_buddies_by_address_t *mbba;
 	BonjourJabberConversation *bconv;
 	GSList *buddies;
@@ -640,7 +652,9 @@
 	if (condition != PURPLE_INPUT_READ)
 		return;
 
-	if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1)
+	memset(&their_addr, 0, sin_size);
+
+	if ((client_socket = accept(server_socket, (struct sockaddr*)&their_addr, &sin_size)) == -1)
 		return;
 
 	flags = fcntl(client_socket, F_GETFL);
@@ -650,7 +664,16 @@
 #endif
 
 	/* Look for the buddy that has opened the conversation and fill information */
-	address_text = inet_ntoa(their_addr.sin_addr);
+#ifdef HAVE_INET_NTOP
+	if (their_addr.ss_family == AF_INET6)
+		address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in6 *)&their_addr)->sin6_addr,
+			addrstr, sizeof(addrstr));
+	else
+		address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in *)&their_addr)->sin_addr,
+			addrstr, sizeof(addrstr));
+#else
+	address_text = inet_ntoa(((struct sockaddr_in *)&their_addr)->sin_addr);
+#endif
 	purple_debug_info("bonjour", "Received incoming connection from %s.\n", address_text);
 	mbba = g_new0(struct _match_buddies_by_address_t, 1);
 	mbba->address = address_text;
@@ -680,52 +703,42 @@
 
 }
 
-gint
-bonjour_jabber_start(BonjourJabber *jdata)
+static int
+start_serversocket_listening(int port, int socket, struct sockaddr *addr, size_t addr_size, gboolean ip6, gboolean allow_port_fallback)
 {
-	struct sockaddr_in my_addr;
+	int ret_port = port;
 
-	/* Open a listening socket for incoming conversations */
-	jdata->socket = socket(PF_INET, SOCK_STREAM, 0);
-	if (jdata->socket < 0) {
-		gchar *buf = g_strdup_printf(_("Unable to create socket: %s"),
-				g_strerror(errno));
-		purple_connection_error_reason(jdata->account->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, buf);
-		g_free(buf);
-		return -1;
-	}
-
-	memset(&my_addr, 0, sizeof(struct sockaddr_in));
-	my_addr.sin_family = AF_INET;
+	purple_debug_info("bonjour", "Attempting to bind IPv%d socket to port %d.\n", ip6 ? 6 : 4, port);
 
 	/* Try to use the specified port - if it isn't available, use a random port */
-	my_addr.sin_port = htons(jdata->port);
-	if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0)
-	{
+	if (bind(socket, addr, addr_size) != 0) {
+
 		purple_debug_info("bonjour", "Unable to bind to specified "
-				"port %i: %s\n", jdata->port, g_strerror(errno));
-		my_addr.sin_port = 0;
-		if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0)
-		{
-			gchar *buf = g_strdup_printf(_("Unable to bind socket "
-					"to port: %s"), g_strerror(errno));
-			purple_connection_error_reason(jdata->account->gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, buf);
-			g_free(buf);
+				"port %i: %s\n", port, g_strerror(errno));
+
+		if (!allow_port_fallback) {
+			purple_debug_warning("bonjour", "Not attempting random port assignment.\n");
 			return -1;
 		}
-		jdata->port = purple_network_get_port_from_fd(jdata->socket);
+#ifdef PF_INET6
+		if (ip6)
+			((struct sockaddr_in6 *) addr)->sin6_port = 0;
+		else
+#endif
+		((struct sockaddr_in *) addr)->sin_port = 0;
+
+		if (bind(socket, addr, addr_size) != 0) {
+			purple_debug_error("bonjour", "Unable to bind IPv%d socket to port: %s\n", ip6 ? 6 : 4, g_strerror(errno));
+			return -1;
+		}
+		ret_port = purple_network_get_port_from_fd(socket);
 	}
 
+	purple_debug_info("bonjour", "Bound IPv%d socket to port %d.\n", ip6 ? 6 : 4, ret_port);
+
 	/* Attempt to listen on the bound socket */
-	if (listen(jdata->socket, 10) != 0)
-	{
-		gchar *buf = g_strdup_printf(_("Unable to listen on socket: %s"),
-				g_strerror(errno));
-		purple_connection_error_reason(jdata->account->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, buf);
-		g_free(buf);
+	if (listen(socket, 10) != 0) {
+		purple_debug_error("bonjour", "Unable to listen on IPv%d socket: %s\n", ip6 ? 6 : 4, g_strerror(errno));
 		return -1;
 	}
 
@@ -739,8 +752,66 @@
 	}
 #endif
 
-	/* Open a watcher in the socket we have just opened */
-	jdata->watcher_id = purple_input_add(jdata->socket, PURPLE_INPUT_READ, _server_socket_handler, jdata);
+	return ret_port;
+}
+
+gint
+bonjour_jabber_start(BonjourJabber *jdata)
+{
+	int ipv6_port = -1, ipv4_port = -1;
+
+	/* Open a listening socket for incoming conversations */
+#ifdef PF_INET6
+	jdata->socket6 = socket(PF_INET6, SOCK_STREAM, 0);
+#endif
+	jdata->socket = socket(PF_INET, SOCK_STREAM, 0);
+	if (jdata->socket == -1 && jdata->socket6 == -1) {
+		purple_debug_error("bonjour", "Unable to create socket: %s",
+				g_strerror(errno));
+		return -1;
+	}
+
+#ifdef PF_INET6
+	if (jdata->socket6 != -1) {
+		struct sockaddr_in6 addr6;
+	        memset(&addr6, 0, sizeof(addr6));
+		addr6.sin6_family = AF_INET6;
+		addr6.sin6_port = htons(jdata->port);
+      		addr6.sin6_addr = in6addr_any;
+		ipv6_port = start_serversocket_listening(jdata->port, jdata->socket6, (struct sockaddr *) &addr6, sizeof(addr6), TRUE, TRUE);
+		/* Open a watcher in the socket we have just opened */
+		if (ipv6_port > 0) {
+			jdata->watcher_id6 = purple_input_add(jdata->socket6, PURPLE_INPUT_READ, _server_socket_handler, jdata);
+			jdata->port = ipv6_port;
+		} else {
+			purple_debug_error("bonjour", "Failed to start listening on IPv6 socket.\n");
+			close(jdata->socket6);
+			jdata->socket6 = -1;
+		}
+	}
+#endif
+	if (jdata->socket != -1) {
+		struct sockaddr_in addr4;
+		memset(&addr4, 0, sizeof(addr4));
+		addr4.sin_family = AF_INET;
+		addr4.sin_port = htons(jdata->port);
+		ipv4_port = start_serversocket_listening(jdata->port, jdata->socket, (struct sockaddr *) &addr4, sizeof(addr4), FALSE, ipv6_port != -1);
+		/* Open a watcher in the socket we have just opened */
+		if (ipv4_port > 0) {
+			jdata->watcher_id = purple_input_add(jdata->socket, PURPLE_INPUT_READ, _server_socket_handler, jdata);
+			jdata->port = ipv4_port;
+		} else {
+			purple_debug_error("bonjour", "Failed to start listening on IPv4 socket.\n");
+			close(jdata->socket);
+			jdata->socket = -1;
+		}
+	}
+
+	if (!(ipv6_port > 0 || ipv4_port > 0)) {
+		purple_debug_error("bonjour", "Unable to listen on socket: %s",
+				g_strerror(errno));
+		return -1;
+	}
 
 	return jdata->port;
 }
@@ -1101,6 +1172,10 @@
 		close(jdata->socket);
 	if (jdata->watcher_id > 0)
 		purple_input_remove(jdata->watcher_id);
+	if (jdata->socket6 >= 0)
+		close(jdata->socket6);
+	if (jdata->watcher_id6 > 0)
+		purple_input_remove(jdata->watcher_id6);
 
 	/* Close all the conversation sockets and remove all the watchers after sending end streams */
 	if (jdata->account->gc != NULL) {
@@ -1234,58 +1309,97 @@
 	return (ret >= 0) ? 0 : -1;
 }
 
-/* This returns a ';' delimited string containing all non-localhost IPs */
-const char *
-purple_network_get_my_ip_ext2(int fd)
+/* This returns a list containing all non-localhost IPs */
+GSList *
+bonjour_jabber_get_local_ips(int fd)
 {
-	char buffer[1024];
-	static char ip_ext[17 * 10];
+	GSList *ips = NULL;
+	const char *address_text;
+	int ret;
+
+#ifdef HAVE_GETIFADDRS /* This is required for IPv6 */
+	{
+	struct ifaddrs *ifap, *ifa;
+	struct sockaddr *addr;
+	char addrstr[INET6_ADDRSTRLEN];
+
+	ret = getifaddrs(&ifap);
+	if (ret != 0) {
+		const char *error = g_strerror(errno);
+		purple_debug_error("bonjour", "getifaddrs() error: %s\n", error ? error : "(null)");
+		return NULL;
+	}
+
+	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+		if (!(ifa->ifa_flags & IFF_RUNNING) || (ifa->ifa_flags & IFF_LOOPBACK) || ifa->ifa_addr == NULL)
+			continue;
+
+		addr = ifa->ifa_addr;
+		address_text = NULL;
+		switch (addr->sa_family) {
+			case AF_INET:
+				address_text = inet_ntop(addr->sa_family, &((struct sockaddr_in *)addr)->sin_addr,
+					addrstr, sizeof(addrstr));
+				break;
+#ifdef PF_INET6
+			case AF_INET6:
+				address_text = inet_ntop(addr->sa_family, &((struct sockaddr_in6 *)addr)->sin6_addr,
+					addrstr, sizeof(addrstr));
+				break;
+#endif
+		}
+
+		if (address_text != NULL) {
+			if (addr->sa_family == AF_INET)
+				ips = g_slist_append(ips, g_strdup(address_text));
+			else
+				ips = g_slist_prepend(ips, g_strdup(address_text));
+		}
+	}
+
+	freeifaddrs(ifap);
+
+	}
+#else
+	{
 	char *tmp;
-	char *tip;
 	struct ifconf ifc;
 	struct ifreq *ifr;
+	char buffer[1024];
 	struct sockaddr_in *sinptr;
-	guint32 lhost = htonl(127 * 256 * 256 * 256 + 1);
-	long unsigned int add;
 	int source = fd;
-	int len, count = 0;
 
 	if (fd < 0)
 		source = socket(PF_INET, SOCK_STREAM, 0);
 
 	ifc.ifc_len = sizeof(buffer);
 	ifc.ifc_req = (struct ifreq *)buffer;
-	ioctl(source, SIOCGIFCONF, &ifc);
+	ret = ioctl(source, SIOCGIFCONF, &ifc);
 
 	if (fd < 0)
 		close(source);
 
-	memset(ip_ext, 0, sizeof(ip_ext));
-	memcpy(ip_ext, "0.0.0.0", 7);
+	if (ret < 0) {
+		const char *error = g_strerror(errno);
+		purple_debug_error("bonjour", "ioctl(SIOCGIFCONF) error: %s\n", error ? error : "(null)");
+		return NULL;
+	}
+
 	tmp = buffer;
-	tip = ip_ext;
-	while (tmp < buffer + ifc.ifc_len && count < 10)
-	{
+	while (tmp < buffer + ifc.ifc_len) {
 		ifr = (struct ifreq *)tmp;
 		tmp += HX_SIZE_OF_IFREQ(*ifr);
 
-		if (ifr->ifr_addr.sa_family == AF_INET)
-		{
+		if (ifr->ifr_addr.sa_family == AF_INET) {
 			sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
-			if (sinptr->sin_addr.s_addr != lhost)
-			{
-				add = ntohl(sinptr->sin_addr.s_addr);
-				len = g_snprintf(tip, 17, "%lu.%lu.%lu.%lu;",
-					((add >> 24) & 255),
-					((add >> 16) & 255),
-					((add >> 8) & 255),
-					add & 255);
-				tip = &tip[len];
-				count++;
-				continue;
+			if ((ntohl(sinptr->sin_addr.s_addr) >> 24) != 127) {
+				address_text = inet_ntoa(sinptr->sin_addr);
+				ips = g_slist_prepend(ips, g_strdup(address_text));
 			}
-		}
+ 		}
 	}
+	}
+#endif
 
-	return ip_ext;
+	return ips;
 }
--- a/libpurple/protocols/bonjour/jabber.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/bonjour/jabber.h	Mon Mar 01 03:46:33 2010 +0000
@@ -37,7 +37,9 @@
 {
 	gint port;
 	gint socket;
+	gint socket6;
 	gint watcher_id;
+	gint watcher_id6;
 	PurpleAccount *account;
 	GSList *pending_conversations;
 } BonjourJabber;
@@ -105,6 +107,6 @@
 
 XepIq *xep_iq_new(void *data, XepIqType type, const char *to, const char *from, const char *id);
 int xep_iq_send_and_free(XepIq *iq);
-const char *purple_network_get_my_ip_ext2(int fd);
+GSList * bonjour_jabber_get_local_ips(int fd);
 
 #endif /* _BONJOUR_JABBER_H_ */
--- a/libpurple/protocols/bonjour/mdns_avahi.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Mon Mar 01 03:46:33 2010 +0000
@@ -189,8 +189,12 @@
 					bb->ips = g_slist_remove(bb->ips, rd->ip);
 					g_free((gchar *) rd->ip);
 				}
-				bb->ips = g_slist_prepend(bb->ips, g_strdup(ip));
-				rd->ip = bb->ips->data;
+				rd->ip = g_strdup(ip);
+				/* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */
+				if (protocol == AVAHI_PROTO_INET6)
+					bb->ips = g_slist_prepend(bb->ips, (gchar *) rd->ip);
+				else
+					bb->ips = g_slist_append(bb->ips, (gchar *) rd->ip);
 			}
 
 			bb->port_p2pj = port;
@@ -249,7 +253,7 @@
 			/* Make sure it isn't us */
 			if (purple_utf8_strcasecmp(name, account->username) != 0) {
 				if (!avahi_service_resolver_new(avahi_service_browser_get_client(b),
-						interface, protocol, name, type, domain, AVAHI_PROTO_INET,
+						interface, protocol, name, type, domain, protocol,
 						0, _resolver_callback, account)) {
 					purple_debug_warning("bonjour", "_browser_callback -- Error initiating resolver: %s\n",
 						avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
@@ -448,14 +452,14 @@
 		case PUBLISH_START:
 			publish_result = avahi_entry_group_add_service_strlst(
 				idata->group, AVAHI_IF_UNSPEC,
-				AVAHI_PROTO_INET, 0,
+				AVAHI_PROTO_UNSPEC, 0,
 				purple_account_get_username(data->account),
 				LINK_LOCAL_RECORD_NAME, NULL, NULL, data->port_p2pj, lst);
 			break;
 		case PUBLISH_UPDATE:
 			publish_result = avahi_entry_group_update_service_txt_strlst(
 				idata->group, AVAHI_IF_UNSPEC,
-				AVAHI_PROTO_INET, 0,
+				AVAHI_PROTO_UNSPEC, 0,
 				purple_account_get_username(data->account),
 				LINK_LOCAL_RECORD_NAME, NULL, lst);
 			break;
@@ -487,7 +491,7 @@
 
 	g_return_val_if_fail(idata != NULL, FALSE);
 
-	idata->sb = avahi_service_browser_new(idata->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, LINK_LOCAL_RECORD_NAME, NULL, 0, _browser_callback, data->account);
+	idata->sb = avahi_service_browser_new(idata->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, LINK_LOCAL_RECORD_NAME, NULL, 0, _browser_callback, data->account);
 	if (!idata->sb) {
 
 		purple_debug_error("bonjour",
@@ -533,7 +537,7 @@
 				purple_account_get_username(data->account));
 
 		ret = avahi_entry_group_add_record(idata->buddy_icon_group, AVAHI_IF_UNSPEC,
-			AVAHI_PROTO_INET, flags, svc_name,
+			AVAHI_PROTO_UNSPEC, flags, svc_name,
 			AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 120, avatar_data, avatar_len);
 
 		g_free(svc_name);
@@ -622,7 +626,7 @@
 
 	name = g_strdup_printf("%s." LINK_LOCAL_RECORD_NAME "local", buddy->name);
 	idata->buddy_icon_rec_browser = avahi_record_browser_new(session_idata->client, AVAHI_IF_UNSPEC,
-		AVAHI_PROTO_INET, name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 0,
+		AVAHI_PROTO_UNSPEC, name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 0,
 		_buddy_icon_record_cb, buddy);
 	g_free(name);
 
--- a/libpurple/protocols/irc/irc.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/irc/irc.c	Mon Mar 01 03:46:33 2010 +0000
@@ -944,7 +944,8 @@
 	sizeof(PurplePluginProtocolInfo),    /* struct_size */
 	NULL,                    /* get_account_text_table */
 	NULL,                    /* initiate_media */
-	NULL					 /* can_do_media */
+	NULL,					 /* get_media_caps */
+	NULL					 /* get_moods */
 };
 
 static gboolean load_plugin (PurplePlugin *plugin) {
--- a/libpurple/protocols/jabber/jabber.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Mar 01 03:46:33 2010 +0000
@@ -70,6 +70,8 @@
 #include "jingle/jingle.h"
 #include "jingle/rtp.h"
 
+#define PING_TIMEOUT 60
+
 GList *jabber_features = NULL;
 GList *jabber_identities = NULL;
 static GSList *jabber_cmds = NULL;
@@ -521,9 +523,12 @@
 
 void jabber_keepalive(PurpleConnection *gc)
 {
-	JabberStream *js = gc->proto_data;
-
-	if (js->keepalive_timeout == 0) {
+	JabberStream *js = purple_connection_get_protocol_data(gc);
+	time_t now = time(NULL);
+
+	if (js->keepalive_timeout == 0 && (now - js->last_ping) >= PING_TIMEOUT) {
+		js->last_ping = now;
+
 		jabber_keepalive_ping(js);
 		js->keepalive_timeout = purple_timeout_add_seconds(120,
 				(GSourceFunc)(jabber_keepalive_timeout), gc);
@@ -2952,7 +2957,16 @@
 	gchar *error = NULL;
 
 	if (!_jabber_send_buzz(js, username, &error)) {
+		PurpleAccount *account = purple_connection_get_account(gc);
+		PurpleConversation *conv =
+			purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, username, account);
 		purple_debug_error("jabber", "jabber_send_attention: jabber_cmd_buzz failed with error: %s\n", error ? error : "(NULL)");
+
+		if (conv) {
+			purple_conversation_write(conv, username, error, PURPLE_MESSAGE_ERROR,
+			    time(NULL));
+		}
+
 		g_free(error);
 		return FALSE;
 	}
--- a/libpurple/protocols/jabber/jabber.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Mon Mar 01 03:46:33 2010 +0000
@@ -166,6 +166,11 @@
 	time_t idle;
 	time_t old_idle;
 
+	/** When we last pinged the server, so we don't ping more
+	 *  often than once every minute.
+	 */
+	time_t last_ping;
+
 	JabberID *user;
 	JabberBuddy *user_jb;
 
--- a/libpurple/protocols/jabber/pep.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/jabber/pep.c	Mon Mar 01 03:46:33 2010 +0000
@@ -89,10 +89,11 @@
 	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
 	xmlnode *pubsub, *items;
 
-	xmlnode_set_attrib(iq->node,"to",to);
+	if (to)
+		xmlnode_set_attrib(iq->node, "to", to);
+
 	pubsub = xmlnode_new_child(iq->node,"pubsub");
-
-	xmlnode_set_namespace(pubsub,"http://jabber.org/protocol/pubsub");
+	xmlnode_set_namespace(pubsub, "http://jabber.org/protocol/pubsub");
 
 	items = xmlnode_new_child(pubsub, "items");
 	xmlnode_set_attrib(items,"node",node);
--- a/libpurple/protocols/jabber/useravatar.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/jabber/useravatar.c	Mon Mar 01 03:46:33 2010 +0000
@@ -239,16 +239,12 @@
 
 void jabber_avatar_fetch_mine(JabberStream *js)
 {
-	char *jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
-
 	if (js->initial_avatar_hash) {
-		jabber_pep_request_item(js, jid, NS_AVATAR_0_12_METADATA, NULL,
+		jabber_pep_request_item(js, NULL, NS_AVATAR_0_12_METADATA, NULL,
 		                        do_got_own_avatar_0_12_cb);
-		jabber_pep_request_item(js, jid, NS_AVATAR_1_1_METADATA, NULL,
+		jabber_pep_request_item(js, NULL, NS_AVATAR_1_1_METADATA, NULL,
 		                        do_got_own_avatar_cb);
 	}
-
-	g_free(jid);
 }
 
 typedef struct _JabberBuddyAvatarUpdateURLInfo {
--- a/libpurple/protocols/jabber/usermood.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Mon Mar 01 03:46:33 2010 +0000
@@ -75,8 +75,8 @@
 	{"hungry", N_("Hungry"), NULL},
 	{"hurt", N_("Hurt"), NULL},
 	{"impressed", N_("Impressed"), NULL},
-	{"in_awe", N_("In_awe"), NULL},
-	{"in_love", N_("In_love"), NULL},
+	{"in_awe", N_("In awe"), NULL},
+	{"in_love", N_("In love"), NULL},
 	{"indignant", N_("Indignant"), NULL},
 	{"interested", N_("Interested"), NULL},
 	{"intoxicated", N_("Intoxicated"), NULL},
@@ -239,13 +239,14 @@
 void jabber_mood_set(JabberStream *js, const char *mood, const char *text) {
 	xmlnode *publish, *moodnode;
 
-	g_return_if_fail(mood != NULL);
-
 	publish = xmlnode_new("publish");
 	xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/mood");
 	moodnode = xmlnode_new_child(xmlnode_new_child(publish, "item"), "mood");
 	xmlnode_set_namespace(moodnode, "http://jabber.org/protocol/mood");
-	xmlnode_new_child(moodnode, mood);
+	if (mood) {
+		/* if mood is NULL, set an empty mood node, meaning: unset mood */
+	    xmlnode_new_child(moodnode, mood);
+	}
 
 	if (text && text[0] != '\0') {
 		xmlnode *textnode = xmlnode_new_child(moodnode, "text");
--- a/libpurple/protocols/jabber/usernick.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/jabber/usernick.c	Mon Mar 01 03:46:33 2010 +0000
@@ -86,14 +86,12 @@
 }
 
 static void do_nick_set_nick(PurplePluginAction *action) {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	JabberStream *js = gc->proto_data;
-	char *jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
+	PurpleConnection *gc = action->context;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	/* since the nickname might have been changed by another resource of this account, we always have to request the old one
 		from the server to present as the default for the new one */
-	jabber_pep_request_item(js, jid, "http://jabber.org/protocol/nick", NULL, do_nick_got_own_nick_cb);
-	g_free(jid);
+	jabber_pep_request_item(js, NULL, "http://jabber.org/protocol/nick", NULL, do_nick_got_own_nick_cb);
 }
 
 void jabber_nick_init(void) {
--- a/libpurple/protocols/msn/msn.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Mar 01 03:46:33 2010 +0000
@@ -2732,7 +2732,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	msn_get_account_text_table,             /* get_account_text_table */
 	NULL,                                   /* initiate_media */
-	NULL                                    /* can_do_media */
+	NULL,                                   /* get_media_caps */
+	NULL                                    /* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/msn/slp.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/msn/slp.c	Mon Mar 01 03:46:33 2010 +0000
@@ -308,8 +308,6 @@
 	return NULL;
 }
 
-#define MAX_FILE_NAME_LEN 0x226
-
 static void
 got_sessionreq(MsnSlpCall *slpcall, const char *branch,
 			   const char *euf_guid, const char *context)
@@ -382,7 +380,7 @@
 		/* File Transfer */
 		PurpleAccount *account;
 		PurpleXfer *xfer;
-		char *bin;
+		MsnFileContext *header;
 		gsize bin_len;
 		guint32 file_size;
 		char *file_name;
@@ -396,16 +394,18 @@
 
 		xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
 							 slpcall->slplink->remote_user);
-		if (xfer)
-		{
-			bin = (char *)purple_base64_decode(context, &bin_len);
-			file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8));
 
-			file_name = g_convert(bin + 20, MAX_FILE_NAME_LEN, "UTF-8", "UTF-16LE",
+		header = (MsnFileContext *)purple_base64_decode(context, &bin_len);
+		if (bin_len >= sizeof(MsnFileContext) - 1 &&
+			(header->version == 2 ||
+			 (header->version == 3 && header->length == sizeof(MsnFileContext) + 63))) {
+			file_size = GUINT64_FROM_LE(header->file_size);
+
+			file_name = g_convert((const gchar *)&header->file_name,
+			                      MAX_FILE_NAME_LEN * 2,
+			                      "UTF-8", "UTF-16LE",
 			                      NULL, NULL, NULL);
 
-			g_free(bin);
-
 			purple_xfer_set_filename(xfer, file_name ? file_name : "");
 			g_free(file_name);
 			purple_xfer_set_size(xfer, file_size);
@@ -424,6 +424,7 @@
 
 			purple_xfer_request(xfer);
 		}
+		g_free(header);
 
 		accepted = TRUE;
 
--- a/libpurple/protocols/msn/slp.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/msn/slp.h	Mon Mar 01 03:46:33 2010 +0000
@@ -30,6 +30,25 @@
 #include "session.h"
 #include "slpcall.h"
 
+#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
+
+/**
+ * The context data for a file transfer request
+ */
+#pragma pack(push,1) /* Couldn't they have made it the right size? */
+typedef struct
+{
+	guint32   length;       /*< Length of header */
+	guint32   version;      /*< MSN version */
+	guint64   file_size;    /*< Size of file */
+	guint32   type;         /*< Transfer type */
+	gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
+	gchar     unknown1[30]; /*< Used somehow for background sharing */
+	guint32   unknown2;     /*< Possibly for background sharing as well */
+	gchar     preview[1];   /*< File preview data, 96x96 PNG */
+} MsnFileContext;
+#pragma pack(pop)
+
 MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink,
 							  const char *body);
 
--- a/libpurple/protocols/msn/slplink.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/msn/slplink.c	Mon Mar 01 03:46:33 2010 +0000
@@ -307,6 +307,8 @@
 
 	slpmsg->offset += msg->msnslp_header.length;
 
+	slpmsg->msgs = g_list_remove(slpmsg->msgs, msg);
+
 	if (slpmsg->offset < real_size)
 	{
 		if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
@@ -331,8 +333,6 @@
 			}
 		}
 	}
-
-	slpmsg->msgs = g_list_remove(slpmsg->msgs, msg);
 }
 
 /* We have received the message nak. */
@@ -658,74 +658,51 @@
 	}
 }
 
-typedef struct
-{
-	guint32 length;
-	guint32 unk1;
-	guint32 file_size;
-	guint32 unk2;
-	guint32 unk3;
-} MsnContextHeader;
-
-#define MAX_FILE_NAME_LEN 0x226
-
 static gchar *
 gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
 {
 	gsize size = 0;
-	MsnContextHeader header;
+	MsnFileContext header;
 	gchar *u8 = NULL;
-	guchar *base;
-	guchar *n;
 	gchar *ret;
 	gunichar2 *uni = NULL;
 	glong currentChar = 0;
-	glong uni_len = 0;
-	gsize len;
+	glong len = 0;
 
 	size = purple_xfer_get_size(xfer);
 
-	if(!file_name) {
+	if (!file_name) {
 		gchar *basename = g_path_get_basename(file_path);
 		u8 = purple_utf8_try_convert(basename);
 		g_free(basename);
 		file_name = u8;
 	}
 
-	uni = g_utf8_to_utf16(file_name, -1, NULL, &uni_len, NULL);
+	uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL);
 
-	if(u8) {
+	if (u8) {
 		g_free(u8);
 		file_name = NULL;
 		u8 = NULL;
 	}
 
-	len = sizeof(MsnContextHeader) + MAX_FILE_NAME_LEN + 4;
-
-	header.length = GUINT32_TO_LE(len);
-	header.unk1 = GUINT32_TO_LE(2);
-	header.file_size = GUINT32_TO_LE(size);
-	header.unk2 = GUINT32_TO_LE(0);
-	header.unk3 = GUINT32_TO_LE(0);
-
-	base = g_malloc(len + 1);
-	n = base;
+	header.length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1);
+	header.version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */
+	header.file_size = GUINT64_TO_LE(size);
+	header.type = GUINT32_TO_LE(1);    /* No file preview */
 
-	memcpy(n, &header, sizeof(MsnContextHeader));
-	n += sizeof(MsnContextHeader);
+	len = MIN(len, MAX_FILE_NAME_LEN);
+	for (currentChar = 0; currentChar < len; currentChar++) {
+		header.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
+	}
+	memset(&header.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
 
-	memset(n, 0x00, MAX_FILE_NAME_LEN);
-	for(currentChar = 0; currentChar < uni_len; currentChar++) {
-		*((gunichar2 *)n + currentChar) = GUINT16_TO_LE(uni[currentChar]);
-	}
-	n += MAX_FILE_NAME_LEN;
-
-	memset(n, 0xFF, 4);
-	n += 4;
+	memset(&header.unknown1, 0, sizeof(header.unknown1));
+	header.unknown2 = GUINT32_TO_LE(0xffffffff);
+	header.preview[0] = '\0';
 
 	g_free(uni);
-	ret = purple_base64_encode(base, len);
-	g_free(base);
+	ret = purple_base64_encode((const guchar *)&header, sizeof(MsnFileContext));
 	return ret;
 }
 
--- a/libpurple/protocols/mxit/mxit.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.c	Mon Mar 01 03:46:33 2010 +0000
@@ -633,8 +633,9 @@
 	NULL,					/* attention_types */
 	sizeof( PurplePluginProtocolInfo ),		/* struct_size */
 	mxit_get_text_table,	/* get_account_text_table */
-	NULL,
-	NULL
+	NULL,					/* initiate_media */
+	NULL,					/* get_media_caps */
+	NULL					/* get_moods */
 };
 
 
--- a/libpurple/protocols/mxit/mxit.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.h	Mon Mar 01 03:46:33 2010 +0000
@@ -37,7 +37,9 @@
 #endif
 #elif defined( _WIN32 )
 /* windows architecture */
+#ifndef HOST_NAME_MAX
 #define		HOST_NAME_MAX				512
+#endif
 #include	"libc_interface.h"
 #elif defined( __linux__ )
 /* linux architecture */
--- a/libpurple/protocols/myspace/myspace.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Mon Mar 01 03:46:33 2010 +0000
@@ -3093,7 +3093,8 @@
 	sizeof(PurplePluginProtocolInfo), /* struct_size */
 	msim_get_account_text_table,              /* get_account_text_table */
 	NULL,                   /* initiate_media */
-	NULL                    /* can_do_media */
+	NULL,                   /* get_media_caps */
+	NULL                    /* get_moods */
 };
 
 /**
--- a/libpurple/protocols/novell/novell.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/novell/novell.c	Mon Mar 01 03:46:33 2010 +0000
@@ -3529,7 +3529,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,						/* get_account_text_table */
 	NULL,						/* initiate_media */
-	NULL						/* can_do_media */
+	NULL,						/* get_media_caps */
+	NULL						/* get_moods */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/protocols/oscar/flap_connection.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Mon Mar 01 03:46:33 2010 +0000
@@ -364,6 +364,12 @@
 		conn->connect_data = NULL;
 	}
 
+	if (conn->gsc != NULL && conn->gsc->connect_data != NULL)
+	{
+		purple_ssl_close(conn->gsc);
+		conn->gsc = NULL;
+	}
+
 	if (conn->new_conn_data != NULL)
 	{
 		if (conn->type == SNAC_FAMILY_CHAT)
--- a/libpurple/protocols/oscar/libaim.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/oscar/libaim.c	Mon Mar 01 03:46:33 2010 +0000
@@ -97,7 +97,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,					/* get_account_text_table */
 	NULL,					/* initiate_media */
-	NULL					/* can_do_media */
+	NULL,					/* get_media_caps */
+	NULL					/* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/oscar/oscar.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Mar 01 03:46:33 2010 +0000
@@ -185,7 +185,6 @@
 static int purple_parse_misses     (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_userinfo   (OscarData *, FlapConnection *, FlapFrame *, ...);
-static int purple_got_infoblock    (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_motd       (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_chatnav_info     (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_conv_chat_join        (OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -196,7 +195,6 @@
 static int purple_icon_parseicon   (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int oscar_icon_req        (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_msgack     (OscarData *, FlapConnection *, FlapFrame *, ...);
-static int purple_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...);
 static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -3595,55 +3593,6 @@
 	return 1;
 }
 
-static int purple_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
-{
-	PurpleConnection *gc = od->gc;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurpleBuddy *b;
-	PurplePresence *presence;
-	PurpleStatus *status;
-	gchar *message = NULL;
-
-	va_list ap;
-	aim_userinfo_t *userinfo;
-
-	va_start(ap, fr);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	b = purple_find_buddy(account, userinfo->bn);
-	if (b == NULL)
-		return 1;
-
-	if (!oscar_util_valid_name_icq(userinfo->bn))
-	{
-		if (strcmp(purple_buddy_get_name(b), userinfo->bn) != 0)
-			serv_got_alias(gc, purple_buddy_get_name(b), userinfo->bn);
-		else
-			serv_got_alias(gc, purple_buddy_get_name(b), NULL);
-	}
-
-	presence = purple_buddy_get_presence(b);
-	status = purple_presence_get_active_status(presence);
-
-	if (purple_status_is_online(status) && !purple_status_is_available(status) &&
-			userinfo->flags & AIM_FLAG_AWAY && userinfo->away_len > 0 &&
-			userinfo->away != NULL && userinfo->away_encoding != NULL)
-	{
-		gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
-		message = oscar_encoding_to_utf8(account, charset,
-		                                 userinfo->away,
-		                                 userinfo->away_len);
-		g_free(charset);
-		purple_prpl_got_user_status(account, userinfo->bn,
-				purple_status_get_id(status),
-				"message", message, NULL);
-		g_free(message);
-	}
-
-	return 1;
-}
-
 static int purple_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
 {
 	char *msg;
--- a/libpurple/protocols/oscar/oscar.h	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Mon Mar 01 03:46:33 2010 +0000
@@ -539,7 +539,6 @@
 
 	struct {
 		struct aim_userinfo_s *userinfo;
-		struct userinfo_node *requested;
 	} locate;
 
 	struct {
--- a/libpurple/protocols/qq/qq.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/qq/qq.c	Mon Mar 01 03:46:33 2010 +0000
@@ -1037,7 +1037,8 @@
 	sizeof(PurplePluginProtocolInfo), /* struct_size */
 	NULL,							/* get_account_text_table */
 	NULL,							/* initiate_media */
-	NULL                            /* can_do_media */
+	NULL,							/* get_media_caps */
+	NULL							/* get_moods */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/protocols/silc/silc.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/silc/silc.c	Mon Mar 01 03:46:33 2010 +0000
@@ -2116,7 +2116,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,				        /* get_account_text_table */
 	NULL,				        /* initiate_media */
-	NULL                        /* can_do_media */
+	NULL,				        /* get_media_caps */
+	NULL				        /* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/simple/simple.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/simple/simple.c	Mon Mar 01 03:46:33 2010 +0000
@@ -2086,7 +2086,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,					/* get_account_text_table */
 	NULL,					/* initiate_media */
-	NULL					/* can_do_media */
+	NULL,					/* get_media_caps */
+	NULL					/* get_moods */
 };
 
 
--- a/libpurple/protocols/yahoo/libyahoo.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/yahoo/libyahoo.c	Mon Mar 01 03:46:33 2010 +0000
@@ -264,7 +264,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	yahoo_get_account_text_table,    /* get_account_text_table */
 	NULL, /* initiate_media */
-	NULL  /* can_do_media */
+	NULL,  /* get_media_caps */
+	NULL   /* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/yahoo/libyahoojp.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/yahoo/libyahoojp.c	Mon Mar 01 03:46:33 2010 +0000
@@ -160,7 +160,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	yahoojp_get_account_text_table,    /* get_account_text_table */
 	NULL, /* initiate_media */
-	NULL  /* can_do_media */
+	NULL, /* get_media_caps */
+	NULL  /* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/zephyr/zephyr.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Mon Mar 01 03:46:33 2010 +0000
@@ -2908,7 +2908,8 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,					/* get_account_text_table */
 	NULL,					/* initate_media */
-	NULL					/* can_do_media */
+	NULL,					/* get_media_caps */
+	NULL					/* get_moods */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/win32/global.mak	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/win32/global.mak	Mon Mar 01 03:46:33 2010 +0000
@@ -15,7 +15,7 @@
 GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0-2.14
 GTK_BIN ?= $(GTK_TOP)/bin
 BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK
-LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.7.3
+LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.7.4
 MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2_daa2
 NSPR_TOP ?= $(WIN32_DEV_TOP)/nspr-4.6.4
 NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.11.4
@@ -103,7 +103,7 @@
 ifeq "$(origin CC)" "default"
   CC := gcc.exe
 endif
-GMSGFMT ?= $(GTK_BIN)/msgfmt
+GMSGFMT ?= $(WIN32_DEV_TOP)/gettext-0.17/bin/msgfmt
 MAKENSIS ?= makensis.exe
 MAKENSISOPT ?= /
 PERL ?= /cygdrive/c/perl/bin/perl
--- a/libpurple/win32/win32dep.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/libpurple/win32/win32dep.c	Mon Mar 01 03:46:33 2010 +0000
@@ -22,7 +22,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  *
  */
-#define _WIN32_IE 0x500
+#define _WIN32_IE 0x501
 #include "internal.h"
 #include <winuser.h>
 
--- a/pidgin/gtkblist.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/gtkblist.c	Mon Mar 01 03:46:33 2010 +0000
@@ -2660,39 +2660,30 @@
 
 /* Altered from do_colorshift in gnome-panel */
 static void
-do_alphashift (GdkPixbuf *dest, GdkPixbuf *src, int shift)
+do_alphashift(GdkPixbuf *pixbuf, int shift)
 {
 	gint i, j;
-	gint width, height, has_alpha, srcrowstride, destrowstride;
-	guchar *target_pixels;
-	guchar *original_pixels;
-	guchar *pixsrc;
-	guchar *pixdest;
+	gint width, height, padding;
+	guchar *pixels;
 	int val;
-	guchar a;
-
-	has_alpha = gdk_pixbuf_get_has_alpha (src);
-	if (!has_alpha)
+
+	if (!gdk_pixbuf_get_has_alpha(pixbuf))
 	  return;
 
-	width = gdk_pixbuf_get_width (src);
-	height = gdk_pixbuf_get_height (src);
-	srcrowstride = gdk_pixbuf_get_rowstride (src);
-	destrowstride = gdk_pixbuf_get_rowstride (dest);
-	target_pixels = gdk_pixbuf_get_pixels (dest);
-	original_pixels = gdk_pixbuf_get_pixels (src);
+	width = gdk_pixbuf_get_width(pixbuf);
+	height = gdk_pixbuf_get_height(pixbuf);
+	padding = gdk_pixbuf_get_rowstride(pixbuf) - width * 4;
+	pixels = gdk_pixbuf_get_pixels(pixbuf);
 
 	for (i = 0; i < height; i++) {
-		pixdest = target_pixels + i*destrowstride;
-		pixsrc = original_pixels + i*srcrowstride;
 		for (j = 0; j < width; j++) {
-			*(pixdest++) = *(pixsrc++);
-			*(pixdest++) = *(pixsrc++);
-			*(pixdest++) = *(pixsrc++);
-			a = *(pixsrc++);
-			val = a - shift;
-			*(pixdest++) = CLAMP(val, 0, 255);
-		}
+			pixels++;
+			pixels++;
+			pixels++;
+			val = *pixels - shift;
+			*(pixels++) = CLAMP(val, 0, 255);
+		}
+		pixels += padding;
 	}
 }
 
@@ -6367,7 +6358,7 @@
 		g_object_ref(G_OBJECT(gtkblist->empty_avatar));
 		avatar = gtkblist->empty_avatar;
 	} else if ((!PURPLE_BUDDY_IS_ONLINE(buddy) || purple_presence_is_idle(presence))) {
-		do_alphashift(avatar, avatar, 77);
+		do_alphashift(avatar, 77);
 	}
 
 	emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy);
@@ -7837,7 +7828,7 @@
 		const char *mood = purple_request_field_list_get_data(f, l->data);
 		PurpleAccount *account = purple_connection_get_account(gc);
 
-		if (mood != NULL) {
+		if (mood != NULL && !purple_strequal(mood, "")) {
 			purple_account_set_status(account, "mood", TRUE,
 			                          PURPLE_MOOD_NAME, mood,
 			                          NULL);
@@ -7856,11 +7847,10 @@
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *g;
 	PurpleRequestField *f;
-	char* na_fn;
 	PurpleConnection *gc = purple_account_get_connection(account);
 	PurplePluginProtocolInfo *prpl_info;
 	PurpleMood *mood;
-
+	
 	g_return_if_fail(gc->prpl != NULL);
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
 
@@ -7870,14 +7860,10 @@
 	g = purple_request_field_group_new(NULL);
 	f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
 
-	na_fn = g_build_filename("pixmaps", "pidgin", "emblems", "16", "not-authorized.png", NULL);
-
-	purple_request_field_list_add_icon(f, _("None"), na_fn, NULL);
+	purple_request_field_list_add(f, _("None"), "");
 	if (current_mood == NULL)
 		purple_request_field_list_add_selected(f, _("None"));
 
-	g_free(na_fn);
-
 	/* TODO: rlaager wants this sorted. */
 	for (mood = prpl_info->get_moods(account);
 	     mood->mood != NULL ; mood++) {
--- a/pidgin/gtkft.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/gtkft.c	Mon Mar 01 03:46:33 2010 +0000
@@ -575,7 +575,7 @@
 
 	/* Build the tree model */
 	/* Transfer type, Progress Bar, Filename, Size, Remaining */
-	model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_DOUBLE,
+	model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_INT,
 							   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 							   G_TYPE_POINTER);
 	dialog->model = model;
@@ -609,7 +609,7 @@
 	/* Progress bar column */
 	renderer = gtk_cell_renderer_progress_new();
 	column = gtk_tree_view_column_new_with_attributes(_("Progress"), renderer,
-				"percentage", COLUMN_PROGRESS, NULL);
+				"value", COLUMN_PROGRESS, NULL);
 	gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE);
 	gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
 
@@ -906,7 +906,7 @@
 	lfilename = utf8;
 	gtk_list_store_set(dialog->model, &data->iter,
 					   COLUMN_STATUS, pixbuf,
-					   COLUMN_PROGRESS, 0.0,
+					   COLUMN_PROGRESS, 0,
 					   COLUMN_FILENAME, (type == PURPLE_XFER_RECEIVE)
 					                     ? purple_xfer_get_filename(xfer)
 							     : lfilename,
@@ -1039,7 +1039,7 @@
 	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));
 
 	gtk_list_store_set(xfer_dialog->model, &data->iter,
-					   COLUMN_PROGRESS, purple_xfer_get_progress(xfer),
+					   COLUMN_PROGRESS, (gint)(purple_xfer_get_progress(xfer) * 100),
 					   COLUMN_SIZE, size_str,
 					   COLUMN_REMAINING, remaining_str,
 					   -1);
--- a/pidgin/pidginstock.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/pidginstock.c	Mon Mar 01 03:46:33 2010 +0000
@@ -270,37 +270,30 @@
 
 /* Altered from do_colorshift in gnome-panel */
 static void
-do_alphashift(GdkPixbuf *dest, GdkPixbuf *src)
+do_alphashift(GdkPixbuf *pixbuf)
 {
 	gint i, j;
-	gint width, height, has_alpha, srcrowstride, destrowstride;
-	guchar *target_pixels;
-	guchar *original_pixels;
-	guchar *pixsrc;
-	guchar *pixdest;
+	gint width, height, padding;
+	guchar *pixels;
 	guchar a;
 
-	has_alpha = gdk_pixbuf_get_has_alpha (src);
-	if (!has_alpha)
+	if (!gdk_pixbuf_get_has_alpha(pixbuf))
 		return;
 
-	width = gdk_pixbuf_get_width (src);
-	height = gdk_pixbuf_get_height (src);
-	srcrowstride = gdk_pixbuf_get_rowstride (src);
-	destrowstride = gdk_pixbuf_get_rowstride (dest);
-	target_pixels = gdk_pixbuf_get_pixels (dest);
-	original_pixels = gdk_pixbuf_get_pixels (src);
+	width = gdk_pixbuf_get_width(pixbuf);
+	height = gdk_pixbuf_get_height(pixbuf);
+	padding = gdk_pixbuf_get_rowstride(pixbuf) - width * 4;
+	pixels = gdk_pixbuf_get_pixels(pixbuf);
 
 	for (i = 0; i < height; i++) {
-		pixdest = target_pixels + i*destrowstride;
-		pixsrc = original_pixels + i*srcrowstride;
 		for (j = 0; j < width; j++) {
-			*(pixdest++) = *(pixsrc++);
-			*(pixdest++) = *(pixsrc++);
-			*(pixdest++) = *(pixsrc++);
-			a = *(pixsrc++);
-			*(pixdest++) = a / 2;
+			pixels++;
+			pixels++;
+			pixels++;
+			a = *(pixels);
+			*(pixels++) = a / 2;
 		}
+		pixels += padding;
 	}
 }
 
@@ -348,7 +341,7 @@
 	g_return_if_fail(filename != NULL);
 	pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
 	if (translucent)
-		do_alphashift(pixbuf, pixbuf);
+		do_alphashift(pixbuf);
 
 	source = gtk_icon_source_new();
 	gtk_icon_source_set_pixbuf(source, pixbuf);
@@ -378,7 +371,7 @@
 		g_return_if_fail(filename != NULL);
 		pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
 		if (translucent)
-			do_alphashift(pixbuf, pixbuf);
+			do_alphashift(pixbuf);
 
 		source = gtk_icon_source_new();
 		gtk_icon_source_set_pixbuf(source, pixbuf);
--- a/pidgin/pixmaps/Makefile.am	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/pixmaps/Makefile.am	Mon Mar 01 03:46:33 2010 +0000
@@ -203,7 +203,7 @@
 		emotes/default/24/scalable/yin-yang.svg
 
 EMOTES_SMALL_16_SCALABLE = \
-		emotes/small/16/scalable/mobile.svg
+		emotes/small/16/scalable/mobile.svg \
 		emotes/small/16/scalable/pidgin-emotes.svg
 
 PROTOCOLS_16_SCALABLE = \
--- a/pidgin/plugins/gtkbuddynote.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/plugins/gtkbuddynote.c	Mon Mar 01 03:46:33 2010 +0000
@@ -31,11 +31,13 @@
 		const gchar *note = purple_blist_node_get_string(node, "notes");
 
 		if ((note != NULL) && (*note != '\0')) {
-			char *tmp;
+			char *tmp, *esc;
 			purple_markup_html_to_xhtml(note, NULL, &tmp);
+			esc = g_markup_escape_text(tmp, -1);
+			g_free(tmp);
 			g_string_append_printf(text, _("\n<b>Buddy Note</b>: %s"),
-			                       tmp);
-			g_free(tmp);
+			                       esc);
+			g_free(esc);
 		}
 	}
 }
--- a/pidgin/plugins/xmppconsole.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/plugins/xmppconsole.c	Mon Mar 01 03:46:33 2010 +0000
@@ -621,7 +621,7 @@
 }
 
 static void
-signed_on_cb(PurpleConnection *gc)
+signing_on_cb(PurpleConnection *gc)
 {
 	if (!console)
 		return;
@@ -630,7 +630,9 @@
 	console->accounts = g_list_append(console->accounts, gc);
 	console->count++;
 
-	if (console->count > 1)
+	if (console->count == 1)
+		console->gc = gc;
+	else
 		gtk_widget_show_all(console->hbox);
 }
 
@@ -680,8 +682,8 @@
 			    PURPLE_CALLBACK(xmlnode_received_cb), NULL);
 	purple_signal_connect(jabber, "jabber-sending-text", xmpp_console_handle,
 			    PURPLE_CALLBACK(xmlnode_sent_cb), NULL);
-	purple_signal_connect(purple_connections_get_handle(), "signed-on",
-			    plugin, PURPLE_CALLBACK(signed_on_cb), NULL);
+	purple_signal_connect(purple_connections_get_handle(), "signing-on",
+			    plugin, PURPLE_CALLBACK(signing_on_cb), NULL);
 	purple_signal_connect(purple_connections_get_handle(), "signed-off",
 			    plugin, PURPLE_CALLBACK(signed_off_cb), NULL);
 
--- a/pidgin/win32/gtkwin32dep.c	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/win32/gtkwin32dep.c	Mon Mar 01 03:46:33 2010 +0000
@@ -375,11 +375,27 @@
 }
 
 void winpidgin_init(HINSTANCE hint) {
+	FARPROC proc;
 
 	purple_debug_info("winpidgin", "winpidgin_init start\n");
 
 	exe_hInstance = hint;
 
+	proc = wpurple_find_and_loadproc("exchndl.dll", "SetLogFile");
+	if (proc) {
+		gchar *debug_dir, *locale_debug_dir;
+		
+		debug_dir = g_build_filename(purple_user_dir(), "pidgin.RPT", NULL);
+		locale_debug_dir = g_locale_from_utf8(debug_dir, -1, NULL, NULL, NULL);
+
+		purple_debug_info("winpidgin", "Setting exchndl.dll LogFile to %s\n", debug_dir);
+
+		(proc)(locale_debug_dir);
+
+		g_free(debug_dir);
+		g_free(locale_debug_dir);
+	}
+
 	/* IdleTracker Initialization */
 	if(!winpidgin_set_idlehooks())
 		purple_debug_error("winpidgin", "Failed to initialize idle tracker\n");
--- a/pidgin/win32/nsis/langmacros.nsh	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/win32/nsis/langmacros.nsh	Mon Mar 01 03:46:33 2010 +0000
@@ -91,8 +91,10 @@
   !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_SPELLCHECK_SWEDISH		${CUR_LANG}
   !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_SPELLCHECK_UKRAINIAN		${CUR_LANG}
 
-  !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_DEBUGSYMBOLS_ERROR ${CUR_LANG}
-  !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_GTK_DOWNLOAD_ERROR ${CUR_LANG}
+  !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_DEBUGSYMBOLS_ERROR		${CUR_LANG}
+  !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_GTK_DOWNLOAD_ERROR		${CUR_LANG}
+
+  !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT TRANSLATIONS_SECTION_TITLE	${CUR_LANG}
 
   !undef CUR_LANG
 !macroend
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Mon Mar 01 03:46:33 2010 +0000
@@ -53,7 +53,7 @@
 ;Defines
 
 !define PIDGIN_NSIS_INCLUDE_PATH		"."
-!define PIDGIN_INSTALLER_DEPS			"..\..\..\..\win32-dev\pidgin-inst-deps-0.2"
+!define PIDGIN_INSTALLER_DEPS			"..\..\..\..\win32-dev\pidgin-inst-deps-20100223"
 
 ; Remove these and the stuff that uses them at some point
 !define OLD_GAIM_REG_KEY			"SOFTWARE\gaim"
@@ -352,12 +352,11 @@
   Pop $R0
   StrCmp $R0 "cancel" done
   StrCmp $R0 "success" +2
-    MessageBox MB_RETRYCANCEL "$(PIDGIN_GTK_DOWNLOAD_ERROR) : $R1" /SD IDCANCEL IDRETRY retry IDCANCEL done
+    MessageBox MB_RETRYCANCEL "$(PIDGIN_GTK_DOWNLOAD_ERROR) : $R2" /SD IDCANCEL IDRETRY retry IDCANCEL done
 
 !endif
 
   SetOutPath "$INSTDIR"
-
   nsisunz::UnzipToLog $R1 "$INSTDIR"
   Pop $R0
   StrCmp $R0 "success" +2
@@ -610,17 +609,17 @@
 SectionGroupEnd
 
 Section /o $(DEBUG_SYMBOLS_SECTION_TITLE) SecDebugSymbols
+  
   InitPluginsDir
-
-  ; We need to download and extract the debug symbols
-  StrCpy $R1 "$PLUGINSDIR\pidgin-${PIDGIN_VERSION}-dbgsym.zip"
+  StrCpy $R1 "$PLUGINSDIR\dbgsym.zip"
 !ifdef OFFLINE_INSTALLER
 
   SetOutPath $PLUGINSDIR
-  File /oname=pidgin-${PIDGIN_VERSION}-dbgsym.zip "..\..\..\..\gtk_installer\gtk-runtime-${GTK_INSTALL_VERSION}.zip"
+  File /oname=dbgsym.zip "..\..\..\pidgin-${PIDGIN_VERSION}-dbgsym.zip"
 
 !else
 
+  ; We need to download the debug symbols
   retry:
   StrCpy $R2 "${DOWNLOADER_URL}?version=${PIDGIN_VERSION}&dl_pkg=dbgsym"
   DetailPrint "Downloading Debug Symbols... ($R2)"
@@ -632,6 +631,7 @@
 
 !endif
 
+  SetOutPath "$INSTDIR"
   nsisunz::UnzipToLog $R1 "$INSTDIR"
   Pop $R0
   StrCmp $R0 "success" +2
@@ -779,7 +779,7 @@
     Delete "$INSTDIR\libsasl.dll"
     Delete "$INSTDIR\libsilc-1-1-2.dll"
     Delete "$INSTDIR\libsilcclient-1-1-2.dll"
-    Delete "$INSTDIR\libxml2.dll"
+    Delete "$INSTDIR\libxml2-2.dll"
     Delete "$INSTDIR\libymsg.dll"
     Delete "$INSTDIR\nspr4.dll"
     Delete "$INSTDIR\nss3.dll"
@@ -801,7 +801,7 @@
     ; Remove the local GTK+ copy (if we're not just upgrading)
     ${GetParameters} $R0
     ClearErrors
-    ${GetOptions} "$R3" "/KEEPGTK=" $R1
+    ${GetOptions} "$R0" "/KEEPGTK=" $R1
     IfErrors +2
     StrCmp $R1 "1" +2
     RMDir /r "$INSTDIR\Gtk"
@@ -1368,6 +1368,10 @@
   Push $R0
   Push $R1
 
+!ifdef OFFLINE_INSTALLER
+    !insertmacro SelectSection ${SecDebugSymbols}
+!endif
+
   Call DoWeNeedGtk
   Pop $R0
   IntCmp $R0 1 done gtk_not_mandatory
--- a/pidgin/win32/nsis/translations/english.nsh	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/win32/nsis/translations/english.nsh	Mon Mar 01 03:46:33 2010 +0000
@@ -25,13 +25,14 @@
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SHORTCUTS_SECTION_TITLE		"Shortcuts"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE	"Desktop"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE	"Start Menu"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING TRANSLATIONS_SECTION_TITLE		"Localizations"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SECTION_DESCRIPTION		"Core Pidgin files and dlls"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_SECTION_DESCRIPTION		"A multi-platform GUI toolkit, used by Pidgin"
 
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SHORTCUTS_SECTION_DESCRIPTION	"Shortcuts for starting Pidgin"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DESKTOP_SHORTCUT_DESC		"Create a shortcut to Pidgin on the Desktop"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_STARTMENU_SHORTCUT_DESC		"Create a Start Menu entry for Pidgin"
-!insertmacro PIDGIN_MACRO_DEFAULT_STRING DEBUG_SYMBOLS_SECTION_TITLE "Debug Symbols (for reporting crashes)"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING DEBUG_SYMBOLS_SECTION_TITLE		"Debug Symbols (for reporting crashes)"
 
 ; GTK+ Directory Page
 
@@ -79,6 +80,7 @@
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SPELLCHECK_SWEDISH		"Swedish"
 !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SPELLCHECK_UKRAINIAN		"Ukrainian"
 
-!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DEBUGSYMBOLS_ERROR "Error Installing Debug Symbols"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DEBUGSYMBOLS_ERROR		"Error Installing Debug Symbols"
 
-!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_GTK_DOWNLOAD_ERROR "Error Downloading the GTK+ Runtime"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_GTK_DOWNLOAD_ERROR		"Error Downloading the GTK+ Runtime"
+
--- a/pidgin/win32/nsis/translations/norwegian_nynorsk.nsh	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/win32/nsis/translations/norwegian_nynorsk.nsh	Mon Mar 01 03:46:33 2010 +0000
@@ -9,7 +9,6 @@
 ; Startup Checks
 !define INSTALLER_IS_RUNNING			"Installasjonsprogrammet kjører allereie."
 !define PIDGIN_IS_RUNNING			"Pidgin kjører no. Lukk programmet og prøv igjen."
-!define GTK_INSTALLER_NEEDED			"GTK+-kjøremiljøet manglar eller treng å bli oppdatert.$\rInstaller v${GTK_MIN_VERSION} eller nyare av GTK+-kjøremiljøet"
 
 ; License Page
 !define PIDGIN_LICENSE_BUTTON			"Neste >"
@@ -28,20 +27,12 @@
 !define PIDGIN_DESKTOP_SHORTCUT_DESC		"Lag ein snarveg til Pidgin på skrivebordet"
 !define PIDGIN_STARTMENU_SHORTCUT_DESC		"Lag ein snarveg til Pidgin på startmenyen"
 
-; GTK+ Directory Page
-!define GTK_UPGRADE_PROMPT			"Fann ei gammal utgåve av GTK+-kjøremiljøet. Vil du oppdatera ho?$\rMerk: $(^Name) vil kanskje ikkje fungera om du ikkje oppdaterer."
-!define GTK_WINDOWS_INCOMPATIBLE		"Windows 95/98/Me er ikkje kompatibelt med GTK+ 2.8.0 eller nyare. GTK+ ${GTK_INSTALL_VERSION} kjem ikkje til å bli installert.$\rInstallasjonen vil bli abvroten om ikkje GTK+ ${GTK_MIN_VERSION} eller nyare allereie er installert."
-
 ; Installer Finish Page
 !define PIDGIN_FINISH_VISIT_WEB_SITE		"Besøk Pidgin si nettside"
 
 ; Pidgin Section Prompts and Texts
 !define PIDGIN_PROMPT_CONTINUE_WITHOUT_UNINSTALL	"Klarte ikkje å avinstallera Pidgin-utgåva som er i bruk. Den nye utgåva kjem til å bli installert utan å ta vekk den gjeldande."
 
-; GTK+ Section Prompts
-!define GTK_INSTALL_ERROR			"Klarte ikkje å installera GTK+-kjøremiljøet."
-!define GTK_BAD_INSTALL_PATH			"Klarer ikkje å laga eller få tilgang til bana du skreiv."
-
 ; URL Handler section
 !define URI_HANDLERS_SECTION_TITLE		"URI-referanse"
 
--- a/pidgin/win32/nsis/translations/polish.nsh	Wed Feb 24 02:30:35 2010 +0000
+++ b/pidgin/win32/nsis/translations/polish.nsh	Mon Mar 01 03:46:33 2010 +0000
@@ -25,17 +25,9 @@
 !define PIDGIN_DESKTOP_SHORTCUT_DESC		"Utworzenie skrótu do programu Pidgin na pulpicie"
 !define PIDGIN_STARTMENU_SHORTCUT_DESC		"Utworzenie wpisu w menu Start dla programu Pidgin"
 
-; GTK+ Directory Page
-!define GTK_UPGRADE_PROMPT			"Odnaleziono star¹ wersjê biblioteki GTK+. Zaktualizowaæ j¹?$\rUwaga: program $(^Name) mo¿e bez tego nie dzia³aæ."
-!define GTK_WINDOWS_INCOMPATIBLE		"Systemy Windows 95/98/Me s¹ niezgodne z bibliotek¹ GTK+ 2.8.0 lub nowsz¹. Biblioteka GTK+ ${GTK_INSTALL_VERSION} nie zostanie zainstalowana.$\rJeœli brak zainstalowanej biblioteki GTK+ ${GTK_MIN_VERSION} lub nowszej, instalacja zostanie przerwana."
-
 ; Installer Finish Page
 !define PIDGIN_FINISH_VISIT_WEB_SITE		"OdwiedŸ stronê WWW programu Pidgin"
 
-; GTK+ Section Prompts
-!define GTK_INSTALL_ERROR			"B³¹d podczas instalowania biblioteki GTK+."
-!define GTK_BAD_INSTALL_PATH			"Nie mo¿na uzyskaæ dostêpu do podanej œcie¿ki lub jej utworzyæ."
-
 ; Uninstall Section Prompts
 !define un.PIDGIN_UNINSTALL_ERROR_1		"Instalator nie mo¿e odnaleŸæ wpisów w rejestrze dla programu Pidgin.$\rMo¿liwe, ¿e inny u¿ytkownik zainstalowa³ ten program."
-!define un.PIDGIN_UNINSTALL_ERROR_2		"Brak uprawnieñ do odinstalowania tego programu."
\ No newline at end of file
+!define un.PIDGIN_UNINSTALL_ERROR_2		"Brak uprawnieñ do odinstalowania tego programu."