im.pidgin.pidgin.2.2.1: d41bd4e4e784c56bafb185470c1fbd50fd362f49

lschiere at pidgin.im lschiere at pidgin.im
Mon Oct 1 13:56:33 EDT 2007


revision:            d41bd4e4e784c56bafb185470c1fbd50fd362f49
date:                2007-09-28T16:29:17
author:              lschiere at pidgin.im
branch:              im.pidgin.pidgin.2.2.1
changelog:
merge of 'abae017149f09c2c6f55a7d80501a55cfa92f8d7'
     and 'f76b9e1feb23d6a4308ca0c80f5f85765d985aff'

manifest:
format_version "1"

new_manifest [0d6a1323d3f6a69b9ba60b33411e646db7486a51]

old_revision [abae017149f09c2c6f55a7d80501a55cfa92f8d7]

patch "libpurple/protocols/jabber/jabber.c"
 from [9566f6a2fd23699865c6a8ba16b2315d3daa3153]
   to [4e51e9d6769210016e9490d044b6730b47bad7f4]

patch "libpurple/protocols/jabber/jabber.h"
 from [3fde42e62a7ffc59f00d83a86f8049e14df097f8]
   to [09f1d54e927d0c2d48c4d16c5500db62db4747ea]

patch "libpurple/protocols/jabber/libxmpp.c"
 from [c6868a2d6cd1cd84dcb3807b86644f2b79257cf8]
   to [df441db31794ab4e20ce081a2679b63f41b789cd]

patch "libpurple/protocols/myspace/markup.c"
 from [974b81f96fee8c9553b1fed1756448e08c233c89]
   to [58f21b7150ffc5540638233b0a52304c43adac9f]

patch "libpurple/protocols/myspace/myspace.c"
 from [de33d4f732116c766d689735c94f130f9682eb1d]
   to [9348634840b89099dc4d6792ae689dd0c3034457]

patch "libpurple/protocols/myspace/user.c"
 from [99fea72d02ba979ff58a3f30142d3424917df2e4]
   to [cd376f03cc62872fe687b6585cd373130330d2fb]

old_revision [f76b9e1feb23d6a4308ca0c80f5f85765d985aff]

patch "ChangeLog"
 from [e7623b2283a21fc8072758061318a0cb98b08152]
   to [ab4eac330af903fe74985b8f8e2b9ce8795d8bd3]

patch "libpurple/account.c"
 from [5dc69bd980d2847a2f77599480dbeb7bd84218eb]
   to [7b72d1151464af49fc470e957c42d154ed8ff72b]

patch "libpurple/cmds.h"
 from [953c84ca8c44c8e5824209a605d5d889a96b1e0d]
   to [796e9865e88f475e0a36c93142e9170c3dc3cf26]

patch "libpurple/dnssrv.c"
 from [2fd26c74fed3be685076a0478ffd07f5cf378d8c]
   to [21f0607230b52f7bb12383741c8648a8df182f1c]

patch "libpurple/ft.c"
 from [59e9d4da28a7d81ee7a76c399c4115445cca466f]
   to [32dae7657417fd89f64ba4b5563ffbff9ae19013]

patch "libpurple/protocols/jabber/auth.c"
 from [43d0094f5eb9cee59b3edc6cbe6e7a9a430167df]
   to [5b9f4e7c28a89ddc6879a963fc646b14f6f7ab4e]

patch "libpurple/protocols/yahoo/yahoo_filexfer.c"
 from [c3030fac3a35f7fd44b05ff40e7f2090fe491c4c]
   to [148c1cac5309d294bc3bb5482687a5fb0cdb1167]

patch "libpurple/status.c"
 from [186dd554d259db6734202e08e005279fc0327dcb]
   to [603b583997ce734929249cfd927e7d8205b4013d]

patch "libpurple/upnp.c"
 from [9f7037509c784f450f1fb4ad33176d040c1579dc]
   to [78c0017916277fdb5bc0000cca06c35fb3a031ff]

patch "libpurple/util.c"
 from [504ff584b386911ab4c77743e8e17df9e684caf6]
   to [333952029f746cf825390ccadfc3489a3bbf5bad]

patch "pidgin/gtkconv.c"
 from [ae2a582300ca2f4789b9f0981a2884cf2b3f39fc]
   to [981eb411a6aa58d72585ac1d81099e69382582d9]

patch "pidgin/gtkdocklet.c"
 from [70e5582a286631d41683a4a3f0f07ee026e3b33d]
   to [c0fbf99c7ebe18814fa14bd3c151a2ee8929eafd]

patch "pidgin/gtkimhtml.c"
 from [77589de31ac3088af69562e1ce335f93d8e3d701]
   to [5da45f5e789c81e8967f951df1dcca1016a57791]

patch "pidgin/plugins/gtkbuddynote.c"
 from [ceea38e2b71e6cdb0ff0ddbb2da042327ad0f68b]
   to [1fd6753cdc854757b15b841f0c9724c694c5fe73]
-------------- next part --------------
#
#
# patch "libpurple/protocols/jabber/jabber.c"
#  from [9566f6a2fd23699865c6a8ba16b2315d3daa3153]
#    to [4e51e9d6769210016e9490d044b6730b47bad7f4]
# 
# patch "libpurple/protocols/jabber/jabber.h"
#  from [3fde42e62a7ffc59f00d83a86f8049e14df097f8]
#    to [09f1d54e927d0c2d48c4d16c5500db62db4747ea]
# 
# patch "libpurple/protocols/jabber/libxmpp.c"
#  from [c6868a2d6cd1cd84dcb3807b86644f2b79257cf8]
#    to [df441db31794ab4e20ce081a2679b63f41b789cd]
# 
# patch "libpurple/protocols/myspace/markup.c"
#  from [974b81f96fee8c9553b1fed1756448e08c233c89]
#    to [58f21b7150ffc5540638233b0a52304c43adac9f]
# 
# patch "libpurple/protocols/myspace/myspace.c"
#  from [de33d4f732116c766d689735c94f130f9682eb1d]
#    to [9348634840b89099dc4d6792ae689dd0c3034457]
# 
# patch "libpurple/protocols/myspace/user.c"
#  from [99fea72d02ba979ff58a3f30142d3424917df2e4]
#    to [cd376f03cc62872fe687b6585cd373130330d2fb]
#
============================================================
--- libpurple/protocols/jabber/jabber.c	9566f6a2fd23699865c6a8ba16b2315d3daa3153
+++ libpurple/protocols/jabber/jabber.c	4e51e9d6769210016e9490d044b6730b47bad7f4
@@ -2240,6 +2240,44 @@ static PurpleCmdRet jabber_cmd_buzz(Purp
 	return PURPLE_CMD_RET_FAILED;
 }
 
