changeset 29733:356d1f40a56d

propagate from branch 'im.pidgin.pidgin' (head fc93e0ea1ceae4b0e76c50e35965814711dc1c00) to branch 'im.pidgin.pidgin.next.minor' (head bca91e5200ed5372978a121437fd19fe2774c583)
author Will Thompson <will.thompson@collabora.co.uk>
date Sun, 20 Dec 2009 17:17:10 +0000
parents f8e29cf10629 (current diff) 4066bd054421 (diff)
children 1d969bd224f2
files ChangeLog libpurple/conversation.h libpurple/media.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/si.c libpurple/protocols/myspace/user.c pidgin/gtkcelllayout.c pidgin/gtkcelllayout.h pidgin/gtkcellrendererprogress.c pidgin/gtkcellrendererprogress.h pidgin/gtkcellview.c pidgin/gtkcellview.h pidgin/gtkcellviewmenuitem.c pidgin/gtkcellviewmenuitem.h pidgin/gtkdialogs.c pidgin/gtkexpander.c pidgin/gtkexpander.h pidgin/pidgincombobox.c pidgin/pidgincombobox.h pidgin/pixmaps/tray/16/tray-away.png pidgin/pixmaps/tray/16/tray-busy.png pidgin/pixmaps/tray/16/tray-connecting.png pidgin/pixmaps/tray/16/tray-extended-away.png pidgin/pixmaps/tray/16/tray-invisible.png pidgin/pixmaps/tray/16/tray-message.png pidgin/pixmaps/tray/16/tray-new-im.png pidgin/pixmaps/tray/16/tray-offline.png pidgin/pixmaps/tray/16/tray-online.png pidgin/pixmaps/tray/22/tray-away.png pidgin/pixmaps/tray/22/tray-busy.png pidgin/pixmaps/tray/22/tray-connecting.png pidgin/pixmaps/tray/22/tray-extended-away.png pidgin/pixmaps/tray/22/tray-invisible.png pidgin/pixmaps/tray/22/tray-message.png pidgin/pixmaps/tray/22/tray-new-im.png pidgin/pixmaps/tray/22/tray-offline.png pidgin/pixmaps/tray/22/tray-online.png pidgin/pixmaps/tray/32/tray-away.png pidgin/pixmaps/tray/32/tray-busy.png pidgin/pixmaps/tray/32/tray-connecting.png pidgin/pixmaps/tray/32/tray-extended-away.png pidgin/pixmaps/tray/32/tray-invisible.png pidgin/pixmaps/tray/32/tray-message.png pidgin/pixmaps/tray/32/tray-new-im.png pidgin/pixmaps/tray/32/tray-offline.png pidgin/pixmaps/tray/32/tray-online.png pidgin/pixmaps/tray/48/tray-away.png pidgin/pixmaps/tray/48/tray-busy.png pidgin/pixmaps/tray/48/tray-connecting.png pidgin/pixmaps/tray/48/tray-extended-away.png pidgin/pixmaps/tray/48/tray-invisible.png pidgin/pixmaps/tray/48/tray-message.png pidgin/pixmaps/tray/48/tray-new-im.png pidgin/pixmaps/tray/48/tray-offline.png pidgin/pixmaps/tray/48/tray-online.png
diffstat 26 files changed, 255 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Dec 11 03:09:31 2009 +0000
+++ b/ChangeLog	Sun Dec 20 17:17:10 2009 +0000
@@ -19,6 +19,10 @@
 	  it look and behave like the search dialog in Firefox)
 
 version 2.6.5 (??/??/20??):
+	libpurple:
+	* TLS certificates are actually stored to the local cache once again
+	  (accepting a name mismatch on a certificate should now be remembered)
+
 	General:
 	* Build-time fixes for Solaris.  (Paul Townsend)
 
@@ -26,6 +30,14 @@
 	* Messages from some mobile clients are no longer displayed as
 	  Chinese characters (broken in 2.6.4)
 
+	MSN:
+	* File transfer requests will no longer cause a crash if you delete the
+	  file before the other side accepts.
+	* Recieved files will no longer hold an extra lock after completion,
+	  meaning they can be moved or deleted without complaints from your OS.
+	* Buddies who sign in from a second location will no longer cause an
+	  unnecessary chat window to open.
+
 	XMPP:
 	* Added support for the SCRAM-SHA-1 SASL mechanism.  This is only
 	  available when built without Cyrus SASL support.
@@ -33,7 +45,8 @@
 	  (when given by the result of the "last query") and don't show status as
 	  offline.
 	* Do not crash when attempting to register for a new account on Windows.
-	* Added support for Roster Versioning (XEP-0237).
+	* Fix file transfer with clients that do not support Entity Capabilities
+	  (e.g. Spark)
 
 version 2.6.4 (11/29/2009):
 	libpurple:
