changeset 28036:8be4bea98188

merged with im.pidgin.pidgin
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 27 Jul 2009 15:22:00 +0900
parents c81386a2b292 (current diff) 14ce47859540 (diff)
children f1ce91569ed3
files configure.ac libpurple/conversation.c libpurple/protocols/yahoo/libymsg.c libpurple/protocols/yahoo/util.c libpurple/protocols/yahoo/yahoo_filexfer.c libpurple/protocols/yahoo/yahoo_packet.c libpurple/protocols/yahoo/yahoo_profile.c libpurple/protocols/yahoo/yahoochat.c
diffstat 33 files changed, 504 insertions(+), 257 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jul 27 01:08:46 2009 +0900
+++ b/ChangeLog	Mon Jul 27 15:22:00 2009 +0900
@@ -3,7 +3,7 @@
 version 2.6.0 (??/??/2009):
 	libpurple:
 	* Theme support in libpurple thanks to Justin Rodriguez's summer of code
-	  project.  With some minor additions and clean ups from Paul Aurich.
+	  project, with some minor additions and cleanups from Paul Aurich.
 	* Voice & Video framework in libpurple, thanks to Mike Ruprecht's summer
 	  of code project in 2008.
 	* It should no longer be possible to end up with duplicates of buddies
@@ -36,7 +36,7 @@
 	  (Aman Gupta)
 	* Don't fork a DNS resolver process to resolve IP addresses.  (Aman Gupta)
 	* Better handling of corrupt certificates in the TLS Peers cache.
-	* More efficient purple_find_buddies() and purple_find_group() functions.
+	* More efficient buddy list and conversation search functions.
 	  (Jan Kaluza and Aman Gupta)
 	* Internationalized Domain Names are supported when libpurple is compiled
 	  against the GNU IDN library.
@@ -119,10 +119,11 @@
 	  (Sulabh Mahajan)
 	* Addition of MSN buddies to Yahoo accounts by adding them as
 	  'msn/buddy@somedomain.com' is now supported.  (Sulabh Mahajan)
-	* Further fixes for buddy pictures, aliases etc.
+	* Further fixes for buddy pictures, aliases, etc.
 	* Yahoo! and Yahoo! JAPAN are now two separate protocol plugins that share
 	  common protocol code.  You can now have the same account on both
-	  networks.
+	  networks.  Accounts should be seamlessly migrated to the new
+	  arrangement.
 	* Ability to set personal details for an account and for buddies in the
 	  buddylist.
 
--- a/ChangeLog.API	Mon Jul 27 01:08:46 2009 +0900
+++ b/ChangeLog.API	Mon Jul 27 15:22:00 2009 +0900
@@ -15,6 +15,9 @@
 			* account-destroying
 		* blist-node-added and blist-node-removed signals (see
 		  blist-signals.dox)
+		* Three Blist UI ops used to overload libpurple's built-in saving
+		  of the buddy list to blist.xml. If a UI implements these, it probably
+		  wants to add the buddies itself and not call purple_blist_load.
 		* Jabber plugin signals (see jabber-signals.dox)
 		* purple_account_remove_setting
 		* purple_buddy_destroy
@@ -85,6 +88,8 @@
 		* purple_find_buddies is now more efficient in the case where
 		  it is enumerating all the buddies for an account.
 		* purple_find_group is now more efficient for large numbers of groups.
+		* purple_find_conversation_with_account is more efficient for large
+		  numbers of concurrent conversations.
 		* All DNS routines support internationalized domain names (IDNs) when
 		  libpurple is compiled with GNU libidn.
 		* status is set before emitting signals in purple_xfer_set_status.
--- a/configure.ac	Mon Jul 27 01:08:46 2009 +0900
+++ b/configure.ac	Mon Jul 27 15:22:00 2009 +0900
@@ -1640,14 +1640,14 @@
 dnl # Thanks go to Evolution for the checks.
 dnl #######################################################################
 
-AC_ARG_WITH(with-system-ssl-certs, [AC_HELP_STRING([--with-system-ssl-certs=<dir>], [directory containing system-wide SSL CA certificates])])
+AC_ARG_WITH(system-ssl-certs, [AC_HELP_STRING([--with-system-ssl-certs=<dir>], [directory containing system-wide SSL CA certificates])], [ssl_certificates_dir=$withval])
 
 SSL_CERTIFICATES_DIR=""
-if ! test -z "$with_system_ssl_certs" ; then
-	if ! test -d "$with_system_ssl_certs" ; then
-		AC_MSG_ERROR([$with_system_ssl_certs does not exist, if this is the correct location please make sure that it exists.])
+if ! test -z "$ssl_certificates_dir" ; then
+	if ! test -d "$ssl_certificates_dir" ; then
+		AC_MSG_ERROR([$ssl_certificates_dir does not exist, if this is the correct location please make sure that it exists.])
 	fi
-	SSL_CERTIFICATES_DIR="$with_system_ssl_certs"
+	SSL_CERTIFICATES_DIR="$ssl_certificates_dir"
 fi
 AC_SUBST(SSL_CERTIFICATES_DIR)
 AM_CONDITIONAL(INSTALL_SSL_CERTIFICATES, test "x$SSL_CERTIFICATES_DIR" = "x")
--- a/libpurple/account.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/account.c	Mon Jul 27 15:22:00 2009 +0900
@@ -1534,6 +1534,8 @@
 void
 purple_account_set_username(PurpleAccount *account, const char *username)
 {
+	PurpleBlistUiOps *blist_ops;
+
 	g_return_if_fail(account != NULL);
 
 	g_free(account->username);
@@ -1543,7 +1545,9 @@
 
 	/* if the name changes, we should re-write the buddy list
 	 * to disk with the new name */
-	purple_blist_schedule_save();
+	blist_ops = purple_blist_get_ui_ops();
+	if (blist_ops != NULL && blist_ops->save_account != NULL)
+		blist_ops->save_account(account);
 }
 
 void
--- a/libpurple/blist.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/blist.c	Mon Jul 27 15:22:00 2009 +0900
@@ -393,13 +393,42 @@
 	return FALSE;
 }
 
-void
-purple_blist_schedule_save()
+static void
+_purple_blist_schedule_save()
 {
 	if (save_timer == 0)
 		save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
 }
 
+static void
+purple_blist_save_account(PurpleAccount *account)
+{
+#if 1
+	_purple_blist_schedule_save();
+#else
+	if (account != NULL) {
+		/* Save the buddies and privacy data for this account */
+	} else {
+		/* Save all buddies and privacy data */
+	}
+#endif
+}
+
+static void
+purple_blist_save_node(PurpleBlistNode *node)
+{
+	_purple_blist_schedule_save();
+}
+
+void purple_blist_schedule_save()
+{
+	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+
+	/* Save everything */
+	if (ops && ops->save_account)
+		ops->save_account(NULL);
+}
+
 
 /*********************************************************************
  * Reading from disk                                                 *
@@ -971,7 +1000,8 @@
 	g_free(buddy->name);
 	buddy->name = g_strdup(name);
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode *) buddy);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
@@ -1011,7 +1041,8 @@
 		g_free(new_alias); /* could be "\0" */
 	}
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode*) contact);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode *)contact);
@@ -1056,7 +1087,8 @@
 		g_free(new_alias); /* could be "\0" */
 	}
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode*) chat);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode *)chat);
@@ -1092,7 +1124,8 @@
 		g_free(new_alias); /* could be "\0" */
 	}
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode*) buddy);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
@@ -1133,7 +1166,8 @@
 		g_free(new_alias); /* could be "\0"; */
 	}
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode*) buddy);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
@@ -1235,7 +1269,8 @@
 	}
 
 	/* Save our changes */
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode*) source);
 
 	/* Update the UI */
 	if (ops && ops->update)
@@ -1493,8 +1528,6 @@
 		 * reinitialize it */
 		if (ops && ops->new_node)
 			ops->new_node(cnode);
-
-		purple_blist_schedule_save();
 	}
 
 	if (node != NULL) {
@@ -1523,7 +1556,8 @@
 		}
 	}
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node(cnode);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode *)cnode);
@@ -1601,8 +1635,6 @@
 		if (ops && ops->remove)
 			ops->remove(purplebuddylist, bnode);
 