+GList *jabber_attention_types(PurpleAccount *account)
+{
+	static GList *types = NULL;
+	PurpleAttentionType *attn;
+
+	if (!types) {
+		attn = g_new0(PurpleAttentionType, 1);
+		attn->name = _("Buzz");
+		attn->incoming_description = _("%s has buzzed you!");
+		attn->outgoing_description = _("Buzzing %s...");
+		types = g_list_append(types, attn);
+	}
+
+	return types;
+}
+
+gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code)
+{
+	PurpleConversation *conv;
+	char *error;
+	char *args[1];
+	PurpleCmdRet ret;
+
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, username, gc->account);
+
+	args[0] = (char *)username;
+
+	ret = jabber_cmd_buzz(conv, "buzz", args, &error, NULL);
+
+	if (ret == PURPLE_CMD_RET_FAILED) {
+		purple_debug_error("jabber", "jabber_send_attention: jabber_cmd_buzz failed with error: %s\n", error ? error : "(NULL)");
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
+
 gboolean jabber_offline_message(const PurpleBuddy *buddy)
 {
 	return TRUE;
============================================================
--- libpurple/protocols/jabber/jabber.h	3fde42e62a7ffc59f00d83a86f8049e14df097f8
+++ libpurple/protocols/jabber/jabber.h	09f1d54e927d0c2d48c4d16c5500db62db4747ea
@@ -66,6 +66,9 @@ typedef struct _JabberStream JabberStrea
 
 #define CAPS0115_NODE "http://pidgin.im/caps"
 
+/* Index into attention_types list */
+#define JABBER_BUZZ 0
+
 typedef enum {
 	JABBER_STREAM_OFFLINE,
 	JABBER_STREAM_CONNECTING,
@@ -231,6 +234,8 @@ void jabber_unregister_account(PurpleAcc
 void jabber_register_gateway(JabberStream *js, const char *gateway);
 void jabber_register_account(PurpleAccount *account);
 void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data);
+gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code);
+GList *jabber_attention_types(PurpleAccount *account);
 void jabber_convo_closed(PurpleConnection *gc, const char *who);
 PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name);
 gboolean jabber_offline_message(const PurpleBuddy *buddy);
============================================================
--- libpurple/protocols/jabber/libxmpp.c	c6868a2d6cd1cd84dcb3807b86644f2b79257cf8
+++ libpurple/protocols/jabber/libxmpp.c	df441db31794ab4e20ce081a2679b63f41b789cd
@@ -113,10 +113,10 @@ static PurplePluginProtocolInfo prpl_inf
 	jabber_prpl_send_raw,			/* send_raw */
 	jabber_roomlist_room_serialize, /* roomlist_room_serialize */
 	jabber_unregister_account,		/* unregister_user */
+	jabber_attention_types,                 /* attention_types */
+	jabber_send_attention,                  /* send_attention */
 
 	/* padding */
-	NULL,
-	NULL,
 	NULL
 };
 
============================================================
--- libpurple/protocols/myspace/markup.c	974b81f96fee8c9553b1fed1756448e08c233c89
+++ libpurple/protocols/myspace/markup.c	58f21b7150ffc5540638233b0a52304c43adac9f
@@ -515,7 +515,8 @@ html_tag_to_msim_markup(MsimSession *ses
 #endif
 
 		err = g_strdup_printf("html_tag_to_msim_markup: unrecognized "
-			"HTML tag %s was sent by the IM client; ignoring");
+			"HTML tag %s was sent by the IM client; ignoring", 
+			root->name ? root->name : "(NULL)");
 		msim_unrecognized(NULL, NULL, err);
 		g_free(err);
 	}
============================================================
--- libpurple/protocols/myspace/myspace.c	de33d4f732116c766d689735c94f130f9682eb1d
+++ libpurple/protocols/myspace/myspace.c	9348634840b89099dc4d6792ae689dd0c3034457
@@ -453,6 +453,7 @@ msim_compute_login_response(const gchar 
 	purple_cipher_context_append(key_context, hash_pw, HASH_SIZE);
 	purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE);
 	purple_cipher_context_digest(key_context, sizeof(key), key, NULL);
+	purple_cipher_context_destroy(key_context);
 
 #ifdef MSIM_DEBUG_LOGIN_CHALLENGE
 	purple_debug_info("msim", "key = ");