--- a/libpurple/certificate.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/certificate.c	Sun Dec 20 17:17:10 2009 +0000
@@ -1431,9 +1431,8 @@
 	tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,
 						 "tls_peers");
 	if (tls_peers) {
-		if (!purple_certificate_pool_contains(tls_peers, vrq->subject_name) &&
-		        !purple_certificate_pool_store(tls_peers,vrq->subject_name,
-		                                       peer_crt)) {
+		if (!purple_certificate_pool_store(tls_peers,vrq->subject_name,
+		                                   peer_crt)) {
 			purple_debug_error("certificate/x509/tls_cached",
 			                   "FAILED to cache peer certificate\n");
 		}
--- a/libpurple/conversation.h	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/conversation.h	Sun Dec 20 17:17:10 2009 +0000
@@ -1024,7 +1024,8 @@
 GList *purple_conv_chat_set_users(PurpleConvChat *chat, GList *users);
 
 /**
- * Returns a list of users in the chat room.
+ * Returns a list of users in the chat room.  The members of the list
+ * are PurpleConvChatBuddy objects.
  *
  * @param chat The chat.
  *
--- a/libpurple/protocols/jabber/jabber.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sun Dec 20 17:17:10 2009 +0000
@@ -639,10 +639,11 @@
 	js->srv_query_data = NULL;
 
 	if (responses == NULL) {
+		purple_debug_warning("jabber", "Unable to find alternative XMPP connection "
+				  "methods after failing to connect directly.");
 		purple_connection_error_reason(js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Unable to find alternative XMPP connection "
-				  "methods after failing to connect directly."));
+				_("Unable to connect"));
 		return;
 	}
 
--- a/libpurple/protocols/jabber/jingle/jingle.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/jabber/jingle/jingle.c	Sun Dec 20 17:17:10 2009 +0000
@@ -29,12 +29,13 @@
 #include "content.h"
 #include "debug.h"
 #include "jingle.h"
-#include <string.h>
 #include "session.h"
 #include "iceudp.h"
 #include "rawudp.h"
 #include "rtp.h"
 
+#include <string.h>
+
 GType
 jingle_get_type(const gchar *type)
 {
--- a/libpurple/protocols/jabber/roster.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/jabber/roster.c	Sun Dec 20 17:17:10 2009 +0000
@@ -77,16 +77,13 @@
 void jabber_roster_request(JabberStream *js)
 {
 	PurpleAccount *account;
-	const char *ver;
 	JabberIq *iq;
 	xmlnode *query;
 
 	account = purple_connection_get_account(js->gc);
-	ver = purple_account_get_string(account, "roster_ver", "");
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
 	query = xmlnode_get_child(iq->node, "query");
-	xmlnode_set_attrib(query, "ver", ver);
 
 	if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
 		xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
@@ -223,18 +220,18 @@
 			continue;
 
 		if(subscription) {
-			if (jb == js->user_jb)
+			if (g_str_equal(subscription, "remove"))
+				jb->subscription = JABBER_SUB_REMOVE;
+			else if (jb == js->user_jb)
 				jb->subscription = JABBER_SUB_BOTH;
-			else if(!strcmp(subscription, "none"))
+			else if (g_str_equal(subscription, "none"))
 				jb->subscription = JABBER_SUB_NONE;
-			else if(!strcmp(subscription, "to"))
+			else if (g_str_equal(subscription, "to"))
 				jb->subscription = JABBER_SUB_TO;
-			else if(!strcmp(subscription, "from"))
+			else if (g_str_equal(subscription, "from"))
 				jb->subscription = JABBER_SUB_FROM;
-			else if(!strcmp(subscription, "both"))
+			else if (g_str_equal(subscription, "both"))
 				jb->subscription = JABBER_SUB_BOTH;
-			else if(!strcmp(subscription, "remove"))
-				jb->subscription = JABBER_SUB_REMOVE;
 		}
 
 		if(purple_strequal(ask, "subscribe"))
--- a/libpurple/protocols/jabber/si.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/jabber/si.c	Sun Dec 20 17:17:10 2009 +0000
@@ -1456,7 +1456,7 @@
 	g_free(xfer->who);
 	xfer->who = who;
 
-	if (jbr) {
+	if (jbr && jabber_resource_know_capabilities(jbr)) {
 		char *msg;
 
 		if (jabber_resource_has_capability(jbr, NS_IBB))
--- a/libpurple/protocols/msn/slp.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slp.c	Sun Dec 20 17:17:10 2009 +0000
@@ -126,22 +126,60 @@
 			g_free(content);
 			msn_slplink_send_queued_slpmsgs(slpcall->slplink);
 
-			msn_slpcall_destroy(slpcall);
+			if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
+				slpcall->wasted = TRUE;
+			else
+				msn_slpcall_destroy(slpcall);
 		}
 	}
 }
 
-void
-msn_xfer_progress_cb(MsnSlpCall *slpcall, gsize total_length, gsize len, gsize offset)
+gssize
+msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer)
 {
-	PurpleXfer *xfer;
+	MsnSlpCall *slpcall;
+
+	g_return_val_if_fail(xfer != NULL, -1);
+	g_return_val_if_fail(data != NULL, -1);
+	g_return_val_if_fail(len > 0, -1);
+
+	g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1);
+
+	slpcall = xfer->data;
+	/* Not sure I trust it'll be there */
+	g_return_val_if_fail(slpcall != NULL, -1);
+
+	g_return_val_if_fail(slpcall->xfer_msg != NULL, -1);
+
+	slpcall->u.outgoing.len = len;
+	slpcall->u.outgoing.data = data;
+	msn_slplink_send_msgpart(slpcall->slplink, slpcall->xfer_msg);
+	return MIN(1202, len);
+}
 
-	xfer = slpcall->xfer;
+gssize
+msn_xfer_read(guchar **data, PurpleXfer *xfer)
+{
+	MsnSlpCall *slpcall;
+	gsize len;
+
+	g_return_val_if_fail(xfer != NULL, -1);
+	g_return_val_if_fail(data != NULL, -1);
+
+	g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1);
 
-	xfer->bytes_sent = (offset + len);
-	xfer->bytes_remaining = total_length - (offset + len);
+	slpcall = xfer->data;
+	/* Not sure I trust it'll be there */
+	g_return_val_if_fail(slpcall != NULL, -1);
 
-	purple_xfer_update_progress(xfer);
+	/* Just pass up the whole GByteArray. We'll make another. */
+	*data = slpcall->u.incoming_data->data;
+	len = slpcall->u.incoming_data->len;
+
+	g_byte_array_free(slpcall->u.incoming_data, FALSE);
+	slpcall->u.incoming_data = g_byte_array_new();
+
+	return len;
 }
 
 void