-		purple_blist_schedule_save();
-
 		if (bnode->parent->parent != (PurpleBlistNode*)g) {
 			struct _purple_hbuddy hb;
 			hb.name = (gchar *)purple_normalize(buddy->account, buddy->name);
@@ -1667,7 +1699,8 @@
 
 	purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+		ops->save_node((PurpleBlistNode*) buddy);
 
 	if (ops && ops->update)
 		ops->update(purplebuddylist, (PurpleBlistNode*)buddy);
@@ -1886,7 +1919,8 @@
 		if (ops && ops->remove)
 			ops->remove(purplebuddylist, cnode);
 
-		purple_blist_schedule_save();
+		if (ops && ops->remove_node)
+			ops->remove_node(cnode);
 	}
 
 	if (node && (PURPLE_BLIST_NODE_IS_CONTACT(node) ||
@@ -1912,7 +1946,13 @@
 		g->currentsize++;
 	g->totalsize++;
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node)
+	{
+		if (cnode->child)
+			ops->save_node(cnode);
+		for (bnode = cnode->child; bnode; bnode = bnode->next)
+			ops->save_node(bnode);
+	}
 
 	if (ops && ops->update)
 	{
@@ -2012,7 +2052,11 @@
 		purplebuddylist->root = gnode;
 	}
 
-	purple_blist_schedule_save();
+	if (ops && ops->save_node) {
+		ops->save_node(gnode);
+		for (node = gnode->child; node; node = node->next)
+			ops->save_node(node);
+	}
 
 	if (ops && ops->update) {
 		ops->update(purplebuddylist, gnode);
@@ -2058,12 +2102,13 @@
 		if (node->next)
 			node->next->prev = node->prev;
 
-		purple_blist_schedule_save();
-
 		/* Update the UI */
 		if (ops && ops->remove)
 			ops->remove(purplebuddylist, node);
 
+		if (ops && ops->remove_node)
+			ops->remove_node(node);
+
 		purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
 				PURPLE_BLIST_NODE(contact));
 
@@ -2119,8 +2164,6 @@
 		}
 	}
 
-	purple_blist_schedule_save();
-
 	/* Remove this buddy from the buddies hash table */
 	hb.name = (gchar *)purple_normalize(buddy->account, buddy->name);
 	hb.account = buddy->account;
@@ -2134,6 +2177,9 @@
 	if (ops && ops->remove)
 		ops->remove(purplebuddylist, node);
 
+	if (ops && ops->remove_node)
+		ops->remove_node(node);
+
 	/* Signal that the buddy has been removed before freeing the memory for it */
 	purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy);
 
@@ -2176,13 +2222,15 @@
 		}
 		group->totalsize--;
 
-		purple_blist_schedule_save();
 	}
 
 	/* Update the UI */
 	if (ops && ops->remove)
 		ops->remove(purplebuddylist, node);
 
+	if (ops && ops->remove_node)
+		ops->remove_node(node);
+
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
 			PURPLE_BLIST_NODE(chat));
 
@@ -2217,12 +2265,13 @@
 	g_hash_table_remove(groups_cache, key);
 	g_free(key);
 
-	purple_blist_schedule_save();
-
 	/* Update the UI */
 	if (ops && ops->remove)
 		ops->remove(purplebuddylist, node);
 
+	if (ops && ops->remove_node)
+		ops->remove_node(node);
+
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
 			PURPLE_BLIST_NODE(group));
 
@@ -2827,13 +2876,16 @@
 
 void purple_blist_node_remove_setting(PurpleBlistNode *node, const char *key)
 {
+	PurpleBlistUiOps *ops;
 	g_return_if_fail(node != NULL);
 	g_return_if_fail(node->settings != NULL);
 	g_return_if_fail(key != NULL);
 
 	g_hash_table_remove(node->settings, key);
 
-	purple_blist_schedule_save();
+	ops = purple_blist_get_ui_ops();
+	if (ops && ops->save_node)
+		ops->save_node(node);
 }
 
 void
@@ -2863,6 +2915,7 @@
 purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data)
 {
 	PurpleValue *value;
+	PurpleBlistUiOps *ops;
 
 	g_return_if_fail(node != NULL);
 	g_return_if_fail(node->settings != NULL);
@@ -2873,7 +2926,9 @@
 
 	g_hash_table_replace(node->settings, g_strdup(key), value);
 
-	purple_blist_schedule_save();
+	ops = purple_blist_get_ui_ops();
+	if (ops && ops->save_node)
+		ops->save_node(node);
 }
 
 gboolean
@@ -2899,6 +2954,7 @@
 purple_blist_node_set_int(PurpleBlistNode* node, const char *key, int data)
 {
 	PurpleValue *value;
+	PurpleBlistUiOps *ops;
 
 	g_return_if_fail(node != NULL);
 	g_return_if_fail(node->settings != NULL);
@@ -2909,7 +2965,9 @@
 
 	g_hash_table_replace(node->settings, g_strdup(key), value);
 
-	purple_blist_schedule_save();
+	ops = purple_blist_get_ui_ops();
+	if (ops && ops->save_node)
+		ops->save_node(node);
 }
 
 int
@@ -2935,6 +2993,7 @@
 purple_blist_node_set_string(PurpleBlistNode* node, const char *key, const char *data)
 {
 	PurpleValue *value;
+	PurpleBlistUiOps *ops;
 
 	g_return_if_fail(node != NULL);
 	g_return_if_fail(node->settings != NULL);
@@ -2945,7 +3004,9 @@
 
 	g_hash_table_replace(node->settings, g_strdup(key), value);
 
-	purple_blist_schedule_save();
+	ops = purple_blist_get_ui_ops();
+	if (ops && ops->save_node)
+		ops->save_node(node);
 }
 
 const char *
@@ -2999,7 +3060,31 @@
 void
 purple_blist_set_ui_ops(PurpleBlistUiOps *ops)
 {
+	gboolean overrode = FALSE;
 	blist_ui_ops = ops;
+
+	if (!ops)
+		return;
+
+	if (!ops->save_node) {
+		ops->save_node = purple_blist_save_node;
+		overrode = TRUE;
+	}
+	if (!ops->remove_node) {
+		ops->remove_node = purple_blist_save_node;
+		overrode = TRUE;
+	}
+	if (!ops->save_account) {
+		ops->save_account = purple_blist_save_account;
+		overrode = TRUE;
+	}
+
+	if (overrode && (ops->save_node    != purple_blist_save_node ||
+	                 ops->remove_node  != purple_blist_save_node ||
+	                 ops->save_account != purple_blist_save_account)) {
+		purple_debug_warning("blist", "Only some of the blist saving UI ops "
+				"were overridden. This probably is not what you want!\n");
+	}
 }
 
 PurpleBlistUiOps *
--- a/libpurple/blist.h	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/blist.h	Mon Jul 27 15:22:00 2009 +0900
@@ -216,10 +216,49 @@
 							 const char *alias, const char *name);
 	void (*request_add_group)(void);
 
+	/**
+	 * This is called when a node has been modified and should be saved.
+	 *
+	 * Implementation of this UI op is OPTIONAL. If not implemented, it will
+	 * be set to a fallback function that saves data to blist.xml like in
+	 * previous libpurple versions.
+	 *
+	 * @attrib node    The node which has been modified.
+	 *
+	 * @since 2.6.0.
+	 */
+	void (*save_node)(PurpleBlistNode *node);
+
+	/**
+	 * Called when a node is about to be removed from the buddy list.
+	 * The UI op should update the relevant data structures to remove this
+	 * node (for example, removing a buddy from the group this node is in).
+	 *
+	 * Implementation of this UI op is OPTIONAL. If not implemented, it will
+	 * be set to a fallback function that saves data to blist.xml like in
+	 * previous libpurple versions.
+	 *
+	 * @attrib node  The node which has been modified.
+	 * @since 2.6.0.
+	 */
+	void (*remove_node)(PurpleBlistNode *node);
+
+	/**
+	 * Called to save all the data for an account. If the UI sets this,
+	 * the callback must save the privacy and buddy list data for an account.
+	 * If the account is NULL, save the data for all accounts.
+	 *
+	 * Implementation of this UI op is OPTIONAL. If not implemented, it will
+	 * be set to a fallback function that saves data to blist.xml like in
+	 * previous libpurple versions.
+	 *
+	 * @attrib account  The account whose data to save. If NULL, save all data
+	 *                  for all accounts.
+	 * @since 2.6.0.
+	 */
+	void (*save_account)(PurpleAccount *account);
+
 	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
 };
 
 #ifdef __cplusplus