@@ -1029,7 +1030,7 @@ msim_set_status(PurpleAccount *account, 
 	PurpleStatusType *type;
 	MsimSession *session;
 	guint status_code;
-	const gchar *statstring;
+	gchar *statstring;
 
 	session = (MsimSession *)account->gc->proto_data;
 
@@ -1063,7 +1064,7 @@ msim_set_status(PurpleAccount *account, 
 			break;
 	}
 
-	statstring = purple_status_get_attr_string(status, "message");
+	statstring = (gchar *)purple_status_get_attr_string(status, "message");
 
 	if (!statstring) {
 		statstring = "";
@@ -1072,7 +1073,7 @@ msim_set_status(PurpleAccount *account, 
 	/* Status strings are plain text. */
 	statstring = purple_markup_strip_html(statstring);
 
-	msim_set_status_code(session, status_code, g_strdup(statstring));
+	msim_set_status_code(session, status_code, statstring);
 }
 
 /** Go idle. */
@@ -1203,7 +1204,7 @@ msim_uid2username_from_blist(MsimSession
 		if (uid == wanted_uid)
 		{
 			ret = g_strdup(name);
-            break;
+			break;
 		}
 	}
 
@@ -1860,6 +1861,7 @@ msim_incoming_status(MsimSession *sessio
 		purple_blist_add_buddy(buddy, NULL, NULL, NULL);
 
 		user = msim_get_user_from_buddy(buddy);
+		/* TODO: free user. memory leak? */
 
 		/* All buddies on list should have 'uid' integer associated with them. */
 		purple_blist_node_set_int(&buddy->node, "UserID", msim_msg_get_integer(msg, "f"));
============================================================
--- libpurple/protocols/myspace/user.c	99fea72d02ba979ff58a3f30142d3424917df2e4
+++ libpurple/protocols/myspace/user.c	cd376f03cc62872fe687b6585cd373130330d2fb
@@ -154,7 +154,13 @@ msim_append_user_info(MsimSession *sessi
 	}
 }
 
-/** Store a field of information about a buddy. */
+/** Store a field of information about a buddy. 
+ *
+ * @param key_str Key to store.
+ * @param value_str Value string, either user takes ownership of this string
+ *                  or it is freed if MsimUser doesn't store the string.
+ * @param user User to store data in. Existing data will be replaced.
+ * */
 void 
 msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
 {
@@ -168,26 +174,34 @@ msim_store_user_info_each(const gchar *k
 		/* Need to store in MsimUser, too? What if not on blist? */
 	} else if (g_str_equal(key_str, "Age")) {
 		user->age = atol(value_str);
+		g_free(value_str);
 	} else if (g_str_equal(key_str, "Gender")) {
-		user->gender = g_strdup(value_str);
+		g_free(user->gender);
+		user->gender = value_str;
 	} else if (g_str_equal(key_str, "Location")) {
-		user->location = g_strdup(value_str);
+		g_free(user->location);
+		user->location = value_str;
 	} else if (g_str_equal(key_str, "TotalFriends")) {
 		user->total_friends = atol(value_str);
 	} else if (g_str_equal(key_str, "DisplayName")) {
-		user->display_name = g_strdup(value_str);
+		g_free(user->display_name);
+		user->display_name = value_str;
 	} else if (g_str_equal(key_str, "BandName")) {
-		user->band_name = g_strdup(value_str);
+		g_free(user->band_name);
+		user->band_name = value_str;
 	} else if (g_str_equal(key_str, "SongName")) {
-		user->song_name = g_strdup(value_str);
+		g_free(user->song_name);
+		user->song_name = value_str;
 	} else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
 		/* Ignore because PurpleBuddy knows this already */
-		;
+		g_free(value_str);
 	} else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
 		const gchar *previous_url;
 
-		user->image_url = g_strdup(value_str);
+		g_free(user->image_url);
 
+		user->image_url = value_str;
+
 		/* Instead of showing 'no photo' picture, show nothing. */
 		if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
 		{
@@ -207,14 +221,17 @@ msim_store_user_info_each(const gchar *k
 	} else if (g_str_equal(key_str, "LastImageUpdated")) {
 		/* TODO: use somewhere */
 		user->last_image_updated = atol(value_str);
+		g_free(value_str);
 	} else if (g_str_equal(key_str, "Headline")) {
-		user->headline = g_strdup(value_str);
+		g_free(user->headline);
+		user->headline = value_str;
 	} else {
 		/* TODO: other fields in MsimUser */
 		gchar *msg;
 
 		msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
 				key_str, value_str);
+		g_free(value_str);
 
 		msim_unrecognized(NULL, NULL, msg);
 
@@ -284,7 +301,6 @@ msim_store_user_info(MsimSession *sessio
 
 		value_str = msim_msg_get_string_from_element(elem);
 		msim_store_user_info_each(key_str, value_str, user);
-		g_free(value_str);
 	}
 
 	if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
@@ -301,6 +317,7 @@ msim_store_user_info(MsimSession *sessio
 	}
 
 	msim_msg_free(body);
+	g_free(username);
 
 	return TRUE;
 }
-------------- next part --------------
#
#
# patch "ChangeLog"
#  from [e7623b2283a21fc8072758061318a0cb98b08152]
#    to [ab4eac330af903fe74985b8f8e2b9ce8795d8bd3]
# 
# patch "libpurple/account.c"
#  from [5dc69bd980d2847a2f77599480dbeb7bd84218eb]
#    to [7b72d1151464af49fc470e957c42d154ed8ff72b]
# 
# patch "libpurple/cmds.h"
#  from [953c84ca8c44c8e5824209a605d5d889a96b1e0d]
#    to [796e9865e88f475e0a36c93142e9170c3dc3cf26]
# 
# patch "libpurple/dnssrv.c"
#  from [2fd26c74fed3be685076a0478ffd07f5cf378d8c]
#    to [21f0607230b52f7bb12383741c8648a8df182f1c]
# 
# patch "libpurple/ft.c"
#  from [59e9d4da28a7d81ee7a76c399c4115445cca466f]
#    to [32dae7657417fd89f64ba4b5563ffbff9ae19013]
# 
# patch "libpurple/protocols/jabber/auth.c"
#  from [43d0094f5eb9cee59b3edc6cbe6e7a9a430167df]
#    to [5b9f4e7c28a89ddc6879a963fc646b14f6f7ab4e]
# 
# patch "libpurple/protocols/yahoo/yahoo_filexfer.c"
#  from [c3030fac3a35f7fd44b05ff40e7f2090fe491c4c]
#    to [148c1cac5309d294bc3bb5482687a5fb0cdb1167]
# 
# patch "libpurple/status.c"
#  from [186dd554d259db6734202e08e005279fc0327dcb]
#    to [603b583997ce734929249cfd927e7d8205b4013d]
# 
# patch "libpurple/upnp.c"
#  from [9f7037509c784f450f1fb4ad33176d040c1579dc]
#    to [78c0017916277fdb5bc0000cca06c35fb3a031ff]
# 
# patch "libpurple/util.c"
#  from [504ff584b386911ab4c77743e8e17df9e684caf6]
#    to [333952029f746cf825390ccadfc3489a3bbf5bad]
# 
# patch "pidgin/gtkconv.c"
#  from [ae2a582300ca2f4789b9f0981a2884cf2b3f39fc]
#    to [981eb411a6aa58d72585ac1d81099e69382582d9]
# 
# patch "pidgin/gtkdocklet.c"
#  from [70e5582a286631d41683a4a3f0f07ee026e3b33d]
#    to [c0fbf99c7ebe18814fa14bd3c151a2ee8929eafd]
# 
# patch "pidgin/gtkimhtml.c"
#  from [77589de31ac3088af69562e1ce335f93d8e3d701]
#    to [5da45f5e789c81e8967f951df1dcca1016a57791]
# 
# patch "pidgin/plugins/gtkbuddynote.c"
#  from [ceea38e2b71e6cdb0ff0ddbb2da042327ad0f68b]
#    to [1fd6753cdc854757b15b841f0c9724c694c5fe73]
#
============================================================
--- ChangeLog	e7623b2283a21fc8072758061318a0cb98b08152
+++ ChangeLog	ab4eac330af903fe74985b8f8e2b9ce8795d8bd3
@@ -1,20 +1,38 @@ Version 2.2.1:
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 Version 2.2.1:
 	http://developer.pidgin.im/query?status=closed&milestone=2.2.1
 	
+	libpurple:
+	* A few build issues on Solaris were fixed.
+	* Cancelling the password prompt for an account will no longer leave
+	  it in an ambiguous state.  (It will be disabled.)
+	* Fixed an erroneous size display for MSN file transfers. (galt)
+	* Real usernames are now shown in the system log.
+
 	Pidgin:
-	* When aliasing someone to an alias that already exists in the
-	  same group, offer to merge the buddies into the same contact
-	* It's possible to keep a conversation (chat/IM) open even after closing
-	  the conversation window/tab.
-	* A music emblem is displayed in the buddy list for a buddy if we know she
-	  is listening to some soothing music.
-	* 'Move to' menu in buddy list context menu for moving buddies to
-  	   other groups
-	* Move "Smiley" to the top-level of the toolbar
-	* Save Pidgin's display in the command line for session
+	* If you alias a buddy to an alias that is already present within
+	  a particular group, we now offer to merge the buddies into the
+	  same contact.
+	* A music emblem is now displayed in the buddy list for a buddy if we
+	  know she is listening to some soothing music.
+	* Added a 'Move to' menu in buddy list context menu for moving buddies
+	  to other groups as an alternative to dragging.
+	* Group headings are now marked via an underline instead of a
+	  different color background.
+	* It is now possible to mark a chat on your buddy list as "Persistent"
+	  so you do not leave the chat when the window or tab is closed.
+	* The auto-join option for chats is now listed in the "Add Chat"
+	  dialog along with the new persistence option.
+	* Closing an IM no longer immediately closes your conversation.  It
+	  will now remain active for a short time so that if the conversation
+	  resumes, the history will be retained.  A preference has been added
+	  to toggle this behavior.
+	* The "Smiley" menu has been moved to the top-level of the toolbar.
+	* Fixed keyboard tab reordering to move tabs one step instead of two.
+	* Pidgin's display is now saved with the command line for session
 	  restoration.  (David Mohr)
+	* You should no longer lose proxy settings when Pidgin is restarted.
 
 Version 2.2.0 (09/13/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.2.0
============================================================
--- libpurple/account.c	5dc69bd980d2847a2f77599480dbeb7bd84218eb
+++ libpurple/account.c	7b72d1151464af49fc470e957c42d154ed8ff72b
@@ -917,7 +917,7 @@ purple_account_set_register_callback(Pur
 purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data)
 {
 	g_return_if_fail(account != NULL);
-	
+
 	account->registration_cb = cb;
 	account->registration_cb_user_data = user_data;
 }
@@ -937,10 +937,10 @@ purple_account_unregister(PurpleAccount 
 purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data)
 {
 	g_return_if_fail(account != NULL);
-	
+
 	purple_debug_info("account", "Unregistering account %s\n",
 					  purple_account_get_username(account));
-	
+
 	purple_connection_new_unregister(account, purple_account_get_password(account), cb, user_data);
 }
 
@@ -960,13 +960,21 @@ request_password_ok_cb(PurpleAccount *ac
 	}
 
 	if(remember)
-	  purple_account_set_remember_password(account, TRUE);
+		purple_account_set_remember_password(account, TRUE);
 
 	purple_account_set_password(account, entry);
 
 	purple_connection_new(account, FALSE, entry);
 }
 
+static void
+request_password_cancel_cb(PurpleAccount *account, PurpleRequestFields *fields)
+{
+	/* Disable the account as the user has canceled connecting */
+	purple_account_set_enabled(account, purple_core_get_ui(), FALSE);
+}
+
+
 void
 purple_account_request_password(PurpleAccount *account, GCallback ok_cb,
 				GCallback cancel_cb, void *user_data)
@@ -1040,7 +1048,7 @@ purple_account_connect(PurpleAccount *ac
 	if ((password == NULL) &&
 		!(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
 		!(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
-		purple_account_request_password(account, G_CALLBACK(request_password_ok_cb), NULL, account);
+		purple_account_request_password(account, G_CALLBACK(request_password_ok_cb), G_CALLBACK(request_password_cancel_cb), account);
 	else
 		purple_connection_new(account, FALSE, password);
 }
@@ -1111,18 +1119,18 @@ purple_account_request_close_info(Purple
 	g_free(info);
 }
 
-void 
+void
 purple_account_request_close_with_account(PurpleAccount *account)
 {
 	GList *l, *l_next;
-	
+
 	g_return_if_fail(account != NULL);
-	
+
 	for (l = handles; l != NULL; l = l_next) {
 		PurpleAccountRequestInfo *info = l->data;
-		
+
 		l_next = l->next;
-		
+
 		if (info->account == account) {
 			handles = g_list_remove(handles, info);
 			purple_account_request_close_info(info);
@@ -1130,18 +1138,18 @@ purple_account_request_close_with_accoun
 	}
 }
 
-void 
+void
 purple_account_request_close(void *ui_handle)
 {
 	GList *l, *l_next;
-	
+
 	g_return_if_fail(ui_handle != NULL);
-	
+
 	for (l = handles; l != NULL; l = l_next) {
 		PurpleAccountRequestInfo *info = l->data;
-		
+
 		l_next = l->next;
-		
+
 		if (info->ui_handle == ui_handle) {
 			handles = g_list_remove(handles, info);
 			purple_account_request_close_info(info);
@@ -1172,7 +1180,7 @@ purple_account_request_authorization(Pur
 		handles = g_list_append(handles, info);
 		return info->ui_handle;
 	}
-	
+
 	return NULL;
 }
 
@@ -2443,7 +2451,7 @@ purple_accounts_init(void)
 						 purple_value_new(PURPLE_TYPE_SUBTYPE,
 							 			PURPLE_SUBTYPE_ACCOUNT),
 						 purple_value_new(PURPLE_TYPE_STRING));
-	
+
 	load_accounts();
 
 }
============================================================
--- libpurple/cmds.h	953c84ca8c44c8e5824209a605d5d889a96b1e0d
+++ libpurple/cmds.h	796e9865e88f475e0a36c93142e9170c3dc3cf26
@@ -67,10 +67,20 @@ enum _PurpleCmdPriority {
 	PURPLE_CMD_P_VERY_HIGH =  6000,
 };
 
+/** Flags used to set various properties of commands.  Every command should
+ *  have at least one of #PURPLE_CMD_FLAG_IM and #PURPLE_CMD_FLAG_CHAT set in
+ *  order to be even slighly useful.
+ *
+ *  @see purple_cmd_register
+ */
 enum _PurpleCmdFlag {
+	/** Command is usable in IMs. */
 	PURPLE_CMD_FLAG_IM               = 0x01,
+	/** Command is usable in multi-user chats. */
 	PURPLE_CMD_FLAG_CHAT             = 0x02,
+	/** Command is usable only for a particular prpl. */
 	PURPLE_CMD_FLAG_PRPL_ONLY        = 0x04,
+	/** Incorrect arguments to this command should be accepted anyway. */
 	PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS = 0x08,
 };
 
@@ -92,36 +102,49 @@ extern "C" {
  * The command will only happen if commands are enabled,
  * which is a UI pref. UIs don't have to support commands at all.
  *
- * @param cmd The command. This should be a UTF8 (or ASCII) string, with no spaces
+ * @param cmd The command. This should be a UTF-8 (or ASCII) string, with no spaces
  *            or other white space.
- * @param args This tells Purple how to parse the arguments to the command for you.
- *             If what the user types doesn't match, Purple will keep looking for another
- *             command, unless the flag @c PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed in f.
- *             This string contains no whitespace, and uses a single character for each argument.
- *             The recognized characters are:
- *               'w' Matches a single word.
- *               'W' Matches a single word, with formatting.
- *               's' Matches the rest of the arguments after this point, as a single string.
- *               'S' Same as 's' but with formatting.
+ * @param args A string of characters describing to libpurple how to parse this
+ *             command's arguments.  If what the user types doesn't match this
+ *             pattern, libpurple will keep looking for another command, unless
+ *             the flag #PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed in @a f.
+ *             This string should contain no whitespace, and use a single
+ *             character for each argument.  The recognized characters are:
+ *             <ul>
+ *               <li><tt>'w'</tt>: Matches a single word.</li>
+ *               <li><tt>'W'</tt>: Matches a single word, with formatting.</li>
+ *               <li><tt>'s'</tt>: Matches the rest of the arguments after this
+ *                                 point, as a single string.</li>
+ *               <li><tt>'S'</tt>: Same as <tt>'s'</tt> but with formatting.</li>
+ *             </ul>
  *             If args is the empty string, then the command accepts no arguments.
- *             The args passed to callback func will be a @c NULL terminated array of null
- *             terminated strings, and will always match the number of arguments asked for,
- *             unless PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed.
- * @param p This is the priority. Higher priority commands will be run first, and usually the
- *          first command will stop any others from being called.
- * @param f These are the flags. You need to at least pass one of PURPLE_CMD_FLAG_IM or
- *          PURPLE_CMD_FLAG_CHAT (can may pass both) in order for the command to ever actually
- *          be called.
- * @param prpl_id This is the prpl's id string. This is only meaningful if the proper flag is set.
+ *             The args passed to the callback @a func will be a @c NULL
+ *             terminated array of @c NULL terminated strings, and will always
+ *             match the number of arguments asked for, unless
+ *             #PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS is passed.
+ * @param p This is the priority. Higher priority commands will be run first,
+ *          and usually the first command will stop any others from being
+ *          called.
+ * @param f Flags specifying various options about this command, combined with
+ *          <tt>|</tt> (bitwise OR). You need to at least pass one of
+ *          #PURPLE_CMD_FLAG_IM or #PURPLE_CMD_FLAG_CHAT (you may pass both) in
+ *          order for the command to ever actually be called.
+ * @param prpl_id If the #PURPLE_CMD_FLAG_PRPL_ONLY flag is set, this is the id
+ *                of the prpl to which the command applies (such as
+ *                <tt>"prpl-msn"</tt>). If the flag is not set, this parameter
+ *                is ignored; pass @c NULL (or a humourous string of your
+ *                choice!).
  * @param func This is the function to call when someone enters this command.
- * @param helpstr This is a whitespace sensitive, UTF-8, HTML string describing how to use the command.
- *                The preferred format of this string shall be the commands name, followed by a space
- *                and any arguments it accepts (if it takes any arguments, otherwise no space), followed
- *                by a colon, two spaces, and a description of the command in sentence form. No slash
- *                before the command name.
- * @param data User defined data to pass to the PurpleCmdFunc
- * @return A PurpleCmdId. This is only used for calling purple_cmd_unregister.
- *         Returns 0 on failure.
+ * @param helpstr a whitespace sensitive, UTF-8, HTML string describing how to
+ *                use the command.  The preferred format of this string is the
+ *                command's name, followed by a space and any arguments it
+ *                accepts (if it takes any arguments, otherwise no space),
+ *                followed by a colon, two spaces, and a description of the
+ *                command in sentence form.  Do not include a slash before the
+ *                command name.
+ * @param data User defined data to pass to the #PurpleCmdFunc @a f.
+ * @return A #PurpleCmdId, which is only used for calling
+ *         #purple_cmd_unregister, or @a 0 on failure.
  */
 PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args, PurpleCmdPriority p, PurpleCmdFlag f,
                              const gchar *prpl_id, PurpleCmdFunc func, const gchar *helpstr, void *data);
@@ -133,7 +156,7 @@ PurpleCmdId purple_cmd_register(const gc
  * or something else that might go away. Normally this is called when the plugin
  * unloads itself.
  *
- * @param id The PurpleCmdId to unregister.
+ * @param id The #PurpleCmdId to unregister, as returned by #purple_cmd_register.
  */
 void purple_cmd_unregister(PurpleCmdId id);
 
@@ -153,7 +176,7 @@ void purple_cmd_unregister(PurpleCmdId i
  *               include both the default formatting and any extra manual formatting.
  * @param errormsg If the command failed errormsg is filled in with the appropriate error
  *                 message. It must be freed by the caller with g_free().
- * @return A PurpleCmdStatus indicated if the command succeeded or failed.
+ * @return A #PurpleCmdStatus indicated if the command succeeded or failed.
  */
 PurpleCmdStatus purple_cmd_do_command(PurpleConversation *conv, const gchar *cmdline,
                                   const gchar *markup, gchar **errormsg);
@@ -161,13 +184,15 @@ PurpleCmdStatus purple_cmd_do_command(Pu
 /**
  * List registered commands.
  *
- * Returns a GList (which must be freed by the caller) of all commands
- * that are valid in the context of conv, or all commands, if conv is
- * @c NULL. Don't keep this list around past the main loop, or anything else
- * that might unregister a command, as the char*'s used get freed then.
+ * Returns a <tt>GList</tt> (which must be freed by the caller) of all commands
+ * that are valid in the context of @a conv, or all commands, if @a conv is @c
+ * NULL.  Don't keep this list around past the main loop, or anything else that
+ * might unregister a command, as the <tt>const char *</tt>'s used get freed
+ * then.
  *
  * @param conv The conversation, or @c NULL.
- * @return A GList of const char*, which must be freed with g_list_free().
+ * @return A @c GList of <tt>const char *</tt>, which must be freed with
+ *         <tt>g_list_free()</tt>.
  */
 GList *purple_cmd_list(PurpleConversation *conv);
 
@@ -180,7 +205,7 @@ GList *purple_cmd_list(PurpleConversatio
  * @param conv The conversation, or @c NULL for no context.
  * @param cmd The command. No wildcards accepted, but returns help for all
  *            commands if @c NULL.
- * @return A GList of const char*s, which is the help string
+ * @return A <tt>GList</tt> of <tt>const char *</tt>s, which is the help string
  *         for that command.
  */
 GList *purple_cmd_help(PurpleConversation *conv, const gchar *cmd);
============================================================
--- libpurple/dnssrv.c	2fd26c74fed3be685076a0478ffd07f5cf378d8c
+++ libpurple/dnssrv.c	21f0607230b52f7bb12383741c8648a8df182f1c
@@ -69,6 +69,7 @@ struct _PurpleSrvQueryData {
 	char *error_message;
 	GSList *results;
 #else
+	int fd_in, fd_out;
 	pid_t pid;
 #endif
 };
@@ -112,8 +113,11 @@ resolve(int in, int out)
 	purple_restore_default_signal_handlers();
 #endif
 
-	if (read(in, query, 256) <= 0)
+	if (read(in, query, 256) <= 0) {
+		close(out);
+		close(in);
 		_exit(0);
+	}
 
 	size = res_query( query, C_IN, T_SRV, (u_char*)&answer, sizeof( answer));
 
@@ -179,6 +183,9 @@ end:
 		ret = g_list_remove(ret, ret->data);
 	}
 
+	close(out);
+	close(in);
+
 	_exit(0);
 }
 
@@ -358,6 +365,8 @@ purple_srv_resolve(const char *protocol,
 	query_data->cb = cb;
 	query_data->extradata = extradata;
 	query_data->pid = pid;
+	query_data->fd_out = out[0];
+	query_data->fd_in = in[1];
 	query_data->handle = purple_input_add(out[0], PURPLE_INPUT_READ, resolved, query_data);
 
 	g_free(query);
@@ -414,6 +423,9 @@ purple_srv_cancel(PurpleSrvQueryData *qu
 	}
 	g_free(query_data->query);
 	g_free(query_data->error_message);
+#else
+	close(query_data->fd_out);
+	close(query_data->fd_in);
 #endif
 	g_free(query_data);
 }
============================================================
--- libpurple/ft.c	59e9d4da28a7d81ee7a76c399c4115445cca466f
+++ libpurple/ft.c	32dae7657417fd89f64ba4b5563ffbff9ae19013
@@ -67,6 +67,7 @@ purple_xfer_new(PurpleAccount *account, 
 	xfer->ui_ops  = purple_xfers_get_ui_ops();
 	xfer->message = NULL;
 	xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
+	xfer->fd = -1;
 
 	ui_ops = purple_xfer_get_ui_ops(xfer);
 
============================================================
--- libpurple/protocols/jabber/auth.c	43d0094f5eb9cee59b3edc6cbe6e7a9a430167df
+++ libpurple/protocols/jabber/auth.c	5b9f4e7c28a89ddc6879a963fc646b14f6f7ab4e
@@ -23,6 +23,7 @@
 #include "account.h"
 #include "debug.h"
 #include "cipher.h"
+#include "core.h"
 #include "conversation.h"
 #include "request.h"
 #include "sslconn.h"
@@ -66,10 +67,10 @@ static void finish_plaintext_authenticat
 
 		auth = xmlnode_new("auth");
 		xmlnode_set_namespace(auth, "urn:ietf:params:xml:ns:xmpp-sasl");
-		
+
 		xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
 		xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
-		
+
 		response = g_string_new("");
 		response = g_string_append_len(response, "\0", 1);
 		response = g_string_append(response, js->user->node);
@@ -202,7 +203,7 @@ static gboolean auth_pass_generic(Jabber
 
 	return TRUE;
 }
-	
+
 static void auth_pass_cb(PurpleConnection *conn, PurpleRequestFields *fields)
 {
 	JabberStream *js;
@@ -236,7 +237,7 @@ auth_old_pass_cb(PurpleConnection *conn,
 
 	if (!auth_pass_generic(js, fields))
 		return;
-	
+
 	/* Restart our connection */
 	jabber_auth_start_old(js);
 }
@@ -253,7 +254,8 @@ auth_no_pass_cb(PurpleConnection *conn, 
 
 	js = conn->proto_data;
 
-	purple_connection_error(conn, _("Password is required to sign on."));
+	/* Disable the account as the user has canceled connecting */
+	purple_account_set_enabled(conn->account, purple_core_get_ui(), FALSE);
 }
 
 static void jabber_auth_start_cyrus(JabberStream *js)
@@ -621,7 +623,7 @@ void jabber_auth_start_old(JabberStream 
 	 * to OPTIONAL for this protocol. So, we need to do our own
 	 * password prompting here
 	 */
-	
+
 	if (!purple_account_get_password(js->gc->account)) {
 		purple_account_request_password(js->gc->account, G_CALLBACK(auth_old_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc);
 		return;
============================================================
--- libpurple/protocols/yahoo/yahoo_filexfer.c	c3030fac3a35f7fd44b05ff40e7f2090fe491c4c
+++ libpurple/protocols/yahoo/yahoo_filexfer.c	148c1cac5309d294bc3bb5482687a5fb0cdb1167
@@ -281,13 +281,9 @@ static void yahoo_xfer_init(PurpleXfer *
 			}
 		}
 	} else {
-		/* TODO: Using xfer->fd like this is probably a bad thing... */
+		xfer->fd = -1;
 		if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port,
-		                              yahoo_receivefile_connected, xfer) == NULL)
-			xfer->fd = -1;
-		else
-			xfer->fd = 0;
-		if (xfer->fd == -1) {
+		                              yahoo_receivefile_connected, xfer) == NULL) {
 			purple_notify_error(gc, NULL, _("File Transfer Failed"),
 			             _("Unable to establish file descriptor."));
 			purple_xfer_cancel_remote(xfer);
============================================================
--- libpurple/status.c	186dd554d259db6734202e08e005279fc0327dcb
+++ libpurple/status.c	603b583997ce734929249cfd927e7d8205b4013d
@@ -601,7 +601,7 @@ notify_buddy_status_update(PurpleBuddy *
 	{
 		time_t current_time = time(NULL);
 		const char *buddy_alias = purple_buddy_get_alias(buddy);
-		char *tmp;
+		char *tmp, *logtmp;
 		PurpleLog *log;
 
 		if (old_status != NULL)
@@ -609,6 +609,10 @@ notify_buddy_status_update(PurpleBuddy *
 			tmp = g_strdup_printf(_("%s changed status from %s to %s"), buddy_alias,
 			                      purple_status_get_name(old_status),
 			                      purple_status_get_name(new_status));
+			logtmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, buddy->name,
+			                      purple_status_get_name(old_status),
+			                      purple_status_get_name(new_status));
+
 		}
 		else
 		{
@@ -618,11 +622,16 @@ notify_buddy_status_update(PurpleBuddy *
 			{
 				tmp = g_strdup_printf(_("%s is now %s"), buddy_alias,
 				                      purple_status_get_name(new_status));
+				logtmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, buddy->name,
+				                      purple_status_get_name(new_status));
+
 			}
 			else
 			{
 				tmp = g_strdup_printf(_("%s is no longer %s"), buddy_alias,
 				                      purple_status_get_name(new_status));
+				logtmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, buddy->name,
+				                      purple_status_get_name(new_status));
 			}
 		}
 
@@ -630,10 +639,11 @@ notify_buddy_status_update(PurpleBuddy *
 		if (log != NULL)
 		{
 			purple_log_write(log, PURPLE_MESSAGE_SYSTEM, buddy_alias,
-			               current_time, tmp);
+			               current_time, logtmp);
 		}
 
 		g_free(tmp);
+		g_free(logtmp);
 	}
 }
 
============================================================
--- libpurple/upnp.c	9f7037509c784f450f1fb4ad33176d040c1579dc
+++ libpurple/upnp.c	78c0017916277fdb5bc0000cca06c35fb3a031ff
@@ -553,7 +553,7 @@ purple_upnp_discover_udp_read(gpointer d
 	dd->inpa = 0;
 
 	close(dd->fd);
-	dd->fd = 0;
+	dd->fd = -1;
 
 	/* parse the response, and see if it was a success */
 	purple_upnp_parse_discover_response(buf, len, dd);
============================================================
--- libpurple/util.c	504ff584b386911ab4c77743e8e17df9e684caf6
+++ libpurple/util.c	333952029f746cf825390ccadfc3489a3bbf5bad
@@ -3870,6 +3870,7 @@ purple_util_fetch_url_request(const char
 	gfud->full = full;
 	gfud->request = g_strdup(request);
 	gfud->include_headers = include_headers;
+	gfud->fd = -1;
 
 	purple_url_parse(url, &gfud->website.address, &gfud->website.port,
 				   &gfud->website.page, &gfud->website.user, &gfud->website.passwd);
============================================================
--- pidgin/gtkconv.c	ae2a582300ca2f4789b9f0981a2884cf2b3f39fc
+++ pidgin/gtkconv.c	981eb411a6aa58d72585ac1d81099e69382582d9
@@ -4490,7 +4490,7 @@ setup_chat_userlist(PidginConversation *
 	g_signal_connect(G_OBJECT(list), "motion-notify-event",
 					 G_CALLBACK(pidgin_userlist_motion_cb), gtkconv);
 	g_signal_connect(G_OBJECT(list), "leave-notify-event",
-					 G_CALLBACK(pidgin_userlist_motion_cb), gtkconv);
+					 G_CALLBACK(pidgin_conv_leave_cb), gtkconv);
 	g_signal_connect(G_OBJECT(list), "popup-menu",
 			 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv);
 	g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv);
@@ -4618,10 +4618,8 @@ pidgin_userlist_tooltip_timeout(PidginCo
 
 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
 
-	gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list),
-								  tooltip.userlistx, tooltip.userlisty, &path, &column, &x, &y);
-
-	if (path == NULL)
+	if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list),
+								  tooltip.userlistx, tooltip.userlisty, &path, &column, &x, &y))
 		return FALSE;
 
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
============================================================
--- pidgin/gtkdocklet.c	70e5582a286631d41683a4a3f0f07ee026e3b33d
+++ pidgin/gtkdocklet.c	c0fbf99c7ebe18814fa14bd3c151a2ee8929eafd
@@ -532,7 +532,7 @@ docklet_menu() {
 	g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_mute), NULL);
 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 
-	menuitem = gtk_check_menu_item_new_with_label(_("Blink On New Message"));
+	menuitem = gtk_check_menu_item_new_with_label(_("Blink on New Message"));
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink"));
 	g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_blink), NULL);
 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
============================================================
--- pidgin/gtkimhtml.c	77589de31ac3088af69562e1ce335f93d8e3d701
+++ pidgin/gtkimhtml.c	5da45f5e789c81e8967f951df1dcca1016a57791
@@ -3211,24 +3211,25 @@ animate_image_cb(gpointer data)
 	im_image = data;
 
 	/* Update the pointer to this GdkPixbuf frame of the animation */
-	g_object_unref(G_OBJECT(im_image->pixbuf));
-	gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL);
-	im_image->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
-	g_object_ref(G_OBJECT(im_image->pixbuf));
+	if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
+		GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
+		g_object_unref(G_OBJECT(im_image->pixbuf));
+		im_image->pixbuf = gdk_pixbuf_copy(pb);
 
-	/* Update the displayed GtkImage */
-	width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
-	height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
-	if (width > 0 && height > 0)
-	{
-		/* Need to scale the new frame to the same size as the old frame */
-		GdkPixbuf *tmp;
-		tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
-		gtk_image_set_from_pixbuf(im_image->image, tmp);
-		g_object_unref(G_OBJECT(tmp));
-	} else {
-		/* Display at full-size */
-		gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
+		/* Update the displayed GtkImage */
+		width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
+		height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
+		if (width > 0 && height > 0)
+		{
+			/* Need to scale the new frame to the same size as the old frame */
+			GdkPixbuf *tmp;
+			tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
+			gtk_image_set_from_pixbuf(im_image->image, tmp);
+			g_object_unref(G_OBJECT(tmp));
+		} else {
+			/* Display at full-size */
+			gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
+		}
 	}
 
 	delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
@@ -3249,11 +3250,14 @@ GtkIMHtmlScalable *gtk_imhtml_animation_
 	if (gdk_pixbuf_animation_is_static_image(anim)) {
 		GTK_IMHTML_ANIMATION(im_image)->iter = NULL;
 		im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
+		g_object_ref(im_image->pixbuf);
 		GTK_IMHTML_ANIMATION(im_image)->timer = 0;
 	} else {
 		int delay;
+		GdkPixbuf *pb;
 		GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
-		im_image->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
+		pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
+		im_image->pixbuf = gdk_pixbuf_copy(pb);
 		delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
 		GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
 	}
@@ -3266,7 +3270,6 @@ GtkIMHtmlScalable *gtk_imhtml_animation_
 	im_image->filesel = NULL;
 
 	g_object_ref(anim);
-	g_object_ref(im_image->pixbuf);
 
 	return GTK_IMHTML_SCALABLE(im_image);
 }