@@ -332,9 +370,7 @@
 
 		account = slpcall->slplink->session->account;
 
-		slpcall->cb = msn_xfer_completed_cb;
 		slpcall->end_cb = msn_xfer_end_cb;
-		slpcall->progress_cb = msn_xfer_progress_cb;
 		slpcall->branch = g_strdup(branch);
 
 		slpcall->pending = TRUE;
@@ -357,6 +393,10 @@
 			purple_xfer_set_init_fnc(xfer, msn_xfer_init);
 			purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
 			purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
+			purple_xfer_set_read_fnc(xfer, msn_xfer_read);
+			purple_xfer_set_write_fnc(xfer, msn_xfer_write);
+
+			slpcall->u.incoming_data = g_byte_array_new();
 
 			slpcall->xfer = xfer;
 			purple_xfer_ref(slpcall->xfer);
--- a/libpurple/protocols/msn/slp.h	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slp.h	Sun Dec 20 17:17:10 2009 +0000
@@ -29,9 +29,6 @@
 #include "internal.h"
 #include "ft.h"
 
-void msn_xfer_progress_cb(MsnSlpCall *slpcall, gsize total_length, gsize
-						  len, gsize offset);
-
 MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink,
 							  const char *body);
 
@@ -41,6 +38,9 @@
 						   const guchar *body, gsize size);
 
 void msn_xfer_cancel(PurpleXfer *xfer);
+gssize msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer);
+gssize msn_xfer_read(guchar **data, PurpleXfer *xfer);
+
 void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session);
 
 void msn_queue_buddy_icon_request(MsnUser *user);
--- a/libpurple/protocols/msn/slpcall.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Sun Dec 20 17:17:10 2009 +0000
@@ -105,10 +105,13 @@
 		slpcall->end_cb(slpcall, slpcall->slplink->session);
 
 	if (slpcall->xfer != NULL) {
+		if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE)
+			g_byte_array_free(slpcall->u.incoming_data, TRUE);
 		slpcall->xfer->data = NULL;
 		purple_xfer_unref(slpcall->xfer);
 	}
 
+
 	msn_slplink_remove_slpcall(slpcall->slplink, slpcall);
 
 	g_free(slpcall->id);
@@ -272,7 +275,8 @@
 				slpcall->timer = 0;
 			}
 
-			slpcall->cb(slpcall, body, body_len);
+			if (slpcall->cb)
+				slpcall->cb(slpcall, body, body_len);
 
 			slpcall->wasted = TRUE;
 		}
--- a/libpurple/protocols/msn/slpcall.h	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slpcall.h	Sun Dec 20 17:17:10 2009 +0000
@@ -72,6 +72,14 @@
 	char *data_info;
 
 	PurpleXfer *xfer;