--- a/libpurple/conversation.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/conversation.c	Mon Jul 27 15:22:00 2009 +0900
@@ -40,6 +40,36 @@
 static GList *chats = NULL;
 static PurpleConversationUiOps *default_ops = NULL;
 
+/**
+ * A hash table used for efficient lookups of conversations by name.
+ * struct _purple_hconv => PurpleConversation*
+ */
+static GHashTable *conversation_cache = NULL;
+
+struct _purple_hconv {
+	PurpleConversationType type;
+	char *name;
+	const PurpleAccount *account;
+};
+
+static guint _purple_conversations_hconv_hash(struct _purple_hconv *hc)
+{
+	return g_str_hash(hc->name) ^ hc->type ^ g_direct_hash(hc->account);
+}
+
+static guint _purple_conversations_hconv_equal(struct _purple_hconv *hc1, struct _purple_hconv *hc2)
+{
+	return (hc1->type == hc2->type &&
+	        hc1->account == hc2->account &&
+	        g_str_equal(hc1->name, hc2->name));
+}
+
+static void _purple_conversations_hconv_free_key(struct _purple_hconv *hc)
+{
+	g_free(hc->name);
+	g_free(hc);
+}
+
 void
 purple_conversations_set_ui_ops(PurpleConversationUiOps *ops)
 {
@@ -287,6 +317,7 @@
 	PurpleConversation *conv;
 	PurpleConnection *gc;
 	PurpleConversationUiOps *ops;
+	struct _purple_hconv *hc;
 
 	g_return_val_if_fail(type    != PURPLE_CONV_TYPE_UNKNOWN, NULL);
 	g_return_val_if_fail(account != NULL, NULL);
@@ -342,7 +373,7 @@
 		conv->u.im->conv = conv;
 		PURPLE_DBUS_REGISTER_POINTER(conv->u.im, PurpleConvIm);
 
-		ims = g_list_append(ims, conv);
+		ims = g_list_prepend(ims, conv);
 		if ((icon = purple_buddy_icons_find(account, name)))
 		{
 			purple_conv_im_set_icon(conv->u.im, icon);
@@ -364,7 +395,7 @@
 		conv->u.chat->conv = conv;
 		PURPLE_DBUS_REGISTER_POINTER(conv->u.chat, PurpleConvChat);
 
-		chats = g_list_append(chats, conv);
+		chats = g_list_prepend(chats, conv);
 
 		if ((disp = purple_connection_get_display_name(account->gc)))
 			purple_conv_chat_set_nick(conv->u.chat, disp);
@@ -379,7 +410,14 @@
 		}
 	}
 
-	conversations = g_list_append(conversations, conv);
+	conversations = g_list_prepend(conversations, conv);
+
+	hc = g_new(struct _purple_hconv, 1);
+	hc->name = g_strdup(purple_normalize(account, conv->name));
+	hc->account = account;
+	hc->type = type;
+
+	g_hash_table_insert(conversation_cache, hc, conv);
 
 	/* Auto-set the title. */
 	purple_conversation_autoset_title(conv);
@@ -405,6 +443,7 @@
 	PurpleConversationUiOps *ops;
 	PurpleConnection *gc;
 	const char *name;
+	struct _purple_hconv hc;
 
 	g_return_if_fail(conv != NULL);
 
@@ -481,6 +520,12 @@
 	else if(conv->type==PURPLE_CONV_TYPE_CHAT)
 		chats = g_list_remove(chats, conv);
 
+	hc.name = (gchar *)purple_normalize(conv->account, conv->name);
+	hc.account = conv->account;
+	hc.type = conv->type;
+
+	g_hash_table_remove(conversation_cache, &hc);
+
 	purple_signal_emit(purple_conversations_get_handle(),
 					 "deleting-conversation", conv);
 
@@ -711,10 +756,20 @@
 void
 purple_conversation_set_name(PurpleConversation *conv, const char *name)
 {
+	struct _purple_hconv *hc;
 	g_return_if_fail(conv != NULL);
 
+	hc = g_new(struct _purple_hconv, 1);
+	hc->type = conv->type;
+	hc->account = conv->account;
+	hc->name = (gchar *)purple_normalize(conv->account, conv->name);
+
+	g_hash_table_remove(conversation_cache, hc);
 	g_free(conv->name);
+
 	conv->name = g_strdup(name);
+	hc->name = g_strdup(purple_normalize(conv->account, conv->name));
+	g_hash_table_insert(conversation_cache, hc, conv);
 
 	purple_conversation_autoset_title(conv);
 }
@@ -823,43 +878,31 @@
 									const PurpleAccount *account)
 {
 	PurpleConversation *c = NULL;
-	gchar *name1;
-	const gchar *name2;
-	GList *cnv;
+	struct _purple_hconv hc;
 
 	g_return_val_if_fail(name != NULL, NULL);
 
+	hc.name = (gchar *)purple_normalize(account, name);
+	hc.account = account;
+	hc.type = type;
+
 	switch (type) {
 		case PURPLE_CONV_TYPE_IM:
-			cnv = purple_get_ims();
-			break;
 		case PURPLE_CONV_TYPE_CHAT:
-			cnv = purple_get_chats();
+			c = g_hash_table_lookup(conversation_cache, &hc);
 			break;
 		case PURPLE_CONV_TYPE_ANY:
-			cnv = purple_get_conversations();
+			hc.type = PURPLE_CONV_TYPE_IM;
+			c = g_hash_table_lookup(conversation_cache, &hc);
+			if (!c) {
+				hc.type = PURPLE_CONV_TYPE_CHAT;
+				c = g_hash_table_lookup(conversation_cache, &hc);
+			}
 			break;
 		default:
 			g_return_val_if_reached(NULL);
 	}
 
-	name1 = g_strdup(purple_normalize(account, name));
-
-	for (; cnv != NULL; cnv = cnv->next) {
-		c = (PurpleConversation *)cnv->data;
-		name2 = purple_normalize(account, purple_conversation_get_name(c));
-
-		if ((account == purple_conversation_get_account(c)) &&
-				!purple_utf8_strcasecmp(name1, name2)) {
-
-			break;
-		}
-
-		c = NULL;
-	}
-
-	g_free(name1);
-
 	return c;
 }
 
@@ -2229,6 +2272,10 @@
 {
 	void *handle = purple_conversations_get_handle();
 
+	conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash,
+						(GEqualFunc)_purple_conversations_hconv_equal,
+						(GDestroyNotify)_purple_conversations_hconv_free_key, NULL);
+
 	/**********************************************************************
 	 * Register preferences
 	 **********************************************************************/
@@ -2518,6 +2565,7 @@
 {
 	while (conversations)
 		purple_conversation_destroy((PurpleConversation*)conversations->data);
+	g_hash_table_destroy(conversation_cache);
 	purple_signals_unregister_by_instance(purple_conversations_get_handle());
 }
 
--- a/libpurple/privacy.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/privacy.c	Mon Jul 27 15:22:00 2009 +0900
@@ -35,6 +35,7 @@
 	GSList *l;
 	char *name;
 	PurpleBuddy *buddy;
+	PurpleBlistUiOps *blist_ops;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
@@ -62,7 +63,9 @@
 	if (privacy_ops != NULL && privacy_ops->permit_added != NULL)
 		privacy_ops->permit_added(account, who);
 
-	purple_blist_schedule_save();
+	blist_ops = purple_blist_get_ui_ops();
+	if (blist_ops != NULL && blist_ops->save_account != NULL)
+		blist_ops->save_account(account);
 
 	/* This lets the UI know a buddy has had its privacy setting changed */
 	buddy = purple_find_buddy(account, name);
@@ -81,6 +84,7 @@
 	const char *name;
 	PurpleBuddy *buddy;
 	char *del;
+	PurpleBlistUiOps *blist_ops;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
@@ -109,7 +113,9 @@
 	if (privacy_ops != NULL && privacy_ops->permit_removed != NULL)
 		privacy_ops->permit_removed(account, who);
 
