propagate from branch 'im.pidgin.pidgin' (head ad7890a74433d4988573c3314dc452b0010f21d4) cpw.rekkanoryo.ggupdate

Mon, 01 Mar 2010 03:46:33 +0000

author
John Bailey <rekkanoryo@rekkanoryo.org>
date
Mon, 01 Mar 2010 03:46:33 +0000
branch
cpw.rekkanoryo.ggupdate
changeset 29793
bcee77415e77
parent 29792
ad7890a74433 (diff)
parent 29753
4101af714b47 (current diff)
child 29802
39e57b941184

propagate from branch 'im.pidgin.pidgin' (head ad7890a74433d4988573c3314dc452b0010f21d4)
to branch 'im.pidgin.cpw.rekkanoryo.ggupdate' (head 4101af714b47fdba8a010bef0ca5b10eb6b95aec)

--- 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);