+	union {
+		GByteArray *incoming_data;
+		struct {
+			gsize len;
+			const guchar *data;
+		} outgoing;
+	} u;
+	MsnSlpMessage *xfer_msg; /* A dirty hack */
 
 	MsnSlpCb cb;
 	void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session);
--- a/libpurple/protocols/msn/slplink.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slplink.c	Sun Dec 20 17:17:10 2009 +0000
@@ -232,7 +232,7 @@
 	}
 }
 
-static void
+void
 msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
 {
 	MsnMessage *msg;
@@ -247,11 +247,11 @@
 
 	if (slpmsg->offset < real_size)
 	{
-		if (slpmsg->fp)
+		if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
+				purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
 		{
-			char data[1202];
-			len = fread(data, 1, sizeof(data), slpmsg->fp);
-			msn_message_set_bin_data(msg, data, len);
+			len = MIN(1202, slpmsg->slpcall->u.outgoing.len);
+			msn_message_set_bin_data(msg, slpmsg->slpcall->u.outgoing.data, len);
 		}
 		else
 		{
@@ -309,7 +309,13 @@
 
 	if (slpmsg->offset < real_size)
 	{
-		msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
+		if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
+		{
+			slpmsg->slpcall->xfer_msg = slpmsg;
+			purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+		}
+		else
+			msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
 	}
 	else
 	{
@@ -448,20 +454,22 @@
 send_file_cb(MsnSlpCall *slpcall)
 {
 	MsnSlpMessage *slpmsg;
-	struct stat st;
 	PurpleXfer *xfer;
 
+	xfer = (PurpleXfer *)slpcall->xfer;
+	purple_xfer_ref(xfer);
+	purple_xfer_start(xfer, -1, NULL, 0);
+	if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) {
+		purple_xfer_unref(xfer);
+		return;
+	}
+	purple_xfer_unref(xfer);
+
 	slpmsg = msn_slpmsg_new(slpcall->slplink);
 	slpmsg->slpcall = slpcall;
 	slpmsg->flags = 0x1000030;
 	slpmsg->info = "SLP FILE";
-
-	xfer = (PurpleXfer *)slpcall->xfer;
-	purple_xfer_start(slpcall->xfer, -1, NULL, 0);
-	slpmsg->fp = xfer->dest_fp;
-	if (g_stat(purple_xfer_get_local_filename(xfer), &st) == 0)
-		slpmsg->size = st.st_size;
-	xfer->dest_fp = NULL; /* Disable double fclose() */
+	slpmsg->size = purple_xfer_get_size(xfer);
 
 	msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
 }
@@ -489,6 +497,7 @@
 	const char *data;
 	guint64 offset;
 	gsize len;
+	PurpleXfer *xfer = NULL;
 
 	if (purple_debug_is_verbose())
 		msn_slpmsg_show(msg);
@@ -525,12 +534,12 @@
 				if (slpmsg->flags == 0x20 ||
 				    slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030)
 				{
-					PurpleXfer *xfer;
-
 					xfer = slpmsg->slpcall->xfer;
-
 					if (xfer != NULL)
 					{
+						slpmsg->ft = TRUE;
+						slpmsg->slpcall->xfer_msg = slpmsg;
+
 						purple_xfer_ref(xfer);
 						purple_xfer_start(xfer,	-1, NULL, 0);
 
@@ -540,14 +549,12 @@
 							g_return_if_reached();
 						} else {
 							purple_xfer_unref(xfer);
-							slpmsg->fp = xfer->dest_fp;
-							xfer->dest_fp = NULL; /* Disable double fclose() */
 						}
 					}
 				}
 			}
 		}
-		if (!slpmsg->fp && slpmsg->size)
+		if (!slpmsg->ft && slpmsg->size)
 		{
 			slpmsg->buffer = g_try_malloc(slpmsg->size);
 			if (slpmsg->buffer == NULL)
@@ -569,10 +576,12 @@
 		}
 	}
 