-	purple_blist_schedule_save();
+	blist_ops = purple_blist_get_ui_ops();
+	if (blist_ops != NULL && blist_ops->save_account != NULL)
+		blist_ops->save_account(account);
 
 	buddy = purple_find_buddy(account, name);
 	if (buddy != NULL) {
@@ -127,6 +133,7 @@
 	GSList *l;
 	char *name;
 	PurpleBuddy *buddy;
+	PurpleBlistUiOps *blist_ops;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
@@ -154,7 +161,9 @@
 	if (privacy_ops != NULL && privacy_ops->deny_added != NULL)
 		privacy_ops->deny_added(account, who);
 
-	purple_blist_schedule_save();
+	blist_ops = purple_blist_get_ui_ops();
+	if (blist_ops != NULL && blist_ops->save_account != NULL)
+		blist_ops->save_account(account);
 
 	buddy = purple_find_buddy(account, name);
 	if (buddy != NULL) {
@@ -172,6 +181,7 @@
 	const char *normalized;
 	char *name;
 	PurpleBuddy *buddy;
+	PurpleBlistUiOps *blist_ops;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
@@ -205,7 +215,10 @@
 	}
 
 	g_free(name);
-	purple_blist_schedule_save();
+
+	blist_ops = purple_blist_get_ui_ops();
+	if (blist_ops != NULL && blist_ops->save_account != NULL)
+		blist_ops->save_account(account);
 
 	return TRUE;
 }
--- a/libpurple/protocols/jabber/buddy.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/jabber/buddy.c	Mon Jul 27 15:22:00 2009 +0900
@@ -88,6 +88,83 @@
 	return jb;
 }
 
+static gint resource_compare_cb(gconstpointer a, gconstpointer b)
+{
+	const JabberBuddyResource *jbra = a;
+	const JabberBuddyResource *jbrb = b;
+	JabberBuddyState state_a, state_b;
+
+	if (jbra->priority != jbrb->priority)
+		return jbra->priority > jbrb->priority ? 1 : -1;
+
+	/* Fold the states for easier comparison */
+	switch (jbra->state) {
+		case JABBER_BUDDY_STATE_ONLINE:
+		case JABBER_BUDDY_STATE_CHAT:
+			state_a = JABBER_BUDDY_STATE_ONLINE;
+			break;
+		case JABBER_BUDDY_STATE_AWAY:
+		case JABBER_BUDDY_STATE_DND:
+			state_a = JABBER_BUDDY_STATE_AWAY;
+			break;
+		case JABBER_BUDDY_STATE_XA:
+			state_a = JABBER_BUDDY_STATE_XA;
+			break;
+		case JABBER_BUDDY_STATE_UNAVAILABLE:
+			state_a = JABBER_BUDDY_STATE_UNAVAILABLE;
+			break;
+		default:
+			state_a = JABBER_BUDDY_STATE_UNKNOWN;
+			break;
+	}
+
+	switch (jbrb->state) {
+		case JABBER_BUDDY_STATE_ONLINE:
+		case JABBER_BUDDY_STATE_CHAT:
+			state_b = JABBER_BUDDY_STATE_ONLINE;
+			break;
+		case JABBER_BUDDY_STATE_AWAY:
+		case JABBER_BUDDY_STATE_DND:
+			state_b = JABBER_BUDDY_STATE_AWAY;
+			break;
+		case JABBER_BUDDY_STATE_XA:
+			state_b = JABBER_BUDDY_STATE_XA;
+			break;
+		case JABBER_BUDDY_STATE_UNAVAILABLE:
+			state_b = JABBER_BUDDY_STATE_UNAVAILABLE;
+			break;
+		default:
+			state_b = JABBER_BUDDY_STATE_UNKNOWN;
+			break;
+	}
+
+	if (state_a == state_b) {
+		if (jbra->idle == jbrb->idle)
+			return 0;
+		else if ((jbra->idle && !jbrb->idle) ||
+				(jbra->idle && jbrb->idle && jbra->idle < jbrb->idle))
+			return -1;
+		else
+			return 1;
+	}
+
+	if (state_a == JABBER_BUDDY_STATE_ONLINE)
+		return 1;
+	else if (state_a == JABBER_BUDDY_STATE_AWAY &&
+				(state_b == JABBER_BUDDY_STATE_XA ||
+				 state_b == JABBER_BUDDY_STATE_UNAVAILABLE ||
+				 state_b == JABBER_BUDDY_STATE_UNKNOWN))
+		return 1;
+	else if (state_a == JABBER_BUDDY_STATE_XA &&
+				(state_b == JABBER_BUDDY_STATE_UNAVAILABLE ||
+				 state_b == JABBER_BUDDY_STATE_UNKNOWN))
+		return 1;
+	else if (state_a == JABBER_BUDDY_STATE_UNAVAILABLE &&
+				state_b == JABBER_BUDDY_STATE_UNKNOWN)
+		return 1;
+
+	return -1;
+}
 
 JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb,
 		const char *resource)