@@ -4606,10 +4609,15 @@ void gtk_imhtml_insert_smiley_at_iter(Gt
 				if (imhtml->num_animations == 20) {
 					GtkImage *image = GTK_IMAGE(g_queue_pop_head(imhtml->animations));
 					GdkPixbufAnimation *anim = gtk_image_get_animation(image);
+					g_signal_handlers_disconnect_matched(G_OBJECT(image), G_SIGNAL_MATCH_FUNC,
+							 0, 0, NULL, G_CALLBACK(animated_smiley_destroy_cb), NULL);
 					if (anim) {
 						GdkPixbuf *pb = gdk_pixbuf_animation_get_static_image(anim);
-						gtk_image_set_from_pixbuf(image, pb);
-						g_object_unref(G_OBJECT(pb));
+						if (pb != NULL) {
+							GdkPixbuf *copy = gdk_pixbuf_copy(pb);
+							gtk_image_set_from_pixbuf(image, copy);
+							g_object_unref(G_OBJECT(copy));
+						}
 					}
 				} else {
  					imhtml->num_animations++;
============================================================
--- pidgin/plugins/gtkbuddynote.c	ceea38e2b71e6cdb0ff0ddbb2da042327ad0f68b
+++ pidgin/plugins/gtkbuddynote.c	1fd6753cdc854757b15b841f0c9724c694c5fe73
@@ -31,8 +31,11 @@ append_to_tooltip(PurpleBlistNode *node,
 		const gchar *note = purple_blist_node_get_string(node, "notes");
 
 		if ((note != NULL) && (*note != '\0')) {
+			char *tmp;
+			purple_markup_html_to_xhtml(note, NULL, &tmp);
 			g_string_append_printf(text, _("\n<b>Buddy Note</b>: %s"),
-			                       note);
+			                       tmp);
+			g_free(tmp);
 		}
 	}
 }


More information about the Commits mailing list