-	if (slpmsg->fp)
+	if (slpmsg->ft)
 	{
-		/* fseek(slpmsg->fp, offset, SEEK_SET); */
-		len = fwrite(data, 1, len, slpmsg->fp);
+		xfer = slpmsg->slpcall->xfer;
+		slpmsg->slpcall->u.incoming_data =
+				g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len);
+		purple_xfer_prpl_ready(xfer);
 	}
 	else if (slpmsg->size && slpmsg->buffer)
 	{
@@ -613,29 +622,37 @@
 
 		slpcall = msn_slp_process_msg(slplink, slpmsg);
 
-		if (slpmsg->flags == 0x100)
-		{
-			MsnDirectConn *directconn;
+		if (slpcall == NULL) {
+			msn_slpmsg_destroy(slpmsg);
+			return;
+		}
 
-			directconn = slplink->directconn;
+		if (!slpcall->wasted) {
+			if (slpmsg->flags == 0x100)
+			{
+				MsnDirectConn *directconn;
+
+				directconn = slplink->directconn;
 #if 0
-			if (!directconn->acked)
-				msn_directconn_send_handshake(directconn);
+				if (!directconn->acked)
+					msn_directconn_send_handshake(directconn);
 #endif
-		}
-		else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 ||  
-		         slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 ||  
-		         slpmsg->flags == 0x1000030)
-		{
-			/* Release all the messages and send the ACK */
+			}
+			else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 ||  
+			         slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 ||  
+			         slpmsg->flags == 0x1000030)
+			{
+				/* Release all the messages and send the ACK */
 
-			msn_slplink_send_ack(slplink, msg);
-			msn_slplink_send_queued_slpmsgs(slplink);
+				msn_slplink_send_ack(slplink, msg);
+				msn_slplink_send_queued_slpmsgs(slplink);
+			}
+
 		}
 
 		msn_slpmsg_destroy(slpmsg);
 
-		if (slpcall != NULL && slpcall->wasted)
+		if (slpcall->wasted)
 			msn_slpcall_destroy(slpcall);
 	}
 }
@@ -732,7 +749,6 @@
 
 	slpcall->session_init_cb = send_file_cb;
 	slpcall->end_cb = msn_xfer_end_cb;
-	slpcall->progress_cb = msn_xfer_progress_cb;
 	slpcall->cb = msn_xfer_completed_cb;
 	slpcall->xfer = xfer;
 	purple_xfer_ref(slpcall->xfer);
@@ -740,6 +756,8 @@
 	slpcall->pending = TRUE;
 
 	purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel);
+	purple_xfer_set_read_fnc(xfer, msn_xfer_read);
+	purple_xfer_set_write_fnc(xfer, msn_xfer_write);
 
 	xfer->data = slpcall;
 
--- a/libpurple/protocols/msn/slplink.h	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slplink.h	Sun Dec 20 17:17:10 2009 +0000
@@ -84,6 +84,9 @@
 void msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg);
 void msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer);
 
+/* Only exported for msn_xfer_write */
+void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+
 void msn_slplink_request_object(MsnSlpLink *slplink,
 								const char *info,
 								MsnSlpCb cb,
--- a/libpurple/protocols/msn/slpmsg.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slpmsg.c	Sun Dec 20 17:17:10 2009 +0000
@@ -60,9 +60,6 @@
 
 	slplink = slpmsg->slplink;
 
-	if (slpmsg->fp != NULL)
-		fclose(slpmsg->fp);
-
 	purple_imgstore_unref(slpmsg->img);
 
 	/* We don't want to free the data of the PurpleStoredImage,
@@ -96,7 +93,7 @@
 	/* We can only have one data source at a time. */
 	g_return_if_fail(slpmsg->buffer == NULL);
 	g_return_if_fail(slpmsg->img == NULL);
-	g_return_if_fail(slpmsg->fp == NULL);
+	g_return_if_fail(slpmsg->ft == FALSE);
 
 	if (body != NULL)
 		slpmsg->buffer = g_memdup(body, size);
@@ -112,7 +109,7 @@
 	/* We can only have one data source at a time. */
 	g_return_if_fail(slpmsg->buffer == NULL);
 	g_return_if_fail(slpmsg->img == NULL);
-	g_return_if_fail(slpmsg->fp == NULL);
+	g_return_if_fail(slpmsg->ft == FALSE);
 
 	slpmsg->img = purple_imgstore_ref(img);
 	slpmsg->buffer = (guchar *)purple_imgstore_get_data(img);
--- a/libpurple/protocols/msn/slpmsg.h	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/slpmsg.h	Sun Dec 20 17:17:10 2009 +0000
@@ -54,7 +54,7 @@
 	gboolean sip; /**< A flag that states if this is a SIP slp message. */
 	long flags;
 
-	FILE *fp;
+	gboolean ft;
 	PurpleStoredImage *img;
 	guchar *buffer;
 	long long offset;
--- a/libpurple/protocols/msn/switchboard.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Sun Dec 20 17:17:10 2009 +0000
@@ -222,13 +222,28 @@
 {
 	MsnCmdProc *cmdproc;
 	PurpleAccount *account;
+	char *semicolon;
+	char *passport;
 
 	g_return_if_fail(swboard != NULL);
 
 	cmdproc = swboard->cmdproc;
 	account = cmdproc->session->account;
 
-	swboard->users = g_list_prepend(swboard->users, g_strdup(user));
+	semicolon = strchr(user, ';');
+	/* We don't really care about the machine ID. */
+	if (semicolon)
+		passport = g_strndup(user, semicolon - user);
+	else
+		passport = g_strdup(user);
+
+	/* Don't add multiple endpoints to the conversation. */
+	if (g_list_find_custom(swboard->users, passport, (GCompareFunc)strcmp)) {
+		g_free(passport);
+		return;
+	}
+
+	swboard->users = g_list_prepend(swboard->users, passport);
 	swboard->current_users++;
 	swboard->empty = FALSE;
 
--- a/libpurple/protocols/msn/userlist.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/msn/userlist.c	Sun Dec 20 17:17:10 2009 +0000
@@ -50,8 +50,11 @@
 	{
 		MsnSession *session = pa->gc->proto_data;
 		MsnUserList *userlist = session->userlist;
+		PurpleAccount *account = purple_connection_get_account(pa->gc);
 
 		msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL);
+		purple_privacy_deny_remove(account, pa->who, TRUE);
+		purple_privacy_permit_add(account, pa->who, TRUE);
 
 		msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL);
 	}