@@ -104,44 +181,8 @@
 		if (!jbr && !resource) {
 			jbr = tmp;
 		} else if (!resource) {
-			if (tmp->priority > jbr->priority)
+			if (resource_compare_cb(tmp, jbr) > 0)
 				jbr = tmp;
-			else if (tmp->priority == jbr->priority) {
-				/* Determine if this resource is more available than the one we've currently chosen */
-				switch(tmp->state) {
-					case JABBER_BUDDY_STATE_ONLINE:
-					case JABBER_BUDDY_STATE_CHAT:
-						/* This resource is online/chatty. Prefer to one which isn't either. */
-						if (((jbr->state != JABBER_BUDDY_STATE_ONLINE) && (jbr->state != JABBER_BUDDY_STATE_CHAT))
-							|| (jbr->idle && !tmp->idle)
-							|| (jbr->idle && tmp->idle && tmp->idle > jbr->idle))
-							jbr = tmp;
-						break;
-					case JABBER_BUDDY_STATE_AWAY:
-					case JABBER_BUDDY_STATE_DND:
-						/* This resource is away/dnd. Prefer to one which is extended away, unavailable, or unknown. */
-						if (((jbr->state == JABBER_BUDDY_STATE_XA) || (jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) ||
-							(jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
-							|| (jbr->idle && !tmp->idle)
-							|| (jbr->idle && tmp->idle && tmp->idle > jbr->idle))
-							jbr = tmp;
-						break;
-					case JABBER_BUDDY_STATE_XA:
-						/* This resource is extended away. That's better than unavailable or unknown. */
-						if ((jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) || (jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
-							jbr = tmp;
-						break;
-					case JABBER_BUDDY_STATE_UNAVAILABLE:
-						/* This resource is unavailable. That's better than unknown. */
-						if ((jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
-							jbr = tmp;
-						break;
-					case JABBER_BUDDY_STATE_UNKNOWN:
-					case JABBER_BUDDY_STATE_ERROR:
-						/* These are never preferable. */
-						break;
-				}
-			}
 		} else if(tmp->name) {
 			if(!strcmp(tmp->name, resource)) {
 				jbr = tmp;
--- a/libpurple/protocols/jabber/presence.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/jabber/presence.c	Mon Jul 27 15:22:00 2009 +0900
@@ -62,14 +62,16 @@
 void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status)
 {
 	PurpleAccount *account;
+	PurplePresence *presence;
 	const char *username;
 
 	g_return_if_fail(js->user != NULL);
 
 	account = purple_connection_get_account(js->gc);
 	username = purple_connection_get_display_name(js->gc);
+	presence = purple_account_get_presence(account);
 	if (status == NULL)
-		status = purple_account_get_active_status(account);
+		status = purple_presence_get_active_status(presence);
 
 	if (purple_find_buddy(account, username)) {
 		JabberBuddy *jb = jabber_buddy_find(js, username, TRUE);
@@ -86,14 +88,23 @@
 				state == JABBER_BUDDY_STATE_UNKNOWN) {
 			jabber_buddy_remove_resource(jb, js->user->resource);
 		} else {
-			jabber_buddy_track_resource(jb, js->user->resource, priority,
-			                            state, msg);
+			jbr = jabber_buddy_track_resource(jb, js->user->resource, priority,
+					state, msg);
+			jbr->idle = purple_presence_is_idle(presence) ?
+					purple_presence_get_idle_time(presence) : 0;
 		}
 
 		if ((jbr = jabber_buddy_find_resource(jb, NULL))) {
-			purple_prpl_got_user_status(account, username, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL);
+			purple_prpl_got_user_status(account, username,
+					jabber_buddy_state_get_status_id(jbr->state),
+					"priority", jbr->priority,
+					jbr->status ? "message" : NULL, jbr->status,
+					NULL);
+			purple_prpl_got_user_idle(account, username, jbr->idle, jbr->idle);
 		} else {
-			purple_prpl_got_user_status(account, username, "offline", msg ? "message" : NULL, msg, NULL);
+			purple_prpl_got_user_status(account, username, "offline",
+					msg ? "message" : NULL, msg,
+					NULL);
 		}
 		g_free(msg);
 	}
--- a/libpurple/protocols/yahoo/libymsg.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/libymsg.c	Mon Jul 27 15:22:00 2009 +0900
@@ -456,7 +456,7 @@
 	return cookie;
 }
 
-static void yahoo_process_cookie(struct yahoo_data *yd, char *c)
+static void yahoo_process_cookie(YahooData *yd, char *c)
 {
 	if (c[0] == 'Y') {
 		if (yd->cookie_y)
@@ -476,7 +476,7 @@
 	GSList *l = pkt->hash;
 
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	GHashTable *ht;
 	char *norm_bud = NULL;
 	char *temp = NULL;
@@ -607,7 +607,7 @@
 	PurpleGroup *g;
 	YahooFriend *f = NULL;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	GHashTable *ht;
 
 	char **lines;
@@ -754,7 +754,7 @@
 	YahooFriend *f = NULL;
 	GSList *l = pkt->hash;
 	gint val_11 = 0;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	gboolean msn = FALSE;
 
 	account = purple_connection_get_account(gc);
@@ -849,7 +849,7 @@
 	PurpleAccount *account;
 	GSList *l = pkt->hash;
 	struct _yahoo_im *sms = NULL;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	char *server_msg = NULL;
 	char *m;
 
@@ -909,7 +909,7 @@
 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
 {
 	PurpleAccount *account;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	GSList *l = pkt->hash;
 	GSList *list = NULL;
 	struct _yahoo_im *im = NULL;
@@ -1142,7 +1142,7 @@
 {
 	struct yahoo_add_request *add_req = data;
 	struct yahoo_packet *pkt;
-	struct yahoo_data *yd = add_req->gc->proto_data;
+	YahooData *yd = add_req->gc->proto_data;
 	const char *who = add_req->who;
 
 	if (add_req->protocol == 2)
@@ -1165,7 +1165,7 @@
 static void
 yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg)
 {
-	struct yahoo_data *yd = add_req->gc->proto_data;
+	YahooData *yd = add_req->gc->proto_data;
 	struct yahoo_packet *pkt;
 	char *encoded_msg = NULL;
 	const char *who = add_req->who;
@@ -1217,7 +1217,7 @@
 static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
 {
 	char *notify_msg;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	if (who == NULL)
 		return;
@@ -1530,7 +1530,7 @@
 static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	const char *who = NULL;
 	const char *email = NULL;
 	const char *subj = NULL;
@@ -1614,7 +1614,7 @@
 
 static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	PurpleAccount *account = purple_connection_get_account(gc);
 	const char *name = purple_normalize(account, purple_account_get_username(account));
 	PurpleCipher *md5_cipher;
@@ -1657,7 +1657,7 @@
 {
 	struct yahoo_auth_data *auth_data = user_data;
 	PurpleConnection *gc = auth_data->gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	gboolean try_login_on_error = FALSE;
 
 	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage2\n");
@@ -1668,7 +1668,7 @@
 		g_return_if_reached();
 	}
 
-	yd = (struct yahoo_data *)gc->proto_data;
+	yd = (YahooData *)gc->proto_data;
 
 	if (error_message != NULL) {
 		purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message);
@@ -2032,7 +2032,7 @@
 static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 #ifdef TRY_WEBMESSENGER_LOGIN
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 #endif /* TRY_WEBMESSENGER_LOGIN */
 	GSList *l = pkt->hash;
 	int err = 0;
@@ -2116,7 +2116,7 @@
 	char *buf;
 	YahooFriend *f;
 	GSList *l = pkt->hash;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	int protocol = 0;
 	gboolean msn = FALSE;
 
@@ -2203,7 +2203,7 @@
 	PurpleConnection *gc = user_data;
 	struct yahoo_packet *pkt_to_send;
 	PurpleAccount *account;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	account = purple_connection_get_account(gc);
 
@@ -2222,7 +2222,7 @@
 static gboolean yahoo_p2p_keepalive(gpointer data)
 {
 	PurpleConnection *gc = data;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc);
 
@@ -2263,7 +2263,7 @@
 	struct yahoo_packet *pkt_to_send;
 	PurpleAccount *account;
 	int val_13_to_send = 0;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	YahooFriend *f;
 
 	if(!(p2p_data = data))
@@ -2350,7 +2350,7 @@
 	struct yahoo_packet *pkt;
 	guchar *start = NULL;
 	struct yahoo_p2p_data *p2p_data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	if(!(p2p_data = data))
 		return ;
@@ -2422,7 +2422,7 @@
 {
 	int acceptfd;
 	struct yahoo_p2p_data *p2p_data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	if(!(p2p_data = data))
 		return ;
@@ -2461,7 +2461,7 @@
 static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data)
 {
 	struct yahoo_p2p_data *p2p_data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	if(!(p2p_data = data))
 		return FALSE;
@@ -2482,7 +2482,7 @@
 static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data)
 {
 	struct yahoo_p2p_data *p2p_data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	if(!(p2p_data = data))
 		return ;
@@ -2514,7 +2514,7 @@
 	YahooFriend *f;
 	struct yahoo_packet *pkt;
 	PurpleAccount *account;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_p2p_data *p2p_data;
 
 	f = yahoo_friend_find(gc, who);
@@ -2582,7 +2582,7 @@
 	struct yahoo_p2p_data *p2p_data;
 	struct yahoo_packet *pkt_to_send;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	if(!(p2p_data = data))
 		return ;
@@ -2928,7 +2928,7 @@
 static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = data;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	char buf[1024];
 	int len;
 
@@ -3025,7 +3025,7 @@
 static void yahoo_got_connected(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleConnection *gc = data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_packet *pkt;
 
 	if (source < 0) {
@@ -3051,7 +3051,7 @@
 static void yahoo_got_web_connected(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleConnection *gc = data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_packet *pkt;
 
 	if (source < 0) {
@@ -3081,7 +3081,7 @@
 {
 	PurpleConnection *gc = data;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	char bufread[2048], *i = bufread, *buf = bufread;
 	int len;
 	GString *s;
@@ -3156,7 +3156,7 @@
 static void yahoo_got_cookies_send_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleConnection *gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	int written, remaining;
 
 	gc = data;
@@ -3270,7 +3270,7 @@
 {
 	PurpleConnection *gc = (PurpleConnection *)user_data;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	const char *sn = purple_account_get_username(account);
 	const char *pass = purple_connection_get_password(gc);
 	GHashTable *hash = yahoo_login_page_hash(url_text, len);
@@ -3411,7 +3411,7 @@
 
 void yahoo_login(PurpleAccount *account) {
 	PurpleConnection *gc = purple_account_get_connection(account);
-	struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1);
+	YahooData *yd = gc->proto_data = g_new0(YahooData, 1);
 	PurpleStatus *status = purple_account_get_active_status(account);
 	const char *server = NULL;
 	int pager_port = 0;
@@ -3458,7 +3458,7 @@
 }
 
 void yahoo_close(PurpleConnection *gc) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	YahooData *yd = (YahooData *)gc->proto_data;
 	GSList *l;
 
 	if (gc->inpa)
@@ -3556,7 +3556,7 @@
 {
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	YahooFriend *f;
 	PurplePresence *presence;
 
@@ -3619,7 +3619,7 @@
 	PurpleConnection *gc;
 
 	GHashTable *components;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	int id;
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
@@ -3656,7 +3656,7 @@
 	PurpleBuddy *buddy;
 	PurpleConnection *gc;
 
-	struct yahoo_data *yd;
+	YahooData *yd;
 	const char *game;
 	char *game2;
 	char *t;
@@ -3667,7 +3667,7 @@
 
 	buddy = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	yd = (struct yahoo_data *) gc->proto_data;
+	yd = (YahooData *) gc->proto_data;
 
 	f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
 	if (!f)
@@ -3824,7 +3824,7 @@
 static GList *build_presence_submenu(YahooFriend *f, PurpleConnection *gc) {
 	GList *m = NULL;
 	PurpleMenuAction *act;
-	struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
+	YahooData *yd = (YahooData *) gc->proto_data;
 
 	if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
 		if (f->presence != YAHOO_PRESENCE_ONLINE) {
@@ -3884,7 +3884,7 @@
 	PurpleMenuAction *act;
 
 	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	static char buf2[1024];
 	YahooFriend *f;
 
@@ -3965,7 +3965,7 @@
 
 static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	const char *name = yd->profiles[purple_request_fields_get_choice(fields, "id")];
 
 	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -3982,7 +3982,7 @@
 	PurpleConnection *gc = user_data;
 	gboolean set_cookie = FALSE;
 	gchar *url;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
@@ -4018,7 +4018,7 @@
 	/* XXX I have no idea how this will work with Yahoo! Japan. */
 
 	PurpleConnection *gc = action->context;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	PurpleUtilFetchUrlData *url_data;
 	const char* base_url = "http://login.yahoo.com";
@@ -4062,7 +4062,7 @@
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
 	PurpleConnection *gc = (PurpleConnection *) action->context;
-	struct yahoo_data *yd = purple_connection_get_protocol_data(gc);
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	const char *name = purple_connection_get_display_name(gc);
 	int iter;
 
@@ -4132,7 +4132,7 @@
 {
 	struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data;
 	PurpleConnection *gc = sms_cb_data->gc;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	char *mobile_no = NULL;
 	char *status = NULL;
 	char *carrier = NULL;
@@ -4183,7 +4183,7 @@
 
 static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	PurpleUtilFetchUrlData *url_data;
 	struct yahoo_sms_carrier_cb_data *sms_cb_data;
 	char *validate_request_str = NULL;
@@ -4241,7 +4241,7 @@
 
 int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt = NULL;
 	char *msg = yahoo_html_to_codes(what);
 	char *msg2;
@@ -4392,7 +4392,7 @@
 
 unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_p2p_data *p2p_data;
 	gboolean msn = !g_strncasecmp(who, "msn/", 4);
 	struct yahoo_packet *pkt = NULL;
@@ -4437,7 +4437,7 @@
 {
 	PurpleConnection *gc;
 	PurplePresence *presence;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_packet *pkt;
 	int old_status;
 	const char *msg = NULL;
@@ -4450,7 +4450,7 @@
 
 	gc = purple_account_get_connection(account);
 	presence = purple_status_get_presence(status);
-	yd = (struct yahoo_data *)gc->proto_data;
+	yd = (YahooData *)gc->proto_data;
 	old_status = yd->current_status;
 
 	yd->current_status = get_yahoo_status_from_purple_status(status);
@@ -4512,7 +4512,7 @@
 
 void yahoo_set_idle(PurpleConnection *gc, int idle)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt = NULL;
 	char *msg = NULL, *msg2 = NULL;
 	PurpleStatus *status = NULL;
@@ -4619,7 +4619,7 @@
 void yahoo_keepalive(PurpleConnection *gc)
 {
 	struct yahoo_packet *pkt;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	time_t now = time(NULL);
 
 	/* We're only allowed to send a ping once an hour or the servers will boot us */
@@ -4652,7 +4652,7 @@
 
 void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
 {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	YahooData *yd = (YahooData *)gc->proto_data;
 	struct yahoo_packet *pkt;
 	const char *group = NULL;
 	char *group2;
@@ -4716,7 +4716,7 @@
 
 void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	YahooData *yd = (YahooData *)gc->proto_data;
 	struct yahoo_packet *pkt;
 	GSList *buddies, *l;
 	PurpleGroup *g;
@@ -4764,7 +4764,7 @@
 }
 
 void yahoo_add_deny(PurpleConnection *gc, const char *who) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	YahooData *yd = (YahooData *)gc->proto_data;
 	struct yahoo_packet *pkt;
 
 	if (!yd->logged_in)
@@ -4780,7 +4780,7 @@
 }
 
 void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
-	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	YahooData *yd = (YahooData *)gc->proto_data;
 	struct yahoo_packet *pkt;
 
 	if (!yd->logged_in)
@@ -4821,7 +4821,7 @@
 void yahoo_change_buddys_group(PurpleConnection *gc, const char *who,
 				   const char *old_group, const char *new_group)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	char *gpn, *gpo;
 	YahooFriend *f = yahoo_friend_find(gc, who);
@@ -4870,7 +4870,7 @@
 void yahoo_rename_group(PurpleConnection *gc, const char *old_name,
 							   PurpleGroup *group, GList *moved_buddies)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	char *gpn, *gpo;
 
@@ -4910,7 +4910,7 @@
 {
 	GHashTable *comp;
 	PurpleConnection *gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	int id;
 
 	if (!args || !args[0])
--- a/libpurple/protocols/yahoo/libymsg.h	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/libymsg.h	Mon Jul 27 15:22:00 2009 +0900
@@ -167,7 +167,7 @@
 	} phone;
 } YahooPersonalDetails;
 
-struct yahoo_data {
+typedef struct {
 	PurpleConnection *gc;
 	int fd;
 	guchar *rxqueue;
@@ -239,7 +239,7 @@
 	int yahoo_p2p_server_watcher;
 	GHashTable *sms_carrier;	/* sms carrier data */
 	guint yahoo_p2p_server_timeout_handle;
-};
+} YahooData;
 
 #define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
 
--- a/libpurple/protocols/yahoo/util.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/util.c	Mon Jul 27 15:22:00 2009 +0900
@@ -54,7 +54,7 @@
 	gchar *t1,*t2,*t3;
 	GSList *tmp;
 	GSList *cookies;
-	cookies = ((struct yahoo_data*)(gc->proto_data))->cookies;
+	cookies = ((YahooData*)(gc->proto_data))->cookies;
 	tmp = cookies;
 	while(tmp)
 	{
@@ -119,7 +119,7 @@
  */
 char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	char *ret = NULL;
 	gsize newlen;
 	const char *to_codeset;
@@ -147,7 +147,7 @@
  */
 char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	char *ret, *tmp;
 	const char *from_codeset;
 	gsize newlen;
--- a/libpurple/protocols/yahoo/yahoo_aliases.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_aliases.c	Mon Jul 27 15:22:00 2009 +0900
@@ -37,9 +37,9 @@
 #include "yahoo_packet.h"
 
 /* I hate hardcoding this stuff, but Yahoo never sends us anything to use.  Someone in the know may be able to tweak this URL */
-#define YAHOO_ALIAS_FETCH_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252"
+#define YAHOO_ALIAS_FETCH_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOO_CLIENT_VERSION "&useutf8=1&legenc=codepage-1252"
 #define YAHOO_ALIAS_UPDATE_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"
-#define YAHOOJP_ALIAS_FETCH_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&diffs=1&t=0&tags=short&rt=0&prog-ver=7.0.0.7"
+#define YAHOOJP_ALIAS_FETCH_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOOJP_CLIENT_VERSION
 #define YAHOOJP_ALIAS_UPDATE_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&sync=1&tags=short&noclear=1"
 
 void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
@@ -74,7 +74,7 @@
 yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
 {
 	PurpleConnection *gc = user_data;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
@@ -186,7 +186,7 @@
 void
 yahoo_fetch_aliases(PurpleConnection *gc)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	const char *url;
 	gchar *request, *webpage, *webaddress;
 	PurpleUtilFetchUrlData *url_data;
@@ -228,7 +228,7 @@
 	xmlnode *node, *result;
 	struct callback_data *cb = user_data;
 	PurpleConnection *gc = cb->gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	yd = gc->proto_data;
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
@@ -289,7 +289,7 @@
 void
 yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	const char *url;
 	gchar *content, *request, *webpage, *webaddress;
 	struct callback_data *cb;
@@ -403,7 +403,7 @@
  * which is stupid, and thus not really surprising. */
 
 struct yahoo_userinfo {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	char *xml;
 };
 
@@ -452,7 +452,7 @@
 {
 	xmlnode *node = xmlnode_new("ab");
 	xmlnode *ct = xmlnode_new_child(node, "ct");
-	struct yahoo_data *yd = purple_connection_get_protocol_data(gc);
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account;
 	PurpleUtilFetchUrlData *url_data;
 	char *webaddress, *webpage;
@@ -592,7 +592,7 @@
 
 void yahoo_set_userinfo(PurpleConnection *gc)
 {
-	struct yahoo_data *yd = purple_connection_get_protocol_data(gc);
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleRequestFields *fields = request_fields_from_personal_details(&yd->ypd,
 					purple_connection_get_display_name(gc));
 	purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
@@ -602,7 +602,7 @@
 }
 
 static gboolean
-parse_contact_details(struct yahoo_data *yd, const char *who, const char *xml)
+parse_contact_details(YahooData *yd, const char *who, const char *xml)
 {
 	xmlnode *node, *nd;
 	YahooFriend *f;
@@ -690,7 +690,7 @@
 {
 	GSList *l = pkt->hash;
 	const char *who = NULL, *xml = NULL;
-	struct yahoo_data *yd = purple_connection_get_protocol_data(gc);
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	for (; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_doodle.c	Mon Jul 27 15:22:00 2009 +0900
@@ -384,7 +384,7 @@
 											  const char *imv,
 											  const char *sixtyfour)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_packet *pkt;
 
 	purple_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to);
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Mon Jul 27 15:22:00 2009 +0900
@@ -80,7 +80,7 @@
 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
 {
 	PurpleConnection *gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	PurpleXfer *xfer;
 	GSList *l;
 
@@ -233,7 +233,7 @@
 	size_t content_length, header_len, pkt_buf_len;
 	PurpleConnection *gc;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	gsize dummy;
 
 	purple_debug_info("yahoo", "in yahoo_sendfile_connected\n");
@@ -316,7 +316,7 @@
 	struct yahoo_xfer_data *xfer_data;
 	PurpleConnection *gc;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	xfer_data = xfer->data;
 	gc = xfer_data->gc;
@@ -359,7 +359,7 @@
 	struct yahoo_xfer_data *xfer_data;
 	PurpleConnection *gc;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_packet *pkt;
 
 	xfer_data = xfer->data;
@@ -530,7 +530,7 @@
 	{
 		PurpleConnection *gc;
 		PurpleAccount *account;
-		struct yahoo_data *yd;
+		YahooData *yd;
 		struct yahoo_packet *pkt;
 
 		gc = xfer_data->gc;
@@ -578,7 +578,7 @@
 
 		PurpleConnection *gc;
 		PurpleAccount *account;
-		struct yahoo_data *yd;
+		YahooData *yd;
 		struct yahoo_packet *pkt;
 
 		gc = xfer_data->gc;
@@ -639,7 +639,7 @@
 	struct yahoo_xfer_data *xfer_data;
 	PurpleXfer *xfer = NULL;
 	PurpleConnection *gc;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	xfer_data = xfer_old->data;
 	if(xfer_data && xfer_data->version == 15
@@ -807,7 +807,7 @@
 	char *imv = NULL;
 	long expires = 0;
 	PurpleXfer *xfer;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_xfer_data *xfer_data;
 	char *service = NULL;
 	char *filename = NULL;
@@ -990,7 +990,7 @@
 	unsigned long a,b,c,d;
 	PurpleConnection *gc;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	gchar *url;
 	gchar *filename;
 
@@ -1073,7 +1073,7 @@
 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
 {
 	struct yahoo_xfer_data *xfer_data;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	PurpleXfer *xfer = yahoo_new_xfer(gc, who);
 
 	g_return_if_fail(xfer != NULL);
@@ -1231,7 +1231,7 @@
 	PurpleXfer *xfer;
 	struct yahoo_xfer_data *xd;
 	PurpleAccount *account;
-	struct yahoo_data* yd;
+	YahooData* yd;
 
 	if (!(xfer = data))
 		return;
@@ -1484,7 +1484,7 @@
 	struct yahoo_xfer_data *xd;
 	struct yahoo_packet *pkt;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	gchar *filename;
 	const char *local_ip;
 	gchar *url_to_send = NULL;
@@ -1551,7 +1551,7 @@
 	struct yahoo_xfer_data *xd;
 	struct yahoo_packet *pkt;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	gchar *filename;
 	struct yahoo_p2p_data *p2p_data;
 
@@ -1588,7 +1588,7 @@
 	char *imv = NULL;
 	long val_222 = 0L;
 	PurpleXfer *xfer;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_xfer_data *xfer_data;
 	char *service = NULL;
 	char *filename = NULL;
@@ -1765,7 +1765,7 @@
 	long val_249 = 0;
 	long val_66 = 0;
 	PurpleXfer *xfer;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_xfer_data *xfer_data;
 	char *filename = NULL;
 	char *xfer_peer_idstring = NULL;
@@ -1872,7 +1872,7 @@
 	gchar *xfer_peer_idstring = NULL;
 	gchar *xfer_idstring_for_relay = NULL;
 	PurpleXfer *xfer;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_xfer_data *xfer_data;
 	GSList *l;
 	PurpleAccount *account;
--- a/libpurple/protocols/yahoo/yahoo_friend.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_friend.c	Mon Jul 27 15:22:00 2009 +0900
@@ -42,7 +42,7 @@
 
 YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	const char *norm;
 
 	g_return_val_if_fail(gc != NULL, NULL);
@@ -57,7 +57,7 @@
 YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name)
 {
 	YahooFriend *f;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	const char *norm;
 
 	g_return_val_if_fail(gc != NULL, NULL);
@@ -215,7 +215,7 @@
 void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
 		YahooPresenceVisibility presence)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt = NULL;
 	YahooFriend *f;
 	const char *thirtyone, *thirteen;
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Mon Jul 27 15:22:00 2009 +0900
@@ -288,7 +288,7 @@
 static void
 yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition cond)
 {
-	struct yahoo_data *yd = data;
+	YahooData *yd = data;
 	int ret, writelen;
 
 	writelen = purple_circ_buffer_get_max_read(yd->txbuf);
@@ -345,7 +345,7 @@
 	return len;
 }
 
-int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd)
+int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd)
 {
 	size_t len;
 	gssize ret;
@@ -385,7 +385,7 @@
 	return ret;
 }
 
-int yahoo_packet_send_and_free(struct yahoo_packet *pkt, struct yahoo_data *yd)
+int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd)
 {
 	int ret;
 
--- a/libpurple/protocols/yahoo/yahoo_packet.h	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_packet.h	Mon Jul 27 15:22:00 2009 +0900
@@ -137,8 +137,8 @@
 void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...);
 void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value);
 void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value);
-int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd);
-int yahoo_packet_send_and_free(struct yahoo_packet *pkt, struct yahoo_data *yd);
+int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd);
+int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd);
 size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm, gboolean jp,
 guchar **buf);
 void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len);
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_picture.c	Mon Jul 27 15:22:00 2009 +0900
@@ -49,7 +49,7 @@
 		const gchar *pic_data, size_t len, const gchar *error_message)
 {
 	struct yahoo_fetch_picture_data *d;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	d = user_data;
 	yd = d->gc->proto_data;
@@ -71,7 +71,7 @@
 
 void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	GSList *l = pkt->hash;
 	char *who = NULL, *us = NULL;
 	gboolean got_icon_info = FALSE, send_icon_info = FALSE;
@@ -192,7 +192,7 @@
 void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	GSList *l = pkt->hash;
 	char *url = NULL;
 
@@ -268,7 +268,7 @@
 
 void yahoo_send_picture_info(PurpleConnection *gc, const char *who)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 
 	if (!yd->picture_url) {
@@ -285,7 +285,7 @@
 
 void yahoo_send_picture_request(PurpleConnection *gc, const char *who)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -297,7 +297,7 @@
 
 void yahoo_send_picture_checksum(PurpleConnection *gc)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -308,7 +308,7 @@
 
 void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_AVATAR_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -333,7 +333,7 @@
 
 void yahoo_send_picture_update(PurpleConnection *gc, int type)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yspufe data;
 
 	data.gc = gc;
@@ -427,7 +427,7 @@
 	gsize pkt_buf_len;
 	PurpleConnection *gc = d->gc;
 	PurpleAccount *account;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	/* use whole URL if using HTTP Proxy */
 	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
 
@@ -461,7 +461,7 @@
 
 	/* header + packet + "29" + 0xc0 + 0x80) + pictureblob */
 
-	host = purple_account_get_string(account, "xfer_host", YAHOO_XFER_HOST);
+	host = purple_account_get_string(account, "xfer_host", yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST);
 	port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
 	tmp = g_strdup_printf("%s:%d", host, port);
 	header = g_strdup_printf("POST %s%s/notifyft HTTP/1.1\r\n"
@@ -497,7 +497,7 @@
 void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	if (yd->buddy_icon_connect_data != NULL) {
 		/* Cancel any in-progress buddy icon upload */
@@ -506,8 +506,8 @@
 	}
 
 	yd->buddy_icon_connect_data = purple_proxy_connect(NULL, account,
-			yd->jp ? purple_account_get_string(account, "xferjp_host",  YAHOOJP_XFER_HOST)
-			       : purple_account_get_string(account, "xfer_host",  YAHOO_XFER_HOST),
+			purple_account_get_string(account, "xfer_host",
+				yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST),
 			purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
 			yahoo_buddy_icon_upload_connected, d);
 
@@ -542,7 +542,7 @@
 
 void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	PurpleAccount *account = gc->account;
 
 	if (img == NULL) {
--- a/libpurple/protocols/yahoo/yahoo_profile.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoo_profile.c	Mon Jul 27 15:22:00 2009 +0900
@@ -788,7 +788,7 @@
 	char *tmp;
 	char *profile_url_text = NULL;
 	int lang, strid;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	const profile_strings_node_t *strings = NULL;
 	const char *title;
 	profile_state_t profile_state = PROFILE_STATE_DEFAULT;
@@ -960,7 +960,7 @@
 		const gchar *url_text, size_t len, const gchar *error_message)
 {
 	YahooGetInfoStepTwoData *info2_data = (YahooGetInfoStepTwoData *)data;
-	struct yahoo_data *yd;
+	YahooData *yd;
 	gboolean found = FALSE;
 	int id = -1;
 
@@ -1273,7 +1273,7 @@
 
 void yahoo_get_info(PurpleConnection *gc, const char *name)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	YahooGetInfoData *data;
 	char *url;
 	PurpleUtilFetchUrlData *url_data;
--- a/libpurple/protocols/yahoo/yahoochat.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoochat.c	Mon Jul 27 15:22:00 2009 +0900
@@ -53,7 +53,7 @@
 /* special function to log us on to the yahoo chat service */
 static void yahoo_chat_online(PurpleConnection *gc)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	const char *rll;
 
@@ -98,7 +98,7 @@
 
 static PurpleConversation *yahoo_find_conference(PurpleConnection *gc, const char *name)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	GSList *l;
 
 	yd = gc->proto_data;
@@ -373,7 +373,7 @@
 
 static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	char *room2;
 	gboolean utf8 = TRUE;
@@ -401,7 +401,7 @@
 /* this is a confirmation of yahoo_chat_online(); */
 void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
-	struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
+	YahooData *yd = (YahooData *) gc->proto_data;
 
 	if (pkt->status == 1) {
 		yd->chat_online = TRUE;
@@ -433,7 +433,7 @@
 /* this is basicly the opposite of chat_online */
 void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
-	struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
+	YahooData *yd = (YahooData *) gc->proto_data;
 	GSList *l;
 
 	for (l = pkt->hash; l; l = l->next) {
@@ -463,7 +463,7 @@
 void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
+	YahooData *yd = (YahooData *) gc->proto_data;
 	PurpleConversation *c = NULL;
 	GSList *l;
 	GList *members = NULL;
@@ -618,7 +618,7 @@
 	char *who = NULL;
 	char *room = NULL;
 	GSList *l;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
 	yd = gc->proto_data;
 
@@ -769,7 +769,7 @@
  * I think conference names are always ascii.
  */
 
-void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who)
+void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who)
 {
 	struct yahoo_packet *pkt;
 	GList *w;
@@ -791,7 +791,7 @@
 static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
 							GList *members, const char *what)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	GList *who;
 	char *msg, *msg2;
@@ -818,7 +818,7 @@
 	return 0;
 }
 
-static void yahoo_conf_join(struct yahoo_data *yd, PurpleConversation *c, const char *dn, const char *room,
+static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn, const char *room,
 						const char *topic, const char *members)
 {
 	struct yahoo_packet *pkt;
@@ -848,7 +848,7 @@
 static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c,
 		const char *dn, const char *buddy, const char *room, const char *msg)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	GList *members;
 	char *msg2 = NULL;
@@ -878,7 +878,7 @@
 
 static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	PurpleConversation *c;
 
@@ -930,7 +930,7 @@
 
 static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	int me = 0;
 	char *msg1, *msg2, *room2;
@@ -975,7 +975,7 @@
 static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy,
 							const char *room, const char *msg)
 {
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
 	char *room2, *msg2 = NULL;
 	gboolean utf8 = TRUE;
@@ -1000,7 +1000,7 @@
 
 void yahoo_chat_goto(PurpleConnection *gc, const char *name)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	struct yahoo_packet *pkt;
 
 	yd = gc->proto_data;
@@ -1035,7 +1035,7 @@
 
 void yahoo_c_leave(PurpleConnection *gc, int id)
 {
-	struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
+	YahooData *yd = (YahooData *) gc->proto_data;
 	PurpleConversation *c;
 
 	if (!yd)
@@ -1060,9 +1060,9 @@
 {
 	PurpleConversation *c;
 	int ret;
-	struct yahoo_data *yd;
+	YahooData *yd;
 
-	yd = (struct yahoo_data *) gc->proto_data;
+	yd = (YahooData *) gc->proto_data;
 	if (!yd)
 		return -1;
 
@@ -1116,11 +1116,11 @@
 
 void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
 {
-	struct yahoo_data *yd;
+	YahooData *yd;
 	char *room, *topic, *type;
 	PurpleConversation *c;
 
-	yd = (struct yahoo_data *) gc->proto_data;
+	yd = (YahooData *) gc->proto_data;
 	if (!yd)
 		return;
 
@@ -1480,7 +1480,7 @@
 {
 	struct yahoo_roomlist *yrl = data;
 	PurpleRoomlist *list = yrl->list;
-	struct yahoo_data *yd = purple_account_get_connection(list->account)->proto_data;
+	YahooData *yd = purple_account_get_connection(list->account)->proto_data;
 
 	if (source < 0) {
 		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
--- a/libpurple/protocols/yahoo/yahoochat.h	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/yahoochat.h	Mon Jul 27 15:22:00 2009 +0900
@@ -50,7 +50,7 @@
 char *yahoo_get_chat_name(GHashTable *data);
 void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
 
-void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who);
+void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who);
 
 void yahoo_chat_goto(PurpleConnection *gc, const char *name);
 
--- a/libpurple/protocols/yahoo/ycht.c	Mon Jul 27 01:08:46 2009 +0900
+++ b/libpurple/protocols/yahoo/ycht.c	Mon Jul 27 15:22:00 2009 +0900
@@ -55,7 +55,7 @@
 static void ycht_process_login(YchtConn *ycht, YchtPkt *pkt)
 {
 	PurpleConnection *gc = ycht->gc;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	if (ycht->logged_in)
 		return;
@@ -70,7 +70,7 @@
 static void ycht_process_logout(YchtConn *ycht, YchtPkt *pkt)
 {
 	PurpleConnection *gc = ycht->gc;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	yd->chat_online = FALSE;
 	ycht->logged_in = FALSE;
@@ -175,7 +175,7 @@
 {
 #if 0
 	PurpleConnection *gc = ycht->gc;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 
 	if (ycht->logged_in)
 		return;
@@ -431,7 +431,7 @@
 
 void ycht_connection_close(YchtConn *ycht)
 {
-	struct yahoo_data *yd = ycht->gc->proto_data;
+	YahooData *yd = ycht->gc->proto_data;
 
 	if (yd) {
 		yd->ycht = NULL;
@@ -543,7 +543,7 @@
 {
 	YchtConn *ycht = data;
 	PurpleConnection *gc = ycht->gc;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	YchtPkt *pkt;
 	char *buf;
 
@@ -570,7 +570,7 @@
 void ycht_connection_open(PurpleConnection *gc)
 {
 	YchtConn *ycht;
-	struct yahoo_data *yd = gc->proto_data;
+	YahooData *yd = gc->proto_data;
 	PurpleAccount *account = purple_connection_get_account(gc);
 
 	ycht = g_new0(YchtConn, 1);
Binary file pidgin/pixmaps/status/11/invisible.png has changed
Binary file pidgin/pixmaps/status/16/invisible.png has changed
Binary file pidgin/pixmaps/status/16/offline.png has changed
Binary file pidgin/pixmaps/status/22/invisible.png has changed
Binary file pidgin/pixmaps/status/22/offline.png has changed
Binary file pidgin/pixmaps/status/32/invisible.png has changed
Binary file pidgin/pixmaps/status/32/offline.png has changed
Binary file pidgin/pixmaps/status/48/invisible.png has changed
Binary file pidgin/pixmaps/status/48/offline.png has changed