--- a/libpurple/protocols/myspace/user.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/myspace/user.c	Sun Dec 20 17:17:10 2009 +0000
@@ -72,6 +72,9 @@
 	if (!user)
 		return;
 
+	if (user->url_data != NULL)
+		purple_util_fetch_url_cancel(user->url_data);
+
 	g_free(user->client_info);
 	g_free(user->gender);
 	g_free(user->location);
@@ -214,6 +217,8 @@
 	const char *name = purple_buddy_get_name(user->buddy);
 	PurpleAccount *account;
 
+	user->url_data = NULL;
+
 	purple_debug_info("msim_downloaded_buddy_icon",
 			"Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
 
@@ -377,7 +382,9 @@
 
 		/* Only download if URL changed */
 		if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
-			purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
+			if (user->url_data != NULL)
+				purple_util_fetch_url_cancel(user->url_data);
+			user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
 		}
 	} else if (g_str_equal(key_str, "LastImageUpdated")) {
 		/* TODO: use somewhere */
--- a/libpurple/protocols/myspace/user.h	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/protocols/myspace/user.h	Sun Dec 20 17:17:10 2009 +0000
@@ -40,6 +40,7 @@
 	gchar *image_url;
 	guint last_image_updated;
 	gboolean temporary_user;
+	PurpleUtilFetchUrlData *url_data;
 } MsimUser;
 
 /* Callback function pointer type for when a user's information is received,
--- a/libpurple/purple-uninstalled.pc.in	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/purple-uninstalled.pc.in	Sun Dec 20 17:17:10 2009 +0000
@@ -6,9 +6,12 @@
 datadir=@datadir@
 sysconfdir=@sysconfdir@
 
+abs_srcdir=@abs_srcdir@
+abs_builddir=@abs_builddir@
+
 Name: libpurple
 Description: libpurple is a GLib-based instant messenger library.
 Version: @VERSION@
 Requires: glib-2.0
-Cflags: -I${pcfiledir}
-Libs: ${pcfiledir}/libpurple.la
+Cflags: -I${abs_srcdir} -I${abs_builddir}
+Libs: ${abs_builddir}/libpurple.la
--- a/libpurple/tests/Makefile.am	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/tests/Makefile.am	Sun Dec 20 17:17:10 2009 +0000
@@ -27,11 +27,11 @@
 		-DBUILDDIR=\"$(top_builddir)\"
 
 check_libpurple_LDADD=\
-        @CHECK_LIBS@ \
-		$(GLIB_LIBS) \
 		$(top_builddir)/libpurple/protocols/jabber/libjabber.la \
 		$(top_builddir)/libpurple/protocols/qq/libqq.la \
 		$(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
-		$(top_builddir)/libpurple/libpurple.la
+		$(top_builddir)/libpurple/libpurple.la \
+        @CHECK_LIBS@ \
+		$(GLIB_LIBS)
 
 endif
--- a/libpurple/tests/check_libpurple.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/tests/check_libpurple.c	Sun Dec 20 17:17:10 2009 +0000
@@ -44,7 +44,7 @@
 	purple_eventloop_set_ui_ops(&eventloop_ui_ops);
 
 	/* build our fake home directory */
-	home_dir = g_build_path(BUILDDIR, "libpurple", "tests", "home", NULL);
+	home_dir = g_build_path(G_DIR_SEPARATOR_S, BUILDDIR, "libpurple", "tests", "home", NULL);
 	purple_util_set_user_dir(home_dir);
 	g_free(home_dir);
 
@@ -67,6 +67,9 @@
 	int number_failed;
 	SRunner *sr;
 
+	if (g_getenv("PURPLE_CHECK_DEBUG"))
+		purple_debug_set_enabled(TRUE);
+
 	/* Make g_return_... functions fatal, ALWAYS.
 	 * As this is the test code, this is NOT controlled
 	 * by PURPLE_FATAL_ASSERTS. */
--- a/libpurple/tests/test_cipher.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/libpurple/tests/test_cipher.c	Sun Dec 20 17:17:10 2009 +0000
@@ -142,12 +142,13 @@
 	PurpleCipherContext *context = NULL; \
 	gchar cdigest[41]; \
 	gboolean ret = FALSE; \
+	gchar *input = data; \
 	\
 	cipher = purple_ciphers_find_cipher("sha1"); \
 	context = purple_cipher_context_new(cipher, NULL); \
 	\
-	if((data)) { \
-		purple_cipher_context_append(context, (guchar *)(data), strlen((data))); \
+	if (input) { \
+		purple_cipher_context_append(context, (guchar *)input, strlen(input)); \
 	} else { \
 		gint j; \
 		guchar buff[1000]; \
@@ -202,12 +203,13 @@
 	PurpleCipherContext *context = NULL; \
 	gchar cdigest[65]; \
 	gboolean ret = FALSE; \
+	gchar *input = data; \
 	\
 	cipher = purple_ciphers_find_cipher("sha256"); \
 	context = purple_cipher_context_new(cipher, NULL); \
 	\
-	if((data)) { \
-		purple_cipher_context_append(context, (guchar *)(data), strlen((data))); \
+	if (input) { \
+		purple_cipher_context_append(context, (guchar *)input, strlen(input)); \
 	} else { \
 		gint j; \
 		guchar buff[1000]; \
--- a/pidgin/gtkdialogs.c	Fri Dec 11 03:09:31 2009 +0000
+++ b/pidgin/gtkdialogs.c	Sun Dec 20 17:17:10 2009 +0000
@@ -195,7 +195,6 @@
 	{N_("Kurdish"),             "ku", "Amed Ç. Jiyan", "amedcj@hotmail.com"},
 	{N_("Kurdish"),             "ku", "Rizoyê Xerzî", "rizoxerzi@hotmail.com"},
 	{N_("Lao"),                 "lo", "Anousak Souphavah", "anousak@gmail.com"},
-	{N_("Lithuanian"),          "lt", "Laurynas Biveinis", "laurynas.biveinis@gmail.com"},
 	{N_("Macedonian"),          "mk", "Arangel Angov ", "arangel@linux.net.mk"},
 	{N_("Macedonian"),          "mk", "Ivana Kirkovska", "ivana.kirkovska@gmail.com"},
 	{N_("Macedonian"),          "mk", "Jovan Naumovski", "jovan@lugola.net"},
@@ -274,8 +273,9 @@
 	{N_("Georgian"),            "ka", "Temuri Doghonadze", NULL},
 	{N_("Korean"),              "ko", "Sang-hyun S, A Ho-seok Lee", NULL},
 	{N_("Korean"),              "ko", "Kyeong-uk Son", NULL},
+	{N_("Lithuanian"),          "lt", "Laurynas Biveinis", "laurynas.biveinis@gmail.com"},
+	{N_("Lithuanian"),          "lt", "Gediminas Čičinskas", NULL},
 	{N_("Lithuanian"),          "lt", "Andrius Štikonas", NULL},
-	{N_("Lithuanian"),          "lt", "Gediminas Čičinskas", NULL},
 	{N_("Macedonian"),          "mk", "Tomislav Markovski", NULL},
 	{N_("Bokmål Norwegian"),    "nb", "Hallvard Glad", "hallvard.glad@gmail.com"},
 	{N_("Bokmål Norwegian"),    "nb", "Petter Johan Olsen", NULL},
--- a/pidgin/pidgin-uninstalled.pc.in	Fri Dec 11 03:09:31 2009 +0000
+++ b/pidgin/pidgin-uninstalled.pc.in	Sun Dec 20 17:17:10 2009 +0000
@@ -6,8 +6,11 @@
 datadir=@datadir@
 sysconfdir=@sysconfdir@
 
+abs_srcdir=@abs_srcdir@
+abs_builddir=@abs_builddir@
+
 Name: Pidgin
 Description: Pidgin is a GTK2-based instant messenger application.
 Version: @VERSION@
 Requires: gtk+-2.0 purple
-Cflags: -I${pcfiledir}
+Cflags: -I${abs_srcdir}
--- a/po/de.po	Fri Dec 11 03:09:31 2009 +0000
+++ b/po/de.po	Sun Dec 20 17:17:10 2009 +0000
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-11-30 11:50+0100\n"
-"PO-Revision-Date: 2009-11-30 11:45+0100\n"
+"POT-Creation-Date: 2009-12-10 22:38+0100\n"
+"PO-Revision-Date: 2009-12-11 20:55+0100\n"
 "Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -3827,6 +3827,13 @@
 "Der Server erfordert eine Klartext-Authentifizierung über einen "
 "unverschlüsselten Kanal"
 
+#. This should never happen!
+msgid "Invalid response from server"
+msgstr "Ungültige Serverantwort"
+
+msgid "Server does not use any supported authentication method"
+msgstr "Der Server benutzt keine der unterstützten Authentifizierungsmethoden"
+
 #, c-format
 msgid ""
 "%s requires plaintext authentication over an unencrypted connection.  Allow "
@@ -3839,15 +3846,6 @@
 msgid "Plaintext Authentication"
 msgstr "Klartext-Authentifizierung"
 
-msgid "SASL authentication failed"
-msgstr "SASL-Authentifizierung fehlgeschlagen"
-
-msgid "Invalid response from server"
-msgstr "Ungültige Serverantwort"
-
-msgid "Server does not use any supported authentication method"
-msgstr "Der Server benutzt keine der unterstützten Authentifizierungsmethoden"
-
 msgid "You require encryption, but it is not available on this server."
 msgstr ""
 "Sie fordern Verschlüsselung, aber diese ist auf dem Server nicht verfügbar."
@@ -3855,10 +3853,32 @@
 msgid "Invalid challenge from server"
 msgstr "Ungültige Challenge vom Server"
 
+msgid "Server thinks authentication is complete, but client does not"
+msgstr ""
+
+msgid "SASL authentication failed"
+msgstr "SASL-Authentifizierung fehlgeschlagen"
+
 #, c-format
 msgid "SASL error: %s"
 msgstr "SASL-Fehler: %s"
 
+#, fuzzy
+msgid "Unable to canonicalize username"
+msgstr "Kann nicht konfigurieren"
+
+#, fuzzy
+msgid "Unable to canonicalize password"
+msgstr "Es konnte kein lauschender Port geöffnet werden."
+
+#, fuzzy
+msgid "Malicious challenge from server"
+msgstr "Ungültige Challenge vom Server"
+
+#, fuzzy
+msgid "Unexpected response from server"
+msgstr "Ungültige HTTP-Antwort vom Server empfangen"
+
 msgid "The BOSH connection manager terminated your session."
 msgstr "Der BOSH-Verbindungsmanager hat Ihre Sitzung beendet."
 
@@ -3959,13 +3979,21 @@
 msgid "Resource"
 msgstr "Ressource"
 
+#, fuzzy
+msgid "Uptime"
+msgstr "Aktualisieren"
+
+#, c-format
+msgid "%s"
+msgstr ""
+
+msgid "Logged Off"
+msgstr "Abgemeldet"
+
 #, c-format
 msgid "%s ago"
 msgstr "vor %s"
 
-msgid "Logged Off"
-msgstr "Abgemeldet"
-
 msgid "Middle Name"
 msgstr "Zweiter Name"
 
@@ -12222,14 +12250,7 @@
 "<br/>We can't help with 3rd party protocols or plugins!<br/>This list's "
 "primary language is <b>English</b>.  You are welcome to post in another "
 "language, but the responses may be less helpful.<br/><br/>"
-msgstr ""
-"<font size=\"4\">Hilfe von anderen Pidgin-Benutzern:</font> <a href=\"mailto:"
-"support@pidgin.im\">support@pidgin.im</a><br/>Dies ist eine <b>öffentliche</"
-"b> Mailing-Liste! (<a href=\"http://pidgin.im/pipermail/support/\">Archiv</"
-"a>)<br/>Wir können nicht bei Problemen mit Drittanbieter-Protokollen oder "
-"Plugins helfen!<br/>Die Hauptsprache dieser Liste ist <b>Englisch</b>.  Sie "
-"können gern in einer anderen Sprache schreiben, aber die Antworten könnten "
-"weniger hilfreich sein.<br/><br/>"
+msgstr "<font size=\"4\">Hilfe von anderen Pidgin-Benutzern:</font> <a href=\"mailto:support@pidgin.im\">support@pidgin.im</a><br/>Dies ist eine <b>öffentliche</b> Mailing-Liste! (<a href=\"http://pidgin.im/pipermail/support/\">Archiv</a>)<br/>Wir können nicht bei Problemen mit Drittanbieter-Protokollen oder Plugins helfen!<br/>Die Hauptsprache dieser Liste ist <b>Englisch</b>.  Sie können gern in einer anderen Sprache schreiben, aber die Antworten könnten weniger hilfreich sein.<br/>Deutschsprachige Benutzer können auch das Portal <a href=\"http://www.pidgin-im.de/\">Pidgin-IM.de</a> nutzen.  Dort finden Sie aktuelle Informationen zu Pidgin, können mit anderen Benutzern im <a href=\"http://forum.pidgin-im.de/\">Forum</a> diskutieren und Hilfe zu Problemen finden.  Beachten Sie, dass dieses Portal unabhängig vom offiziellen Pidgin-Projekt ist.<br/><br/>"
 
 #, c-format
 msgid ""