changeset 32696:763d65f3f758

explicit merge of '6ab9f5ff810acde3c06a2add7b8df2bd75cce6e3' and '7a0bb807afc9c1c3f2aaa7143fc5d1e3dc7c6ee8' to branch 'im.pidgin.cpw.qulogic.gtk3'
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Fri, 23 Dec 2011 06:58:52 +0000
parents 466efc330d3d (diff) 391a75e48641 (current diff)
children 48d35c0c6224
files pidgin/gtkblist.c pidgin/gtkconv.c pidgin/gtkconvwin.h pidgin/gtkdialogs.c pidgin/gtkdocklet.c pidgin/gtkimhtml.c pidgin/gtkimhtmltoolbar.c pidgin/gtkimhtmltoolbar.h pidgin/gtkmedia.c pidgin/gtknotify.c pidgin/gtkpounce.c pidgin/gtkprefs.c pidgin/gtkutils.c pidgin/plugins/adiumthemes/Makefile.am pidgin/plugins/adiumthemes/Template.html pidgin/plugins/adiumthemes/message-style.c pidgin/plugins/adiumthemes/message-style.h pidgin/plugins/adiumthemes/webkit.c pidgin/plugins/vvconfig.c pidgin/plugins/xmppconsole.c
diffstat 178 files changed, 3276 insertions(+), 3568 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sun Oct 09 07:10:36 2011 +0000
+++ b/COPYRIGHT	Fri Dec 23 06:58:52 2011 +0000
@@ -107,6 +107,7 @@
 Ka-Hing Cheung
 Sadrul Habib Chowdhury
 Brian Chu
+Howard Chu
 Arturo Cisneros, Jr.
 Vincas Ciziunas
 Jonathan Clark
@@ -428,6 +429,7 @@
 David Reiss
 Luoh Ren-Shan
 Noa Resare
+Tim Retout
 Daniele Ricci
 Kristian Rietveld
 Pekka Riikonen
--- a/ChangeLog	Sun Oct 09 07:10:36 2011 +0000
+++ b/ChangeLog	Fri Dec 23 06:58:52 2011 +0000
@@ -1,11 +1,32 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 3.0.0 (??/??/????):
+	libpurple:
+	* Support new connection states and signals for NetworkManager 0.9+.
+	  (Dan Williams) (#13859)
+
 	AIM and ICQ:
 	* Make buddy list management code more efficient. (Oliver) (#4816)
 	* Don't try to format ICQ usernames entered as email addresses.
 	  Gets rid of an "Unable to format username" error at login. (#13883)
 
+	Bonjour:
+	* Support file transfers up to ~9 EiB.
+
+	Gadu-Gadu:
+	* Possibility to require encryption. Also, using encryption when
+	  available is default option now. (Tomasz Wasilczyk)
+	* Show local time for incoming messages. (Tomasz Wasilczyk) (#4579)
+	* Fixed password change dialog and problems with connecting to accounts
+	  with non-ASCII passwords. (Tomasz Wasilczyk) (#14652)
+	* Option to show links from strangers. (Tomasz Wasilczyk) (#10591)
+	* Better handling of "invisible" and "chatty" statuses. (Tomasz
+	  Wasilczyk) (#13836)
+
+	MSN:
+	* Fix file transfer with older Mac MSN clients.
+	* Support file transfers up to ~9 EiB.
+
 	MXit:
 	* Remove all reference to Hidden Number.
 	* Fix decoding of font-size changes in the markup of received messages.
@@ -18,13 +39,51 @@
 	* Strip element prefixes from XHTML-IM messages as they're presented
 	  to the core (and UIs) as incoming messages (Thijs Alkemade).
 	  (#14529)
-
-version 2.10.1 (??/??/????):
+	* Support file transfers up to ~9 EiB.
+
+	Plugins:
+	* The Voice/Video Settings plugin supports using the sndio GStreamer
+	 backends. (Brad Smith) (#14414)
+
+version 2.10.1 (12/06/2011):
+	Finch:
+	* Fix compilation on OpenBSD.
+
+	AIM and ICQ:
+	* Fix remotely-triggerable crashes by validating strings in a few
+	  messages related to buddy list management.  Thanks to Evgeny Boger
+	  for reporting this!  (#14682)
+
+	Bonjour:
+	* IPv6 fixes (Linus Lüssing)
+
+	Gadu-Gadu:
+	* Fix problems linking against GnuTLS. (#14544)
+
+	IRC:
+	* Fix a memory leak when admitting UTF-8 text with a non-UTF-8 primary
+	  encoding.  (#14700)
+
+	Jabber:
+	* Fix crashes and memory leaks when receiving malformed voice
+	  and video requests.  Thanks to Thijs Alkemade for reporting this!
+
+	Sametime:
+	* Separate "username" and "server" when adding new Sametime accounts.
+	  (#14608)
+	* Fix compilation in Visual C++. (#14608)
+
 	SILC:
 	* Fix CVE-2011-3594, by UTF-8 validating incoming messages before
 	  passing them to glib or libpurple.  Identified by Diego Bauche
 	  Madero from IOActive.  (#14636)
 
+	Yahoo!:
+	* Fetch buddy icons in some cases where we previously weren't. (#13050)
+
+	Windows-Specific Changes:
+	* Fix compilation
+
 version 2.10.0 (08/18/2011):
 	Pidgin:
 	* Make the max size of incoming smileys a pref instead of hardcoding it.
--- a/ChangeLog.API	Sun Oct 09 07:10:36 2011 +0000
+++ b/ChangeLog.API	Fri Dec 23 06:58:52 2011 +0000
@@ -4,15 +4,24 @@
 	libpurple:
 		Added:
 		* pidgin_create_webview
+		* purple_account_is_disconnecting
 		* purple_account_get_ui_data
 		* purple_account_set_ui_data
+		* purple_account_register_completed
 		* purple_conv_chat_cb_get_alias
 		* purple_conv_chat_cb_get_flags
 		* purple_conv_chat_cb_is_buddy
 		* purple_conv_chat_cb_get_ui_data
 		* purple_conv_chat_cb_set_ui_data
+		* purple_connection_get_flags
+		* purple_connection_set_flags
+		* purple_connection_update_last_received
 		* purple_conversation_get_ui_data
 		* purple_conversation_set_ui_data
+		* purple_conversation_message_get_alias
+		* purple_conversation_message_get_conv
+		* purple_contact_get_contact_size
+		* purple_notify_searchresult_column_get_title
 		* purple_notify_searchresult_column_is_visible
 		* purple_notify_searchresult_column_set_visible
 		* purple_notify_user_info_prepend_pair_plaintext
@@ -50,7 +59,7 @@
 		* purple_xfer_get_ui_data
 		* purple_xfer_get_watcher
 		* purple_xfer_set_fd
-		* purple_Xfer_set_local_port
+		* purple_xfer_set_local_port
 		* purple_xfer_set_protocol_data
 		* purple_xfer_set_status
 		* purple_xfer_set_ui_data
@@ -68,6 +77,8 @@
 		  PurpleCertificate*s as the second parameter
 		* purple_connection_error now takes a PurpleConnectionError
 		  as the second parameter
+		* purple_conversation_get_gc renamed to
+		  purple_conversation_get_connection
 		* purple_dnsquery_a now takes a PurpleAccount as the first parameter
 		* purple_network_listen now takes the protocol family as the second
 		  parameter
@@ -84,15 +95,25 @@
 		* purple_notify_user_info_prepend_pair renamed to
 		  purple_notify_user_info_prepend_pair_html
 		* purple_srv_resolve now takes a PurpleAccount as the first parameter
+		* purple_str_size_to_units now takes a goffset as the size parameter
 		* purple_txt_resolve now takes a PurpleAccount as the first parameter
 		* purple_util_fetch_url_request now takes a PurpleAccount as
 		  the first parameter
 		* purple_util_fetch_url_request now takes a length as the eighth
 		  parameter
 		* purple_util_fetch_url_len now takes a length as the fifth parameter
+		* purple_xfer_get_bytes_remaining now returns a goffset
+		* purple_xfer_get_bytes_sent now returns a goffset
+		* purple_xfer_get_size now returns a goffset
 		* purple_xfer_is_canceled renamed to purple_xfer_is_cancelled
+		* purple_xfer_set_bytes_sent now takes a goffset as the bytes_sent
+		  parameter
+		* purple_xfer_set_size now takes a goffset as the size parameter
 		* PurpleConnectionUiOps.report_disconnect now passes a
 		  PurpleConnectionError as the second parameter
+		* PurpleXfer.bytes_remaining is now a goffset
+		* PurpleXfer.bytes_sent is now a goffset
+		* PurpleXfer.size is now a goffset
 
 		Removed:
 		* _GntFileType
@@ -190,7 +211,12 @@
 		* PurplePluginProtocolInfo.get_cb_away
 		* serv_got_attention
 		* serv_send_attention
+		* struct _GtkIMHtmlAnimation
 		* struct _GtkIMHtmlFontDetail
+		* struct _GtkIMHtmlHr
+		* struct _GtkIMHtmlImage
+		* struct _GtkIMHtmlScalable
+		* struct _GtkSmileyTree
 		* struct _PidginChatPane
 		* struct _PidginImPane
 		* struct _PurpleAttentionType
@@ -198,6 +224,7 @@
 		* struct _PurpleConvChat
 		* struct _PurpleConvChatBuddy
 		* struct _PurpleConvIm
+		* struct _PurpleConvMessage
 		* struct _PurpleMenuAction
 		* struct _PurplePounce
 		* struct _PurpleProxyInfo
@@ -205,12 +232,17 @@
 		* struct _PurpleRoomlist
 		* struct _PurpleRoomlistField
 		* struct _PurpleRoomlistRoom
+		* struct _PurpleWhiteboard
 		* struct PurpleAccountOption
 		* struct PurpleAccountUserSplit
+		* struct PurpleNotifySearchColumn
 		* wpurple_g_access
 		* xmlnode_set_attrib_with_namespace
 		* xmlnode_set_attrib_with_prefix
 
+version 2.10.1:
+	* No changes
+
 version 2.10.0:
 	libpurple:
 		Added:
--- a/configure.ac	Sun Oct 09 07:10:36 2011 +0000
+++ b/configure.ac	Fri Dec 23 06:58:52 2011 +0000
@@ -202,6 +202,12 @@
 dnl FreeBSD doesn't have libdl, dlopen is provided by libc
 AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")])
 
+dnl Windows and Haiku do not use libm for the math functions, they are part
+dnl of the C library
+AC_SEARCH_LIBS([ceil], [m], [], [
+  AC_MSG_ERROR([unable to find the ceil() function])
+])
+
 AC_MSG_CHECKING(for fileno())
 AC_RUN_IFELSE([AC_LANG_SOURCE([[
 #include <stdio.h>
@@ -401,6 +407,10 @@
 	[AC_HELP_STRING([--disable-gestures],
 		[compile without the gestures plugin])],
 	enable_gestures="$enableval", enable_gestures="yes")
+AC_ARG_ENABLE(gcr,
+	[AC_HELP_STRING([--enable-gcr],
+		[compile with GCR certificate widgets])],
+	enable_gcr="$enableval", enable_gcr="no")
 
 AC_PATH_XTRA
 # We can't assume that $x_libraries will be set, because autoconf does not
@@ -614,9 +624,26 @@
 ])
 			fi])
 	fi
-        
+
+	dnl #######################################################################
+	dnl # Check for GCR for its certificate widgets
+	dnl #######################################################################
+	if test "x$enable_gcr" = "xyes"; then
+		PKG_CHECK_MODULES(GCR, gcr-0, [
+			AC_DEFINE(ENABLE_GCR, 1, [Define to 1 if GCR is found.])], [
+			AC_MSG_RESULT(no)
+			enable_gcr="no"
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
+GCR development headers not found.
+Use --disable-gcr if you do not need GCR certificate widgets.
+])
+			fi])
+	fi
+
 
 else # GTK
+	enable_gcr=no
 	enable_cap=no
 	enable_gevolution=no
 	enable_gtkspell=no
@@ -629,6 +656,7 @@
 AM_CONDITIONAL(BUILD_GEVOLUTION, test "x$enable_gevolution" = "xyes")
 AM_CONDITIONAL(ENABLE_CAP, test "x$enable_cap" = "xyes")
 AM_CONDITIONAL(ENABLE_GESTURES, test "x$enable_gestures" = "xyes")
+AM_CONDITIONAL(ENABLE_GCR, test "x$enable_gcr" = "xyes")
 
 
 dnl #######################################################################
@@ -2496,7 +2524,6 @@
 		   pidgin/pixmaps/emotes/none/Makefile
 		   pidgin/pixmaps/emotes/small/16/Makefile
 		   pidgin/plugins/Makefile
-		   pidgin/plugins/adiumthemes/Makefile
 		   pidgin/plugins/cap/Makefile
 		   pidgin/plugins/disco/Makefile
 		   pidgin/plugins/gestures/Makefile
@@ -2505,6 +2532,7 @@
 		   pidgin/plugins/perl/Makefile
 		   pidgin/plugins/perl/common/Makefile.PL
 		   pidgin/plugins/ticker/Makefile
+		   pidgin/themes/Makefile
 		   libpurple/ciphers/Makefile
 		   libpurple/example/Makefile
 		   libpurple/gconf/Makefile
@@ -2588,6 +2616,7 @@
 echo Use X Session Management...... : $enable_sm
 echo Use startup notification...... : $enable_startup_notification
 echo Build with GtkSpell support... : $enable_gtkspell
+echo Build with GCR widgets........ : $enable_gcr
 echo
 echo Build with plugin support..... : $enable_plugins
 echo Build with Mono support....... : $enable_mono
--- a/finch/gntblist.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/finch/gntblist.c	Fri Dec 23 06:58:52 2011 +0000
@@ -169,7 +169,7 @@
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		PurpleBuddy *buddy = (PurpleBuddy*)node;
-		FinchBlistNode *fnode = FINCH_GET_DATA(node);
+		FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 		if (!purple_buddy_get_contact(buddy))
 			return FALSE; /* When a new buddy is added and show-offline is set */
 		if (PURPLE_BUDDY_IS_ONLINE(buddy))
@@ -329,11 +329,11 @@
 static FinchBlistNode *
 create_finch_blist_node(PurpleBlistNode *node, gpointer row)
 {
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 	if (!fnode) {
 		fnode = g_new0(FinchBlistNode, 1);
 		fnode->signed_timer = 0;
-		FINCH_SET_DATA(node, fnode);
+		purple_blist_node_set_ui_data(node, fnode);
 	}
 	fnode->row = row;
 	return fnode;
@@ -342,13 +342,13 @@
 static void
 reset_blist_node_ui_data(PurpleBlistNode *node)
 {
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 	if (fnode == NULL)
 		return;
 	if (fnode->signed_timer)
 		purple_timeout_remove(fnode->signed_timer);
 	g_free(fnode);
-	FINCH_SET_DATA(node, NULL);
+	purple_blist_node_set_ui_data(node, NULL);
 }
 
 static int
@@ -381,7 +381,7 @@
 get_blist_node_flag(PurpleBlistNode *node)
 {
 	GntTextFormatFlags flag = 0;
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 
 	if (ggblist->tagged && g_list_find(ggblist->tagged, node))
 		flag |= GNT_TEXT_FLAG_BOLD;
@@ -390,7 +390,7 @@
 		flag |= GNT_TEXT_FLAG_BLINK;
 	else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node)));
-		fnode = FINCH_GET_DATA(node);
+		fnode = purple_blist_node_get_ui_data(node);
 		if (fnode && fnode->signed_timer)
 			flag |= GNT_TEXT_FLAG_BLINK;
 	} else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
@@ -406,7 +406,7 @@
 					node = purple_blist_node_get_sibling_next(node)) {
 				PurpleBlistNode *pnode;
 				pnode = purple_contact_get_priority_buddy((PurpleContact*)node);
-				fnode = FINCH_GET_DATA(node);
+				fnode = purple_blist_node_get_ui_data(node);
 				if (fnode && fnode->signed_timer) {
 					flag |= GNT_TEXT_FLAG_BLINK;
 					break;
@@ -433,7 +433,7 @@
 	PurpleBlistNode *node;
 	for (node = purple_blist_node_get_first_child(((PurpleBlistNode*)contact)); node;
 			node = purple_blist_node_get_sibling_next(node)) {
-		FinchBlistNode *fnode = FINCH_GET_DATA(node);
+		FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 		if (PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) ||
 				(fnode && fnode->signed_timer))
 			return TRUE;
@@ -465,7 +465,7 @@
 static void
 add_node(PurpleBlistNode *node, FinchBlist *ggblist)
 {
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 
 	if (!ggblist->manager->can_add_node(node))
@@ -502,7 +502,7 @@
 	FinchBlist *ggblist = FINCH_GET_DATA(list);
 	PurpleBlistNode *parent;
 
-	if (ggblist == NULL || FINCH_GET_DATA(node) == NULL)
+	if (ggblist == NULL || purple_blist_node_get_ui_data(node) == NULL)
 		return;
 
 	if (PURPLE_BLIST_NODE_IS_GROUP(node) && ggblist->new_group) {
@@ -543,7 +543,7 @@
 	if (ggblist->window == NULL)
 		return;
 
-	if (FINCH_GET_DATA(node)!= NULL) {
+	if (purple_blist_node_get_ui_data(node)!= NULL) {
 		gnt_tree_change_text(GNT_TREE(ggblist->tree), node,
 				0, get_display_name(node));
 		gnt_tree_sort_row(GNT_TREE(ggblist->tree), node);
@@ -560,7 +560,7 @@
 	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
 		add_node(node, FINCH_GET_DATA(list));
 	} else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
-		if (FINCH_GET_DATA(node)== NULL) {
+		if (purple_blist_node_get_ui_data(node)== NULL) {
 			/* The core seems to expect the UI to add the buddies. */
 			for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node))
 				add_node(node, FINCH_GET_DATA(list));
@@ -839,7 +839,7 @@
 
 	/* Select the group */
 	if (ggblist->tree) {
-		FinchBlistNode *fnode = FINCH_GET_DATA((PurpleBlistNode*)grp);
+		FinchBlistNode *fnode = purple_blist_node_get_ui_data((PurpleBlistNode*)grp);
 		if (!fnode)
 			add_node((PurpleBlistNode*)grp, ggblist);
 		gnt_tree_set_selected(GNT_TREE(ggblist->tree), grp);
@@ -887,7 +887,7 @@
 {
 	gpointer parent;
 	PurpleBlistNode *node = (PurpleBlistNode *)group;
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 	parent = ggblist->manager->find_parent((PurpleBlistNode*)group);
 	create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
@@ -960,7 +960,7 @@
 {
 	gpointer parent;
 	PurpleBlistNode *node = (PurpleBlistNode *)chat;
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 	if (!purple_account_is_connected(purple_chat_get_account(chat)))
 		return;
@@ -979,7 +979,7 @@
 	PurpleBlistNode *node = (PurpleBlistNode*)contact;
 	const char *name;
 
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 
 	name = get_display_name(node);
@@ -1002,7 +1002,7 @@
 	PurpleBlistNode *node = (PurpleBlistNode *)buddy;
 	PurpleContact *contact;
 
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 
 	contact = purple_buddy_get_contact(buddy);
@@ -1561,7 +1561,7 @@
 	if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		PurpleContact *c = (PurpleContact*)node;
 		name = purple_contact_get_alias(c);
-		if (c->totalsize > 1)
+		if (purple_contact_get_contact_size(c, TRUE) > 1)
 			sec = _("Removing this contact will also remove all the buddies in the contact");
 	} else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		name = purple_buddy_get_name((PurpleBuddy*)node);
@@ -2545,7 +2545,7 @@
 buddy_recent_signed_on_off(gpointer data)
 {
 	PurpleBlistNode *node = data;
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 
 	purple_timeout_remove(fnode->signed_timer);
 	fnode->signed_timer = 0;
@@ -2565,7 +2565,7 @@
 buddy_signed_on_off_cb(gpointer data)
 {
 	PurpleBlistNode *node = data;
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 	if (!ggblist || !fnode)
 		return FALSE;
 
--- a/finch/gntconv.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/finch/gntconv.c	Fri Dec 23 06:58:52 2011 +0000
@@ -123,7 +123,7 @@
 			if (send || (purple_conv_im_get_type_again(im) != 0 &&
 						  time(NULL) > purple_conv_im_get_type_again(im))) {
 				unsigned int timeout;
-				timeout = serv_send_typing(purple_conversation_get_gc(conv),
+				timeout = serv_send_typing(purple_conversation_get_connection(conv),
 										   purple_conversation_get_name(conv),
 										   PURPLE_TYPING);
 				purple_conv_im_set_type_again(im, timeout);
@@ -131,7 +131,7 @@
 		} else {
 			purple_conv_im_stop_send_typed_timeout(im);
 
-			serv_send_typing(purple_conversation_get_gc(conv),
+			serv_send_typing(purple_conversation_get_connection(conv),
 							 purple_conversation_get_name(conv),
 							 PURPLE_NOT_TYPING);
 		}
@@ -414,7 +414,7 @@
 send_file_cb(GntMenuItem *item, gpointer ggconv)
 {
 	FinchConv *ggc = ggconv;
-	serv_send_file(purple_conversation_get_gc(ggc->active_conv),
+	serv_send_file(purple_conversation_get_connection(ggc->active_conv),
 			purple_conversation_get_name(ggc->active_conv), NULL);
 }
 
@@ -431,7 +431,7 @@
 get_info_cb(GntMenuItem *item, gpointer ggconv)
 {
 	FinchConv *ggc = ggconv;
-	finch_retrieve_user_info(purple_conversation_get_gc(ggc->active_conv),
+	finch_retrieve_user_info(purple_conversation_get_connection(ggc->active_conv),
 			purple_conversation_get_name(ggc->active_conv));
 }
 
@@ -683,7 +683,7 @@
 
 	name = gnt_tree_get_selection_data(GNT_TREE(widget));
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_cb_real_name))
 		realname = prpl_info->get_cb_real_name(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(fc->active_conv)), name);
 	else
--- a/finch/gntnotify.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/finch/gntnotify.c	Fri Dec 23 06:58:52 2011 +0000
@@ -386,6 +386,7 @@
 {
 	GntTree *tree = GNT_TREE(data);
 	GList *o;
+	GntTreeRow *prev = NULL;
 
 	/* XXX: Do I need to empty the tree here? */
 
@@ -393,10 +394,17 @@
 	{
 		gnt_tree_add_row_after(GNT_TREE(tree), o->data,
 				gnt_tree_create_row_from_list(GNT_TREE(tree), o->data),
-				NULL, NULL);
+				NULL, prev);
+		prev = o->data;
 	}
 }
 
+static void
+notify_sr_destroy_cb(GntWidget *window, void *data)
+{
+	purple_notify_close(PURPLE_NOTIFY_SEARCHRESULTS, window);
+}
+
 static void *
 finch_notify_searchresults(PurpleConnection *gc, const char *title,
 		const char *primary, const char *secondary,
@@ -429,7 +437,7 @@
 	for (iter = results->columns; iter; iter = iter->next)
 	{
 		PurpleNotifySearchColumn *column = iter->data;
-		gnt_tree_set_column_title(GNT_TREE(tree), i, column->title);
+		gnt_tree_set_column_title(GNT_TREE(tree), i, purple_notify_searchresult_column_get_title(column));
 
 		if (!purple_notify_searchresult_column_is_visible(column))
 			gnt_tree_set_column_visible(GNT_TREE(tree), i, FALSE);
@@ -481,6 +489,8 @@
 	}
 
 	gnt_box_add_widget(GNT_BOX(window), box);
+	g_signal_connect(G_OBJECT(tree), "destroy",
+			G_CALLBACK(notify_sr_destroy_cb), NULL);
 
 	finch_notify_sr_new_rows(gc, results, tree);
 
--- a/finch/libgnt/gntwm.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/finch/libgnt/gntwm.c	Fri Dec 23 06:58:52 2011 +0000
@@ -32,7 +32,7 @@
 #define _GNU_SOURCE
 #endif
 
-#if !defined _XOPEN_SOURCE_EXTENDED && (defined(__APPLE__) || defined(__unix__)) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
+#if !defined _XOPEN_SOURCE_EXTENDED && (defined(__APPLE__) || defined(__unix__)) && !defined(__FreeBSD__)
 #define _XOPEN_SOURCE_EXTENDED
 #endif
 
--- a/finch/plugins/grouping.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/finch/plugins/grouping.c	Fri Dec 23 06:58:52 2011 +0000
@@ -54,7 +54,7 @@
 		case PURPLE_BLIST_CONTACT_NODE:
 			{
 				PurpleContact *contact = (PurpleContact*)node;
-				if (contact->currentsize > 0)
+				if (purple_contact_get_contact_size(contact, FALSE) > 0)
 					return TRUE;
 				return FALSE;
 			}
--- a/libpurple/account.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/account.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1119,6 +1119,15 @@
 }
 
 void
+purple_account_register_completed(PurpleAccount *account, gboolean succeeded)
+{
+	g_return_if_fail(account != NULL);
+
+	if (account->registration_cb)
+		(account->registration_cb)(account, succeeded, account->registration_cb_user_data);
+}
+
+void
 purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data)
 {
 	g_return_if_fail(account != NULL);
@@ -1265,6 +1274,14 @@
 	account->disconnecting = FALSE;
 }
 
+gboolean
+purple_account_is_disconnecting(const PurpleAccount *account)
+{
+	g_return_val_if_fail(account != NULL, TRUE);
+	
+	return account->disconnecting;
+}
+
 void
 purple_account_notify_added(PurpleAccount *account, const char *remote_user,
                           const char *id, const char *alias,
@@ -1591,7 +1608,7 @@
 	purple_request_input(gc, _("Set User Info"), primary, NULL,
 					   purple_account_get_user_info(account),
 					   TRUE, FALSE, ((gc != NULL) &&
-					   (gc->flags & PURPLE_CONNECTION_HTML) ? "html" : NULL),
+					   (purple_connection_get_flags(gc) & PURPLE_CONNECTION_HTML) ? "html" : NULL),
 					   _("Save"), G_CALLBACK(set_user_info_cb),
 					   _("Cancel"), NULL,
 					   account, NULL, NULL,
--- a/libpurple/account.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/account.h	Fri Dec 23 06:58:52 2011 +0000
@@ -221,6 +221,15 @@
 void purple_account_register(PurpleAccount *account);
 
 /**
+ * Registration of the account was completed.
+ * Calls the registration call-back set with purple_account_set_register_callback().
+ *
+ * @param account The account being registered.
+ * @param succeeded Was the account registration successful?
+ */
+void purple_account_register_completed(PurpleAccount *account, gboolean succeeded);
+
+/**
  * Unregisters an account (deleting it from the server).
  *
  * @param account The account to unregister.
@@ -237,6 +246,15 @@
 void purple_account_disconnect(PurpleAccount *account);
 
 /**
+ * Indicates if the account is currently being disconnected.
+ *
+ * @param account The account
+ *
+ * @return TRUE if the account is being disconnected.
+ */
+gboolean purple_account_is_disconnecting(const PurpleAccount *account);
+
+/**
  * Notifies the user that the account was added to a remote user's
  * buddy list.
  *
--- a/libpurple/blist.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/blist.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1774,6 +1774,13 @@
 	contact->priority_valid = FALSE;
 }
 
+int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline)   
+{
+	g_return_val_if_fail(contact != NULL, 0);
+
+	return offline ? contact->totalsize : contact->currentsize;
+}   
+
 PurpleGroup *purple_group_new(const char *name)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
--- a/libpurple/blist.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/blist.h	Fri Dec 23 06:58:52 2011 +0000
@@ -756,6 +756,15 @@
 void purple_contact_invalidate_priority_buddy(PurpleContact *contact);
 
 /**
+ * Determines the total size of a contact.
+ *
+ * @param contact	The contact
+ * @param offline	Count buddies in offline accounts
+ * @return The number of buddies in the contact
+ */
+int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline);
+
+/**
  * Removes a buddy from the buddy list and frees the memory allocated to it.
  * This doesn't actually try to remove the buddy from the server list.
  *
--- a/libpurple/certificate.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/certificate.c	Fri Dec 23 06:58:52 2011 +0000
@@ -499,6 +499,24 @@
 	return (scheme->get_times)(crt, activation, expiration);
 }
 
+GByteArray *
+purple_certificate_get_der_data(PurpleCertificate *crt)
+{
+	PurpleCertificateScheme *scheme;
+	GByteArray *data;
+
+	g_return_val_if_fail(crt, NULL);
+	g_return_val_if_fail(crt->scheme, NULL);
+
+	scheme = crt->scheme;
+
+	g_return_val_if_fail(scheme->get_der_data, NULL);
+
+	data = (scheme->get_der_data)(crt);
+
+	return data;
+}
+
 gchar *
 purple_certificate_pool_mkpath(PurpleCertificatePool *pool, const gchar *id)
 {
--- a/libpurple/certificate.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/certificate.h	Fri Dec 23 06:58:52 2011 +0000
@@ -257,9 +257,17 @@
 	 */
 	GSList * (* import_certificates)(const gchar * filename);
 
+	/**
+	 * Retrieves the certificate data in DER form
+	 *
+	 * @param crt   Certificate instance
+	 * @return Binary DER representation of certificate - must be freed using
+	 *         g_byte_array_free()
+	 */
+	GByteArray * (* get_der_data)(PurpleCertificate *crt);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
 };
 
 /** A set of operations used to provide logic for verifying a Certificate's
@@ -561,6 +569,17 @@
 gboolean
 purple_certificate_get_times(PurpleCertificate *crt, time_t *activation, time_t *expiration);
 
+/**
+ * Retrieves the certificate data in DER form.
+ *
+ * @param crt Certificate instance
+ *
+ * @return Binary DER representation of the certificate - must be freed using
+ *         g_byte_array_free().
+ */
+GByteArray *
+purple_certificate_get_der_data(PurpleCertificate *crt);
+
 /*@}*/
 
 /*****************************************************************************/
--- a/libpurple/cmds.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/cmds.c	Fri Dec 23 06:58:52 2011 +0000
@@ -385,5 +385,10 @@
 void purple_cmds_uninit(void)
 {
 	purple_signals_unregister_by_instance(purple_cmds_get_handle());
+
+	while (cmds) {
+		purple_cmd_free(cmds->data);
+		cmds = g_list_delete_link(cmds, cmds);
+	}
 }
 
--- a/libpurple/connection.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/connection.c	Fri Dec 23 06:58:52 2011 +0000
@@ -387,6 +387,14 @@
 }
 
 void
+purple_connection_set_flags(PurpleConnection *gc, PurpleConnectionFlags flags)
+{
+	g_return_if_fail(gc != NULL);
+
+	gc->flags = flags;
+}
+
+void
 purple_connection_set_account(PurpleConnection *gc, PurpleAccount *account)
 {
 	g_return_if_fail(gc != NULL);
@@ -419,6 +427,14 @@
 	return gc->state;
 }
 
+PurpleConnectionFlags
+purple_connection_get_flags(const PurpleConnection *gc)
+{
+	g_return_val_if_fail(gc != NULL, 0);
+
+	return gc->flags;
+}
+
 PurpleAccount *
 purple_connection_get_account(const PurpleConnection *gc)
 {
@@ -611,6 +627,13 @@
 	}
 }
 
+void purple_connection_update_last_received(PurpleConnection *gc)
+{
+	g_return_if_fail(gc != NULL);
+
+	gc->last_received = time(NULL);
+}
+
 void
 purple_connections_disconnect_all(void)
 {
--- a/libpurple/connection.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/connection.h	Fri Dec 23 06:58:52 2011 +0000
@@ -235,7 +235,6 @@
 
 	PurpleAccount *account;        /**< The account being connected to.    */
 	char *password;              /**< The password used.                 */
-	int inpa;                    /**< The input watcher.                 */
 
 	GSList *buddy_chats;         /**< A list of active chats
 	                                  (#PurpleConversation structs of type
@@ -281,6 +280,14 @@
 void purple_connection_set_state(PurpleConnection *gc, PurpleConnectionState state);
 
 /**
+ * Sets the connection flags.
+ *
+ * @param gc    The connection.
+ * @param flags The flags.
+ */
+void purple_connection_set_flags(PurpleConnection *gc, PurpleConnectionFlags flags);
+
+/**
  * Sets the connection's account.
  *
  * @param gc      The connection.
@@ -314,6 +321,15 @@
 PurpleConnectionState purple_connection_get_state(const PurpleConnection *gc);
 
 /**
+ * Returns the connection flags.
+ *
+ * @param gc The connection.
+ *
+ * @return The connection flags.
+ */
+PurpleConnectionFlags purple_connection_get_flags(const PurpleConnection *gc);
+
+/**
  * Returns TRUE if the account is connected, otherwise returns FALSE.
  *
  * @return TRUE if the account is connected, otherwise returns FALSE.
@@ -430,6 +446,14 @@
 gboolean
 purple_connection_error_is_fatal (PurpleConnectionError reason);
 
+/**
+ * Indicate that a packet was received on the connection.
+ * Set by the prpl to avoid sending unneeded keepalives.
+ *
+ * @param gc   The connection.
+ */
+void purple_connection_update_last_received(PurpleConnection *gc);
+
 /*@}*/
 
 /**************************************************************************/
--- a/libpurple/conversation.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/conversation.c	Fri Dec 23 06:58:52 2011 +0000
@@ -146,6 +146,19 @@
 	GList *message_history;         /**< Message history, as a GList of PurpleConvMessage's */
 };
 
+/**
+ * Description of a conversation message
+ */
+struct _PurpleConvMessage
+{
+	char *who;
+	char *what;
+	PurpleMessageFlags flags;
+	time_t when;
+	PurpleConversation *conv;
+	char *alias;
+};
+
 
 static GList *conversations = NULL;
 static GList *ims = NULL;
@@ -228,7 +241,7 @@
 
 	g_return_val_if_fail(conv != NULL, FALSE);
 
-	gc   = purple_conversation_get_gc(conv);
+	gc   = purple_conversation_get_connection(conv);
 	name = purple_conversation_get_name(conv);
 
 	if (gc != NULL && name != NULL) {
@@ -258,7 +271,7 @@
 		return;
 
 	account = purple_conversation_get_account(conv);
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(gc != NULL);
@@ -493,7 +506,7 @@
 	conv->data         = g_hash_table_new_full(g_str_hash, g_str_equal,
 											   g_free, NULL);
 	/* copy features from the connection. */
-	conv->features = gc->flags;
+	conv->features = purple_connection_get_flags(gc);
 
 	if (type == PURPLE_CONV_TYPE_IM)
 	{
@@ -581,7 +594,7 @@
 	purple_request_close_with_handle(conv);
 
 	ops  = purple_conversation_get_ui_ops(conv);
-	gc   = purple_conversation_get_gc(conv);
+	gc   = purple_conversation_get_connection(conv);
 	name = purple_conversation_get_name(conv);
 
 	if (gc != NULL)
@@ -806,7 +819,7 @@
 }
 
 PurpleConnection *
-purple_conversation_get_gc(const PurpleConversation *conv)
+purple_conversation_get_connection(const PurpleConversation *conv)
 {
 	PurpleAccount *account;
 
@@ -1646,7 +1659,7 @@
 	g_return_if_fail(message != NULL);
 
 	conv      = purple_conv_chat_get_conversation(chat);
-	gc        = purple_conversation_get_gc(conv);
+	gc        = purple_conversation_get_connection(conv);
 	account   = purple_connection_get_account(gc);
 
 	/* Don't display this if the person who wrote it is ignored. */
@@ -1762,7 +1775,7 @@
 	conv = purple_conv_chat_get_conversation(chat);
 	ops  = purple_conversation_get_ui_ops(conv);
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	g_return_if_fail(gc != NULL);
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	g_return_if_fail(prpl_info != NULL);
@@ -1789,7 +1802,7 @@
 				}
 			} else {
 				PurpleBuddy *buddy;
-				if ((buddy = purple_find_buddy(gc->account, user)) != NULL)
+				if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL)
 					alias = purple_buddy_get_contact_alias(buddy);
 			}
 		}
@@ -1863,7 +1876,7 @@
 	conv = purple_conv_chat_get_conversation(chat);
 	ops  = purple_conversation_get_ui_ops(conv);
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	g_return_if_fail(gc != NULL);
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	g_return_if_fail(prpl_info != NULL);
@@ -1882,12 +1895,12 @@
 			{
 				const char *display_name = purple_connection_get_display_name(gc);
 				if (display_name != NULL)
-					alias = display_name;
+					new_alias = display_name;
 			}
 		}
 	} else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 		PurpleBuddy *buddy;
-		if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL)
+		if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL)
 			new_alias = purple_buddy_get_contact_alias(buddy);
 	}
 
@@ -1936,9 +1949,9 @@
 			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 				PurpleBuddy *buddy;
 
-				if ((buddy = purple_find_buddy(gc->account, old_user)) != NULL)
+				if ((buddy = purple_find_buddy(purple_connection_get_account(gc), old_user)) != NULL)
 					old_alias = purple_buddy_get_contact_alias(buddy);
-				if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL)
+				if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL)
 					new_alias = purple_buddy_get_contact_alias(buddy);
 			}
 
@@ -1982,7 +1995,7 @@
 
 	conv = purple_conv_chat_get_conversation(chat);
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	g_return_if_fail(gc != NULL);
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	g_return_if_fail(prpl_info != NULL);
@@ -2013,7 +2026,7 @@
 			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 				PurpleBuddy *buddy;
 
-				if ((buddy = purple_find_buddy(gc->account, user)) != NULL)
+				if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL)
 					alias = purple_buddy_get_contact_alias(buddy);
 			}
 
@@ -2167,7 +2180,7 @@
 		conv = (PurpleConversation *)l->data;
 
 		if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)) == id &&
-			purple_conversation_get_gc(conv) == gc)
+			purple_conversation_get_connection(conv) == gc)
 			return conv;
 	}
 
@@ -2195,7 +2208,7 @@
 	user = purple_request_fields_get_string(fields, "screenname");
 	message = purple_request_fields_get_string(fields, "message");
 
-	serv_chat_invite(purple_conversation_get_gc(conv), chat->id, message, user);
+	serv_chat_invite(purple_conversation_get_connection(conv), chat->id, message, user);
 }
 
 void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user,
@@ -2438,30 +2451,42 @@
 	return conv->message_history;
 }
 
-const char *purple_conversation_message_get_sender(PurpleConvMessage *msg)
+const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg)
 {
 	g_return_val_if_fail(msg, NULL);
 	return msg->who;
 }
 
-const char *purple_conversation_message_get_message(PurpleConvMessage *msg)
+const char *purple_conversation_message_get_message(const PurpleConvMessage *msg)
 {
 	g_return_val_if_fail(msg, NULL);
 	return msg->what;
 }
 
-PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg)
+PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg)
 {
 	g_return_val_if_fail(msg, 0);
 	return msg->flags;
 }
 
-time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg)
+time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg)
 {
 	g_return_val_if_fail(msg, 0);
 	return msg->when;
 }
 
+const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg)
+{
+	g_return_val_if_fail(msg, NULL);
+	return msg->alias;
+}
+
+PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg)
+{
+	g_return_val_if_fail(msg, NULL);
+	return msg->conv;
+}
+
 void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data)
 {
 	g_return_if_fail(conv != NULL);
--- a/libpurple/conversation.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/conversation.h	Fri Dec 23 06:58:52 2011 +0000
@@ -249,19 +249,6 @@
 	void (*_purple_reserved4)(void);
 };
 
-/**
- * Description of a conversation message
- */
-struct _PurpleConvMessage
-{
-	char *who;
-	char *what;
-	PurpleMessageFlags flags;
-	time_t when;
-	PurpleConversation *conv;
-	char *alias;
-};
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -368,13 +355,11 @@
 /**
  * Returns the specified conversation's purple_connection.
  *
- * This is the same as purple_conversation_get_user(conv)->gc.
- *
  * @param conv The conversation.
  *
  * @return The conversation's purple_connection.
  */
-PurpleConnection *purple_conversation_get_gc(const PurpleConversation *conv);
+PurpleConnection *purple_conversation_get_connection(const PurpleConversation *conv);
 
 /**
  * Sets the specified conversation's title.
@@ -660,7 +645,7 @@
  *
  * @return   The name of the sender of the message
  */
-const char *purple_conversation_message_get_sender(PurpleConvMessage *msg);
+const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg);
 
 /**
  * Get the message from a PurpleConvMessage
@@ -669,7 +654,7 @@
  *
  * @return   The name of the sender of the message
  */
-const char *purple_conversation_message_get_message(PurpleConvMessage *msg);
+const char *purple_conversation_message_get_message(const PurpleConvMessage *msg);
 
 /**
  * Get the message-flags of a PurpleConvMessage
@@ -678,7 +663,7 @@
  *
  * @return   The message flags
  */
-PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg);
+PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg);
 
 /**
  * Get the timestamp of a PurpleConvMessage
@@ -687,7 +672,25 @@
  *
  * @return   The timestamp of the message
  */
-time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg);
+time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg);
+
+/**
+ * Get the alias from a PurpleConvMessage
+ *
+ * @param msg   A PurpleConvMessage
+ *
+ * @return   The alias of the sender of the message
+ */
+const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg);
+
+/**
+ * Get the conversation associated with the PurpleConvMessage
+ *
+ * @param msg   A PurpleConvMessage
+ *
+ * @return   The conversation
+ */
+PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg);
 
 /**
  * Set the UI data associated with this conversation.
--- a/libpurple/dbus-analyze-functions.py	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/dbus-analyze-functions.py	Fri Dec 23 06:58:52 2011 +0000
@@ -495,7 +495,7 @@
         if self.function.name in stringlists:
             self.cdecls.append("\tchar **%s;" % name)
             self.ccode.append("\tlist = %s;" % self.call)
-            self.ccode.append("\t%s = (char **)purple_%s_to_array(list, FALSE, &%s_LEN);" % \
+            self.ccode.append("\t%s = (char **)purple_%s_to_array(list, &%s_LEN);" % \
                          (name, type[0], name))
             self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \
                           % (name, name))
@@ -507,7 +507,7 @@
         else:
             self.cdecls.append("\tdbus_int32_t *%s;" % name)
             self.ccode.append("\tlist = %s;" % self.call)
-            self.ccode.append("\t%s = purple_dbusify_%s(list, FALSE, &%s_LEN);" % \
+            self.ccode.append("\t%s = purple_dbusify_%s(list, &%s_LEN);" % \
                          (name, type[0], name))
             if (not (self.function.name in constlists)):
                 self.ccode.append("\tg_%s_free(list);" % type[0].lower()[1:])
--- a/libpurple/dbus-bindings.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/dbus-bindings.h	Fri Dec 23 06:58:52 2011 +0000
@@ -84,14 +84,10 @@
 					int              first_arg_type,
 					va_list          var_args);
 
-dbus_int32_t* purple_dbusify_GList(GList *list, gboolean free_memory,
-				 dbus_int32_t *len);
-dbus_int32_t* purple_dbusify_GSList(GSList *list, gboolean free_memory,
-				  dbus_int32_t *len);
-gpointer* purple_GList_to_array(GList *list, gboolean free_memory,
-			      dbus_int32_t *len);
-gpointer* purple_GSList_to_array(GSList *list, gboolean free_memory,
-			      dbus_int32_t *len);
+dbus_int32_t* purple_dbusify_GList(GList *list, dbus_int32_t *len);
+dbus_int32_t* purple_dbusify_GSList(GSList *list, dbus_int32_t *len);
+gpointer* purple_GList_to_array(GList *list, dbus_int32_t *len);
+gpointer* purple_GSList_to_array(GSList *list, dbus_int32_t *len);
 GHashTable *purple_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error);
 
 const char* empty_to_null(const char *str);
--- a/libpurple/dbus-server.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/dbus-server.c	Fri Dec 23 06:58:52 2011 +0000
@@ -300,7 +300,7 @@
 }
 
 dbus_int32_t *
-purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len)
+purple_dbusify_GList(GList *list, dbus_int32_t *len)
 {
 	dbus_int32_t *array;
 	int i;
@@ -311,14 +311,11 @@
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = purple_dbus_pointer_to_id(elem->data);
 
-	if (free_memory)
-		g_list_free(list);
-
 	return array;
 }
 
 dbus_int32_t *
-purple_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len)
+purple_dbusify_GSList(GSList *list, dbus_int32_t *len)
 {
 	dbus_int32_t *array;
 	int i;
@@ -329,14 +326,11 @@
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = purple_dbus_pointer_to_id(elem->data);
 
-	if (free_memory)
-		g_slist_free(list);
-
 	return array;
 }
 
 gpointer *
-purple_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len)
+purple_GList_to_array(GList *list, dbus_int32_t *len)
 {
 	gpointer *array;
 	int i;
@@ -347,14 +341,11 @@
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = elem->data;
 
-	if (free_memory)
-		g_list_free(list);
-
 	return array;
 }
 
 gpointer *
-purple_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len)
+purple_GSList_to_array(GSList *list, dbus_int32_t *len)
 {
 	gpointer *array;
 	int i;
@@ -365,9 +356,6 @@
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = elem->data;
 
-	if (free_memory)
-		g_slist_free(list);
-
 	return array;
 }
 
--- a/libpurple/ft.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/ft.c	Fri Dec 23 06:58:52 2011 +0000
@@ -490,7 +490,7 @@
 purple_xfer_ask_recv(PurpleXfer *xfer)
 {
 	char *buf, *size_buf;
-	size_t size;
+	goffset size;
 	gconstpointer thumb;
 	gsize thumb_size;
 
@@ -801,7 +801,7 @@
 	return xfer->local_filename;
 }
 
-size_t
+goffset
 purple_xfer_get_bytes_sent(const PurpleXfer *xfer)
 {
 	g_return_val_if_fail(xfer != NULL, 0);
@@ -809,7 +809,7 @@
 	return xfer->bytes_sent;
 }
 
-size_t
+goffset
 purple_xfer_get_bytes_remaining(const PurpleXfer *xfer)
 {
 	g_return_val_if_fail(xfer != NULL, 0);
@@ -817,7 +817,7 @@
 	return xfer->bytes_remaining;
 }
 
-size_t
+goffset
 purple_xfer_get_size(const PurpleXfer *xfer)
 {
 	g_return_val_if_fail(xfer != NULL, 0);
@@ -965,7 +965,7 @@
 }
 
 void
-purple_xfer_set_size(PurpleXfer *xfer, size_t size)
+purple_xfer_set_size(PurpleXfer *xfer, goffset size)
 {
 	g_return_if_fail(xfer != NULL);
 
@@ -982,7 +982,7 @@
 }
 
 void
-purple_xfer_set_bytes_sent(PurpleXfer *xfer, size_t bytes_sent)
+purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent)
 {
 	g_return_if_fail(xfer != NULL);
 
--- a/libpurple/ft.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/ft.h	Fri Dec 23 06:58:52 2011 +0000
@@ -140,7 +140,7 @@
 	char *message;                /**< A message sent with the request     */
 	char *filename;               /**< The name sent over the network.     */
 	char *local_filename;         /**< The name on the local hard drive.   */
-	size_t size;                  /**< The size of the file.               */
+	goffset size;                 /**< The size of the file.               */
 
 	FILE *dest_fp;                /**< The destination file pointer.       */
 
@@ -151,8 +151,8 @@
 	int fd;                       /**< The socket file descriptor.         */
 	int watcher;                  /**< Watcher.                            */
 
-	size_t bytes_sent;            /**< The number of bytes sent.           */
-	size_t bytes_remaining;       /**< The number of bytes remaining.      */
+	goffset bytes_sent;           /**< The number of bytes sent.           */
+	goffset bytes_remaining;      /**< The number of bytes remaining.      */
 	time_t start_time;            /**< When the transfer of data began.    */
 	time_t end_time;              /**< When the transfer of data ended.    */
 
@@ -358,7 +358,7 @@
  *
  * @return The number of bytes sent.
  */
-size_t purple_xfer_get_bytes_sent(const PurpleXfer *xfer);
+goffset purple_xfer_get_bytes_sent(const PurpleXfer *xfer);
 
 /**
  * Returns the number of bytes remaining to send or receive.
@@ -367,7 +367,7 @@
  *
  * @return The number of bytes remaining.
  */
-size_t purple_xfer_get_bytes_remaining(const PurpleXfer *xfer);
+goffset purple_xfer_get_bytes_remaining(const PurpleXfer *xfer);
 
 /**
  * Returns the size of the file being sent or received.
@@ -376,7 +376,7 @@
  *
  * @return The total size of the file.
  */
-size_t purple_xfer_get_size(const PurpleXfer *xfer);
+goffset purple_xfer_get_size(const PurpleXfer *xfer);
 
 /**
  * Returns the current percentage of progress of the transfer.
@@ -496,7 +496,7 @@
  * @param xfer The file transfer.
  * @param size The size of the file.
  */
-void purple_xfer_set_size(PurpleXfer *xfer, size_t size);
+void purple_xfer_set_size(PurpleXfer *xfer, goffset size);
 
 /**
  * Sets the local port of the file transfer.
@@ -519,7 +519,7 @@
  *                   send.  If we're receiving a file, this is the
  *                   next byte that we expect to receive.
  */
-void purple_xfer_set_bytes_sent(PurpleXfer *xfer, size_t bytes_sent);
+void purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent);
 
 /**
  * Returns the UI operations structure for a file transfer.
@@ -848,3 +848,4 @@
 #endif
 
 #endif /* _PURPLE_FT_H_ */
+
--- a/libpurple/network.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/network.c	Fri Dec 23 06:58:52 2011 +0000
@@ -811,8 +811,20 @@
 			purple_debug_warning("network", "NetworkManager not active. Assuming connection exists.\n");
 	}
 
-	if (nm_state == NM_STATE_UNKNOWN || nm_state == NM_STATE_CONNECTED)
-		return TRUE;
+	switch (nm_state)
+	{
+		case NM_STATE_UNKNOWN:
+#if NM_CHECK_VERSION(0,8,992)
+		case NM_STATE_CONNECTED_LOCAL:
+		case NM_STATE_CONNECTED_SITE:
+		case NM_STATE_CONNECTED_GLOBAL:
+#else
+		case NM_STATE_CONNECTED:
+#endif
+			return TRUE;
+		default:
+			break;
+	}
 
 	return FALSE;
 
@@ -1149,9 +1161,14 @@
 		                                     NM_DBUS_SERVICE,
 		                                     NM_DBUS_PATH,
 		                                     NM_DBUS_INTERFACE);
+		/* NM 0.6 signal */
 		dbus_g_proxy_add_signal(nm_proxy, "StateChange", G_TYPE_UINT, G_TYPE_INVALID);
 		dbus_g_proxy_connect_signal(nm_proxy, "StateChange",
 		                            G_CALLBACK(nm_state_change_cb), NULL, NULL);
+		/* NM 0.7 and later signal */
+		dbus_g_proxy_add_signal(nm_proxy, "StateChanged", G_TYPE_UINT, G_TYPE_INVALID);
+		dbus_g_proxy_connect_signal(nm_proxy, "StateChanged",
+		                            G_CALLBACK(nm_state_change_cb), NULL, NULL);
 
 		dbus_proxy = dbus_g_proxy_new_for_name(nm_conn,
 		                                       DBUS_SERVICE_DBUS,
@@ -1186,6 +1203,7 @@
 #ifdef HAVE_NETWORKMANAGER
 	if (nm_proxy) {
 		dbus_g_proxy_disconnect_signal(nm_proxy, "StateChange", G_CALLBACK(nm_state_change_cb), NULL);
+		dbus_g_proxy_disconnect_signal(nm_proxy, "StateChanged", G_CALLBACK(nm_state_change_cb), NULL);
 		g_object_unref(G_OBJECT(nm_proxy));
 	}
 	if (dbus_proxy) {
--- a/libpurple/notify.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/notify.c	Fri Dec 23 06:58:52 2011 +0000
@@ -56,6 +56,16 @@
 	GQueue entries;
 };
 
+/**
+ * Single column of a search result.
+ */
+struct _PurpleNotifySearchColumn
+{
+	char *title;           /**< Title of the column. */
+	gboolean visible;      /**< Should the column be visible to the user. Defaults to TRUE. */
+
+};
+
 void *
 purple_notify_message(void *handle, PurpleNotifyMsgType type,
 					const char *title, const char *primary,
@@ -368,6 +378,13 @@
 	return sc;
 }
 
+const char *purple_notify_searchresult_column_get_title(const PurpleNotifySearchColumn *column)
+{
+	g_return_val_if_fail(column != NULL, NULL);
+	
+	return column->title;
+}
+
 void purple_notify_searchresult_column_set_visible(PurpleNotifySearchColumn *column, gboolean visible)
 {
 	g_return_if_fail(column != NULL);
--- a/libpurple/notify.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/notify.h	Fri Dec 23 06:58:52 2011 +0000
@@ -32,10 +32,13 @@
 #include <glib.h>
 
 typedef struct _PurpleNotifyUserInfoEntry	PurpleNotifyUserInfoEntry;
-typedef struct _PurpleNotifyUserInfo	PurpleNotifyUserInfo;
+typedef struct _PurpleNotifyUserInfo		PurpleNotifyUserInfo;
+/** @copydoc _PurpleNotifySearchColumn */
+typedef struct _PurpleNotifySearchColumn	PurpleNotifySearchColumn;
 
 #include "connection.h"
 
+
 /**
  * Notification close callbacks.
  */
@@ -106,15 +109,6 @@
 	PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
 } PurpleNotifyUserInfoEntryType;
 
-/**
- * Single column of a search result.
- */
-typedef struct
-{
-	char *title;           /**< Title of the column. */
-	gboolean visible;      /**< Should the column be visible to the user. Defaults to TRUE. */
-
-} PurpleNotifySearchColumn;
 
 
 /**
@@ -277,6 +271,15 @@
 PurpleNotifySearchColumn *purple_notify_searchresults_column_new(const char *title);
 
 /**
+ * Returns the title of the column
+ *
+ * @param column The search column object.
+ *
+ * @return The title of the column
+ */
+const char *purple_notify_searchresult_column_get_title(const PurpleNotifySearchColumn *column);
+
+/**
  * Sets whether or not a search result column is visible.
  *
  * @param column  The search column object.
--- a/libpurple/plugins/autoaccept.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/plugins/autoaccept.c	Fri Dec 23 06:58:52 2011 +0000
@@ -73,10 +73,10 @@
 auto_accept_complete_cb(PurpleXfer *xfer, PurpleXfer *my)
 {
 	if (xfer == my && purple_prefs_get_bool(PREF_NOTIFY) &&
-			!purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who, xfer->account))
+			!purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_xfer_get_remote_user(xfer), purple_xfer_get_account(xfer)))
 	{
 		char *message = g_strdup_printf(_("Autoaccepted file transfer of \"%s\" from \"%s\" completed."),
-					xfer->filename, xfer->who);
+					purple_xfer_get_filename(xfer), purple_xfer_get_remote_user(xfer));
 		purple_notify_info(NULL, _("Autoaccept complete"), message, NULL);
 		g_free(message);
 	}
@@ -93,8 +93,8 @@
 
     int accept_setting;
 
-	account = xfer->account;
-	node = PURPLE_BLIST_NODE(purple_find_buddy(account, xfer->who));
+	account = purple_xfer_get_account(xfer);
+	node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_xfer_get_remote_user(xfer)));
 
 	/* If person is on buddy list, use the buddy setting; otherwise, use the
 	   stranger setting. */
@@ -121,7 +121,7 @@
 				gchar *ext;
 
 				if (purple_prefs_get_bool(PREF_NEWDIR))
-					dirname = g_build_filename(pref, purple_normalize(account, xfer->who), NULL);
+					dirname = g_build_filename(pref, purple_normalize(account, purple_xfer_get_remote_user(xfer)), NULL);
 				else
 					dirname = g_build_filename(pref, NULL);
 
@@ -133,9 +133,9 @@
 
 				/* Escape filename (if escaping is turned on) */
 				if (purple_prefs_get_bool(PREF_ESCAPE)) {
-					escape = purple_escape_filename(xfer->filename);
+					escape = purple_escape_filename(purple_xfer_get_filename(xfer));
 				} else {
-					escape = xfer->filename;
+					escape = purple_xfer_get_filename(xfer);
 				}
 				filename = g_build_filename(dirname, escape, NULL);
 
@@ -174,7 +174,7 @@
 								PURPLE_CALLBACK(auto_accept_complete_cb), xfer);
 			break;
 		case FT_REJECT:
-			xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL;
+			purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
 			break;
 	}
 }
--- a/libpurple/plugins/log_reader.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/plugins/log_reader.c	Fri Dec 23 06:58:52 2011 +0000
@@ -2203,7 +2203,6 @@
 			log->logger = amsn_logger;
 			log->logger_data = data;
 			list = g_list_prepend(list, log);
-			found_start = FALSE;
 
 			purple_debug_info("aMSN logger",
 			                  "Found log for %s:"
--- a/libpurple/plugins/perl/common/Conversation.xs	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/plugins/perl/common/Conversation.xs	Fri Dec 23 06:58:52 2011 +0000
@@ -146,7 +146,7 @@
 	Purple::Conversation conv
 
 Purple::Connection
-purple_conversation_get_gc(conv)
+purple_conversation_get_connection(conv)
 	Purple::Conversation conv
 
 void
--- a/libpurple/plugins/ssl/Makefile.am	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/plugins/ssl/Makefile.am	Fri Dec 23 06:58:52 2011 +0000
@@ -9,30 +9,15 @@
 
 if PLUGINS
 
-# I'm sorry to report that Automake Conditionals don't support
-#   if USE_GNUTLS && USE_NSS
-# but only support testing a single variable. Hence:
-
+plugin_LTLIBRARIES = \
+	ssl.la
 if USE_GNUTLS
-if USE_NSS
-plugin_LTLIBRARIES = \
-	ssl.la           \
-	ssl-gnutls.la    \
-	ssl-nss.la
-else
-plugin_LTLIBRARIES = \
-	ssl.la           \
+plugin_LTLIBRARIES += \
 	ssl-gnutls.la
 endif
-else
 if USE_NSS
-plugin_LTLIBRARIES = \
-	ssl.la           \
+plugin_LTLIBRARIES += \
 	ssl-nss.la
-else
-plugin_LTLIBRARIES = \
-	ssl.la
-endif
 endif
 
 ssl_la_SOURCES        = ssl.c
@@ -56,3 +41,4 @@
 
 ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS)
 ssl_nss_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS)
+
--- a/libpurple/plugins/ssl/ssl-gnutls.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/plugins/ssl/ssl-gnutls.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1142,6 +1142,37 @@
 	return success;
 }
 
+static GByteArray *
+x509_get_der_data(PurpleCertificate *crt)
+{
+	gnutls_x509_crt crt_dat;
+	GByteArray *data;
+	size_t len;
+	int ret;
+
+	crt_dat = X509_GET_GNUTLS_DATA(crt);
+	g_return_val_if_fail(crt_dat, NULL);
+
+	/* Obtain the output size required */
+	len = 0;
+	ret = gnutls_x509_crt_export(crt_dat, GNUTLS_X509_FMT_DER, NULL, &len);
+	g_return_val_if_fail(ret == GNUTLS_E_SHORT_MEMORY_BUFFER, NULL);
+
+	/* Now allocate a buffer and *really* export it */
+	data = g_byte_array_sized_new(len);
+	data->len = len;
+	ret = gnutls_x509_crt_export(crt_dat, GNUTLS_X509_FMT_DER, data->data, &len);
+	if (ret != 0) {
+		purple_debug_error("gnutls/x509",
+		                   "Failed to export cert to buffer with code %d\n",
+		                   ret);
+		g_byte_array_free(data, TRUE);
+		return NULL;
+	}
+
+	return data;
+}
+
 /* X.509 certificate operations provided by this plugin */
 static PurpleCertificateScheme x509_gnutls = {
 	"x509",                          /* Scheme name */
@@ -1158,9 +1189,9 @@
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
 	x509_importcerts_from_file,      /* Multiple certificates import function */
+	x509_get_der_data,               /* Binary DER data */
 
 	NULL,
-	NULL,
 	NULL
 
 };
--- a/libpurple/plugins/ssl/ssl-nss.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/plugins/ssl/ssl-nss.c	Fri Dec 23 06:58:52 2011 +0000
@@ -930,6 +930,29 @@
 	return TRUE;
 }
 
+static GByteArray *
+x509_get_der_data(PurpleCertificate *crt)
+{
+	CERTCertificate *crt_dat;
+	SECItem *dercrt;
+	GByteArray *data;
+
+	crt_dat = X509_NSS_DATA(crt);
+	g_return_val_if_fail(crt_dat, NULL);
+
+	dercrt = SEC_ASN1EncodeItem(NULL, NULL, crt_dat,
+	                            SEC_ASN1_GET(SEC_SignedCertificateTemplate));
+	g_return_val_if_fail(dercrt != NULL, FALSE);
+
+	data = g_byte_array_sized_new(dercrt->len);
+	memcpy(data->data, dercrt->data, dercrt->len);
+	data->len = dercrt->len;
+
+	SECITEM_FreeItem(dercrt, PR_TRUE);
+
+	return data;
+}
+
 static PurpleCertificateScheme x509_nss = {
 	"x509",                          /* Scheme name */
 	N_("X.509 Certificates"),        /* User-visible scheme name */
@@ -945,9 +968,9 @@
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
 	x509_importcerts_from_file,      /* Multiple certificate import function */
+	x509_get_der_data,               /* Binary DER data */
 
 	NULL,
-	NULL,
 	NULL
 };
 
--- a/libpurple/prefs.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/prefs.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1357,6 +1357,7 @@
 	purple_prefs_remove("/purple/conversations/chat/show_leave");
 	purple_prefs_remove("/purple/conversations/combine_chat_im");
 	purple_prefs_remove("/purple/conversations/use_alias_for_title");
+	purple_prefs_remove("/purple/debug/timestamps");
 	purple_prefs_remove("/purple/logging/log_signon_signoff");
 	purple_prefs_remove("/purple/logging/log_idle_state");
 	purple_prefs_remove("/purple/logging/log_away_state");
--- a/libpurple/protocols/bonjour/bonjour.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Fri Dec 23 06:58:52 2011 +0000
@@ -102,7 +102,7 @@
 	}
 #endif /* _WIN32 */
 
-	gc->flags |= PURPLE_CONNECTION_HTML;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML);
 	bd = g_new0(BonjourData, 1);
 	purple_connection_set_protocol_data(gc, bd);
 
@@ -309,7 +309,7 @@
 static void
 bonjour_convo_closed(PurpleConnection *connection, const char *who)
 {
-	PurpleBuddy *buddy = purple_find_buddy(connection->account, who);
+	PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who);
 	BonjourBuddy *bb;
 
 	if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL)
@@ -439,7 +439,7 @@
 static void
 bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group)
 {
-	PurpleBuddy *buddy = purple_find_buddy(connection->account, who);
+	PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who);
 
 	bonjour_do_group_change(buddy, new_group);
 
@@ -464,7 +464,7 @@
 static gboolean
 bonjour_can_receive_file(PurpleConnection *connection, const char *who)
 {
-	PurpleBuddy *buddy = purple_find_buddy(connection->account, who);
+	PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who);
 
 	return (buddy != NULL && purple_buddy_get_protocol_data(buddy) != NULL);
 }
--- a/libpurple/protocols/bonjour/bonjour_ft.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/bonjour/bonjour_ft.c	Fri Dec 23 06:58:52 2011 +0000
@@ -38,7 +38,7 @@
 bonjour_xfer_init(PurpleXfer *xfer);
 static void
 bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from,
-		     const int filesize, const char *filename, int option);
+		     const goffset filesize, const char *filename, int option);
 static void bonjour_free_xfer(PurpleXfer *xfer);
 
 /* Look for specific xfer handle */
@@ -136,8 +136,8 @@
 	 * otherwise there is a RST resulting in an error on the client side */
 	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && purple_xfer_is_completed(xfer)) {
 		struct socket_cleanup *sc = g_new0(struct socket_cleanup, 1);
-		sc->fd = xfer->fd;
-		xfer->fd = -1;
+		sc->fd = purple_xfer_get_fd(xfer);
+		purple_xfer_set_fd(xfer, -1);
 		sc->handle = purple_input_add(sc->fd, PURPLE_INPUT_READ,
 						 _wait_for_socket_close, sc);
 	}
@@ -211,7 +211,7 @@
 	file = xmlnode_new_child(si_node, "file");
 	xmlnode_set_namespace(file, "http://jabber.org/protocol/si/profile/file-transfer");
 	xmlnode_set_attrib(file, "name", purple_xfer_get_filename(xfer));
-	g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
+	g_snprintf(buf, sizeof(buf), "%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer));
 	xmlnode_set_attrib(file, "size", buf);
 
 	feature = xmlnode_new_child(si_node, "feature");
@@ -333,7 +333,7 @@
 		return NULL;
 
 	/* Build the file transfer handle */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
 	xep_xfer = g_new0(XepXfer, 1);
 	purple_xfer_set_protocol_data(xfer, xep_xfer);
 	xep_xfer->data = bd;
@@ -427,77 +427,172 @@
 
 	type = xmlnode_get_attrib(packet, "type");
 	id = xmlnode_get_attrib(packet, "id");
-	if(type) {
-		if(!strcmp(type, "set")) {
-			const char *profile;
-			xmlnode *si;
-			gboolean parsed_receive = FALSE;
+	if(!type)
+		return;
 
-			si = xmlnode_get_child(packet, "si");
+	if(!strcmp(type, "set")) {
+		const char *profile;
+		xmlnode *si;
+		gboolean parsed_receive = FALSE;
 
-			purple_debug_info("bonjour", "si offer Message type - SET.\n");
-			if (si && (profile = xmlnode_get_attrib(si, "profile"))
-					&& !strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) {
-				const char *filename = NULL, *filesize_str = NULL;
-				int filesize = 0;
-				xmlnode *file;
+		si = xmlnode_get_child(packet, "si");
 
-				const char *sid = xmlnode_get_attrib(si, "id");
-
-				if ((file = xmlnode_get_child(si, "file"))) {
-					filename = xmlnode_get_attrib(file, "name");
-					if((filesize_str = xmlnode_get_attrib(file, "size")))
-						filesize = atoi(filesize_str);
-				}
+		purple_debug_info("bonjour", "si offer Message type - SET.\n");
+		if (si && (profile = xmlnode_get_attrib(si, "profile"))
+				&& !strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) {
+			const char *filename = NULL, *filesize_str = NULL;
+			int filesize = 0;
+			xmlnode *file;
 
-				/* TODO: Make sure that it is advertising a bytestreams transfer */
+			const char *sid = xmlnode_get_attrib(si, "id");
 
-				if (filename) {
-					bonjour_xfer_receive(pc, id, sid, name, filesize, filename, XEP_BYTESTREAMS);
-
-					parsed_receive = TRUE;
-				}
+			if ((file = xmlnode_get_child(si, "file"))) {
+				filename = xmlnode_get_attrib(file, "name");
+				if((filesize_str = xmlnode_get_attrib(file, "size")))
+					filesize = atoi(filesize_str);
 			}
 
-			if (!parsed_receive) {
-				BonjourData *bd = purple_connection_get_protocol_data(pc);
+			/* TODO: Make sure that it is advertising a bytestreams transfer */
+
+			if (filename) {
+				bonjour_xfer_receive(pc, id, sid, name, filesize, filename, XEP_BYTESTREAMS);
+
+				parsed_receive = TRUE;
+			}
+		}
+
+		if (!parsed_receive) {
+			BonjourData *bd = purple_connection_get_protocol_data(pc);
+
+			purple_debug_info("bonjour", "rejecting unrecognized si SET offer.\n");
+			xep_ft_si_reject(bd, id, name, "403", "cancel");
+			/*TODO: Send Cancel (501) */
+		}
+	} else if(!strcmp(type, "result")) {
+		purple_debug_info("bonjour", "si offer Message type - RESULT.\n");
 
-				purple_debug_info("bonjour", "rejecting unrecognized si SET offer.\n");
-				xep_ft_si_reject(bd, id, name, "403", "cancel");
-				/*TODO: Send Cancel (501) */
-			}
-		} else if(!strcmp(type, "result")) {
-			purple_debug_info("bonjour", "si offer Message type - RESULT.\n");
+		xfer = bonjour_si_xfer_find(bd, id, name);
+
+		if(xfer == NULL) {
+			BonjourData *bd = purple_connection_get_protocol_data(pc);
+			purple_debug_info("bonjour", "xfer find fail.\n");
+			xep_ft_si_reject(bd, id, name, "403", "cancel");
+		} else
+			bonjour_bytestreams_init(xfer);
 
-			xfer = bonjour_si_xfer_find(bd, id, name);
+	} else if(!strcmp(type, "error")) {
+		purple_debug_info("bonjour", "si offer Message type - ERROR.\n");
+
+		xfer = bonjour_si_xfer_find(bd, id, name);
+
+		if(xfer == NULL)
+			purple_debug_info("bonjour", "xfer find fail.\n");
+		else
+			purple_xfer_cancel_remote(xfer);
+	} else
+		purple_debug_info("bonjour", "si offer Message type - Unknown-%s.\n", type);
+}
 
-			if(xfer == NULL) {
-				BonjourData *bd = purple_connection_get_protocol_data(pc);
-				purple_debug_info("bonjour", "xfer find fail.\n");
-				xep_ft_si_reject(bd, id, name, "403", "cancel");
-			} else
-				bonjour_bytestreams_init(xfer);
+/**
+ * Will compare a host with a buddy_ip.
+ *
+ * Additionally to a common '!strcmp(host, buddy_ip)', it will also return TRUE
+ * if 'host' is a link local IPv6 address without an appended interface
+ * identifier and 'buddy_ip' string is "host" + "%iface".
+ *
+ * Note: This may theoretically result in the attempt to connect to the wrong
+ * host, because we do not know for sure which interface the according link
+ * local IPv6 address might relate to and RFC4862 for instance only ensures the
+ * uniqueness of this address on a given link. So we could possibly have two
+ * distinct buddies with the same ipv6 link local address on two distinct
+ * interfaces. Unfortunately XEP-0065 does not seem to specify how to deal with
+ * link local ip addresses properly...
+ * However, in practice the possiblity for such a conflict is relatively low
+ * (2011 - might be different in the future though?).
+ *
+ * @param host		ipv4 or ipv6 address string
+ * @param buddy_ip	ipv4 or ipv6 address string
+ * @return		TRUE if they match, FALSE otherwise
+ */
+static gboolean
+xep_cmp_addr(const char *host, const char *buddy_ip)
+{
+#if defined(AF_INET6) && defined(HAVE_GETADDRINFO)
+	struct addrinfo hint, *res = NULL;
+	int ret;
 
-		} else if(!strcmp(type, "error")) {
-			purple_debug_info("bonjour", "si offer Message type - ERROR.\n");
+	memset(&hint, 0, sizeof(hint));
+	hint.ai_family = AF_UNSPEC;
+	hint.ai_flags = AI_NUMERICHOST;
+
+	ret = getaddrinfo(host, NULL, &hint, &res);
+	if(ret)
+		goto out;
+
+	if(res->ai_family != AF_INET6 ||
+	   !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
+		freeaddrinfo(res);
+		goto out;
+	}
+	freeaddrinfo(res);
 
-			xfer = bonjour_si_xfer_find(bd, id, name);
+	if(strlen(buddy_ip) <= strlen(host) ||
+	   buddy_ip[strlen(host)] != '%')
+		return FALSE;
+
+	return !strncmp(host, buddy_ip, strlen(host));
+
+out:
+#endif
+	return !strcmp(host, buddy_ip);
+}
+
+static gboolean
+__xep_bytestreams_parse(PurpleBuddy *pb, PurpleXfer *xfer, xmlnode *query,
+			const char *iq_id)
+{
+	const char *jid, *host, *port;
+	int portnum;
+	xmlnode *streamhost;
+	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
+
+	for(streamhost = xmlnode_get_child(query, "streamhost");
+			streamhost;
+			streamhost = xmlnode_get_next_twin(streamhost)) {
 
-			if(xfer == NULL)
-				purple_debug_info("bonjour", "xfer find fail.\n");
-			else
-				purple_xfer_cancel_remote(xfer);
-		} else
-			purple_debug_info("bonjour", "si offer Message type - Unknown-%s.\n", type);
+		if(!(jid = xmlnode_get_attrib(streamhost, "jid")) ||
+		   !(host = xmlnode_get_attrib(streamhost, "host")) ||
+		   !(port = xmlnode_get_attrib(streamhost, "port")) ||
+		   !(portnum = atoi(port))) {
+			purple_debug_info("bonjour", "bytestream offer Message parse error.\n");
+			continue;
+		}
+
+		if(!xep_cmp_addr(host, xf->buddy_ip))
+			continue;
+
+		g_free(xf->iq_id);
+		xf->iq_id = g_strdup(iq_id);
+		xf->jid = g_strdup(jid);
+		xf->proxy_host = g_strdup(xf->buddy_ip);
+		xf->proxy_port = portnum;
+		purple_debug_info("bonjour", "bytestream offer parse"
+				  "jid=%s host=%s port=%d.\n", jid, host, portnum);
+		bonjour_bytestreams_connect(xfer, pb);
+		return TRUE;
 	}
+
+	return FALSE;
 }
 
+
 void
 xep_bytestreams_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb)
 {
-	const char *type, *from;
+	const char *type, *from, *iq_id, *sid;
 	xmlnode *query;
 	BonjourData *bd;
+	PurpleXfer *xfer;
 
 	g_return_if_fail(pc != NULL);
 	g_return_if_fail(packet != NULL);
@@ -512,71 +607,32 @@
 	type = xmlnode_get_attrib(packet, "type");
 	from = purple_buddy_get_name(pb);
 	query = xmlnode_get_child(packet,"query");
-	if(type) {
-		if(!strcmp(type, "set")) {
-			const char *iq_id, *sid;
-			gboolean found = FALSE;
-			PurpleXfer *xfer;
-
-			purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");
-
-			iq_id = xmlnode_get_attrib(packet, "id");
-
-			sid = xmlnode_get_attrib(query, "sid");
-			xfer = bonjour_si_xfer_find(bd, sid, from);
+	if(!type)
+		return;
 
-			if(xfer) {
-				const char *jid, *host, *port;
-				xmlnode *streamhost;
-				int portnum;
-				XepXfer *xf = NULL;
+	if(strcmp(type, "set")) {
+		purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
+		return;
+	}
 
-				xf = purple_xfer_get_protocol_data(xfer);
-				for(streamhost = xmlnode_get_child(query, "streamhost");
-						streamhost;
-						streamhost = xmlnode_get_next_twin(streamhost)) {
-
-					if((jid = xmlnode_get_attrib(streamhost, "jid")) &&
-					   (host = xmlnode_get_attrib(streamhost, "host")) &&
-					   (port = xmlnode_get_attrib(streamhost, "port")) &&
-					   (portnum = atoi(port))) {
+	purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");
 
-						if(!strcmp(host, xf->buddy_ip)) {
-							g_free(xf->iq_id);
-							xf->iq_id = g_strdup(iq_id);
-							xf->jid = g_strdup(jid);
-							xf->proxy_host = g_strdup(host);
-							xf->proxy_port = portnum;
-							purple_debug_info("bonjour", "bytestream offer parse"
-									  "jid=%s host=%s port=%d.\n", jid, host, portnum);
-							bonjour_bytestreams_connect(xfer, pb);
-							found = TRUE;
-							break;
-						}
-					} else {
-						purple_debug_info("bonjour", "bytestream offer Message parse error.\n");
-					}
-				}
-			} else {
+	iq_id = xmlnode_get_attrib(packet, "id");
 
-			}
-
-			if (!found) {
-				purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
+	sid = xmlnode_get_attrib(query, "sid");
+	xfer = bonjour_si_xfer_find(bd, sid, from);
+	if(xfer && __xep_bytestreams_parse(pb, xfer, query, iq_id))
+		return; /* success */
 
-				if (iq_id && xfer != NULL)
-					xep_ft_si_reject(bd, iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
-			}
+	purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
 
-		} else {
-			purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
-		}
-	}
+	if (iq_id && xfer != NULL)
+		xep_ft_si_reject(bd, iq_id, xfer->who, "404", "cancel");
 }
 
 static void
 bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from,
-		     const int filesize, const char *filename, int option)
+		     const goffset filesize, const char *filename, int option)
 {
 	PurpleXfer *xfer;
 	XepXfer *xf;
@@ -592,7 +648,7 @@
 	purple_debug_info("bonjour", "bonjour-xfer-receive.\n");
 
 	/* Build the file transfer handle */
-	xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from);
+	xfer = purple_xfer_new(purple_connection_get_account(pc), PURPLE_XFER_RECEIVE, from);
 	xf = g_new0(XepXfer, 1);
 	purple_xfer_set_protocol_data(xfer, xf);
 	xf->data = bd;
@@ -648,16 +704,16 @@
 			fcntl(acceptfd, F_SETFD, FD_CLOEXEC);
 #endif
 
-			purple_input_remove(xfer->watcher);
+			purple_input_remove(purple_xfer_get_watcher(xfer));
 			close(source);
-			xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ,
-							 bonjour_sock5_request_cb, xfer);
+			purple_xfer_set_watcher(xfer, purple_input_add(acceptfd, PURPLE_INPUT_READ,
+							 bonjour_sock5_request_cb, xfer));
 			xf->sock5_req_state++;
 			xf->rxlen = 0;
 		}
 		break;
 	case 0x01:
-		xfer->fd = source;
+		purple_xfer_set_fd(xfer, source);
 		len = read(source, xf->rx_buf + xf->rxlen, 3);
 		if(len < 0 && errno == EAGAIN)
 			return;
@@ -665,9 +721,9 @@
 			purple_xfer_cancel_remote(xfer);
 			return;
 		} else {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-							 bonjour_sock5_request_cb, xfer);
+			purple_input_remove(purple_xfer_get_watcher(xfer));
+			purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
+							 bonjour_sock5_request_cb, xfer));
 			xf->sock5_req_state++;
 			xf->rxlen = 0;
 			bonjour_sock5_request_cb(xfer, source, PURPLE_INPUT_WRITE);
@@ -684,9 +740,9 @@
 			purple_xfer_cancel_remote(xfer);
 			return;
 		} else {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ,
-							 bonjour_sock5_request_cb, xfer);
+			purple_input_remove(purple_xfer_get_watcher(xfer));
+			purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_READ,
+							 bonjour_sock5_request_cb, xfer));
 			xf->sock5_req_state++;
 			xf->rxlen = 0;
 		}
@@ -695,9 +751,9 @@
 		len = read(source, xf->rx_buf + xf->rxlen, 20);
 		if(len<=0){
 		} else {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-							 bonjour_sock5_request_cb, xfer);
+			purple_input_remove(purple_xfer_get_watcher(xfer));
+			purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
+							 bonjour_sock5_request_cb, xfer));
 			xf->sock5_req_state++;
 			xf->rxlen = 0;
 			bonjour_sock5_request_cb(xfer, source, PURPLE_INPUT_WRITE);
@@ -720,8 +776,8 @@
 			purple_xfer_cancel_remote(xfer);
 			return;
 		} else {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
+			purple_input_remove(purple_xfer_get_watcher(xfer));
+			purple_xfer_set_watcher(xfer, 0);
 			xf->rxlen = 0;
 			/*close(source);*/
 			purple_xfer_start(xfer, source, NULL, -1);
@@ -750,8 +806,8 @@
 		return;
 	}
 
-	xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ,
-					 bonjour_sock5_request_cb, xfer);
+	purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ,
+					 bonjour_sock5_request_cb, xfer));
 	xf = purple_xfer_get_protocol_data(xfer);
 	xf->listen_data = NULL;
 
@@ -764,7 +820,7 @@
 	xmlnode_set_attrib(query, "sid", xf->sid);
 	xmlnode_set_attrib(query, "mode", "tcp");
 
-	xfer->local_port = purple_network_get_port_from_fd(sock);
+	purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock));
 
 	local_ips = bonjour_jabber_get_local_ips(sock);
 
--- a/libpurple/protocols/bonjour/jabber.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Fri Dec 23 06:58:52 2011 +0000
@@ -206,7 +206,9 @@
 						g_string_append_printf(str, " face='%s'", font_face);
 					if (font_size)
 						g_string_append_printf(str, " size='%s'", font_size);
-					if (ichat_text_color)
+					if (font_color)
+						g_string_append_printf(str, " color='%s'", font_color);
+					else if (ichat_text_color)
 						g_string_append_printf(str, " color='%s'", ichat_text_color);
 					if (ichat_balloon_color)
 						g_string_append_printf(str, " back='%s'", ichat_balloon_color);
@@ -665,9 +667,13 @@
 
 	/* Look for the buddy that has opened the conversation and fill information */
 #ifdef HAVE_INET_NTOP
-	if (their_addr.ss_family == AF_INET6)
+	if (their_addr.ss_family == AF_INET6) {
 		address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in6 *)&their_addr)->sin6_addr,
 			addrstr, sizeof(addrstr));
+
+		append_iface_if_linklocal(addrstr,
+			((struct sockaddr_in6 *)&their_addr)->sin6_scope_id);
+	}
 	else
 		address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in *)&their_addr)->sin_addr,
 			addrstr, sizeof(addrstr));
@@ -1164,7 +1170,7 @@
 				tmp_next = xfers->next;
 				/* We only need to cancel this if it hasn't actually started transferring. */
 				/* This will change if we ever support IBB transfers. */
-				if (strcmp(xfer->who, purple_buddy_get_name(bconv->pb)) == 0
+				if (strcmp(purple_xfer_get_remote_user(xfer), purple_buddy_get_name(bconv->pb)) == 0
 						&& (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_NOT_STARTED
 							|| purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_UNKNOWN)) {
 					purple_xfer_cancel_remote(xfer);
@@ -1449,3 +1455,19 @@
 
 	return ips;
 }
+
+void
+append_iface_if_linklocal(char *ip, guint32 interface_param) {
+	struct in6_addr in6_addr;
+	int len_remain = INET6_ADDRSTRLEN - strlen(ip);
+
+	if (len_remain <= 1)
+		return;
+
+	if (inet_pton(AF_INET6, ip, &in6_addr) != 1 ||
+	    !IN6_IS_ADDR_LINKLOCAL(&in6_addr))
+		return;
+
+	snprintf(ip + strlen(ip), len_remain, "%%%d",
+		 interface_param);
+}
--- a/libpurple/protocols/bonjour/jabber.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/bonjour/jabber.h	Fri Dec 23 06:58:52 2011 +0000
@@ -111,4 +111,6 @@
 int xep_iq_send_and_free(XepIq *iq);
 GSList * bonjour_jabber_get_local_ips(int fd);
 
+void append_iface_if_linklocal(char *ip, guint32 interface_param);
+
 #endif /* _BONJOUR_JABBER_H_ */
--- a/libpurple/protocols/bonjour/mdns_avahi.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Fri Dec 23 06:58:52 2011 +0000
@@ -179,6 +179,9 @@
 			ip[0] = '\0';
 			avahi_address_snprint(ip, AVAHI_ADDRESS_STR_MAX, a);
 
+			if (protocol == AVAHI_PROTO_INET6)
+				append_iface_if_linklocal(ip, interface);
+
 			purple_debug_info("bonjour", "_resolve_callback - name:%s ip:%s prev_ip:%s\n",
 				name, ip, rd->ip);
 
@@ -190,7 +193,7 @@
 				}
 				/* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */
 				if (protocol == AVAHI_PROTO_INET6) {
-					rd->ip = g_strdup_printf("%s%%%d", ip, interface);
+					rd->ip = g_strdup_printf("%s", ip);
 					bb->ips = g_slist_prepend(bb->ips, (gchar *) rd->ip);
 				} else {
 					rd->ip = g_strdup(ip);
--- a/libpurple/protocols/gg/Makefile.am	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/Makefile.am	Fri Dec 23 06:58:52 2011 +0000
@@ -1,5 +1,7 @@
 EXTRA_DIST = \
 	Makefile.mingw \
+	win32-resolver.c \
+	win32-resolver.h \
 	lib/common.c \
 	lib/compat.h \
 	lib/COPYING \
--- a/libpurple/protocols/gg/Makefile.mingw	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/Makefile.mingw	Fri Dec 23 06:58:52 2011 +0000
@@ -60,7 +60,8 @@
 	confer.c \
 	gg.c \
 	search.c \
-	gg-utils.c
+	gg-utils.c \
+	win32-resolver.c
 
 OBJECTS = $(C_SRC:%.c=%.o)
 
--- a/libpurple/protocols/gg/gg-utils.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/gg-utils.c	Fri Dec 23 06:58:52 2011 +0000
@@ -143,5 +143,18 @@
 				    msg ? "message" : NULL, msg, NULL);
 }
 
+guint ggp_http_input_add(struct gg_http *http_req, PurpleInputFunction func,
+	gpointer user_data)
+{
+	PurpleInputCondition cond = 0;
+	int check = http_req->check;
+
+	if (check & GG_CHECK_READ)
+		cond |= PURPLE_INPUT_READ;
+	if (check & GG_CHECK_WRITE)
+		cond |= PURPLE_INPUT_WRITE;
+
+	return purple_input_add(http_req->fd, cond, func, user_data);
+}
 
 /* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/gg-utils.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/gg-utils.h	Fri Dec 23 06:58:52 2011 +0000
@@ -101,6 +101,21 @@
 ggp_status_fake_to_self(PurpleAccount *account);
 
 
+/**
+ * Adds an input handler in purple event loop for http request.
+ *
+ * @see purple_input_add
+ *
+ * @param http_req  Http connection to watch.
+ * @param func      The callback function for data.
+ * @param user_data User-specified data.
+ *
+ * @return The resulting handle (will be greater than 0).
+ */
+guint
+ggp_http_input_add(struct gg_http *http_req, PurpleInputFunction func,
+	gpointer user_data);
+
 #endif /* _PURPLE_GG_UTILS_H */
 
 /* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/gg.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/gg.c	Fri Dec 23 06:58:52 2011 +0000
@@ -39,14 +39,16 @@
 #include "request.h"
 #include "xmlnode.h"
 
-#include <libgadu.h>
-
 #include "gg.h"
 #include "confer.h"
 #include "search.h"
 #include "buddylist.h"
 #include "gg-utils.h"
 
+#ifdef _WIN32
+#  include "win32-resolver.h"
+#endif
+
 static PurplePlugin *my_protocol = NULL;
 
 /* Prototypes */
@@ -389,8 +391,8 @@
 	purple_notify_info(NULL, _("New Gadu-Gadu Account Registered"),
 			 _("Registration completed successfully!"), NULL);
 
-	if(account->registration_cb)
-		(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+	purple_account_register_completed(account, TRUE);
+
 	/* TODO: the currently open Accounts Window will not be updated withthe
 	 * new username and etc, we need to somehow have it refresh at this
 	 * point
@@ -400,8 +402,7 @@
 	purple_account_disconnect(account);
 
 exit_err:
-	if(account->registration_cb)
-		(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+	purple_account_register_completed(account, FALSE);
 
 	gg_register_free(h);
 	g_free(email);
@@ -418,7 +419,7 @@
 	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPToken *token = info->token;
 
-	purple_account_disconnect(gc->account);
+	purple_account_disconnect(purple_connection_get_account(gc));
 
 	g_free(token->id);
 	g_free(token->data);
@@ -616,75 +617,137 @@
 		gc);
 }
 
-/* ----- CHANGE PASSWORD ------------------------------------------------ */
-
-static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields)
+/* ----- CHANGE PASSWORD ---------------------------------------------------- */
+
+typedef struct
+{
+	guint inpa;
+	struct gg_http *http_req;
+	gchar *new_password;
+	PurpleAccount *account;
+} ggp_change_passwd_request;
+
+static void ggp_callback_change_passwd_handler(gpointer _req, gint fd,
+	PurpleInputCondition cond)
+{
+	ggp_change_passwd_request *req = _req;
+	const char *messagesTitle =
+		_("Change password for the Gadu-Gadu account");
+
+	purple_input_remove(req->inpa);
+
+	if (gg_change_passwd_watch_fd(req->http_req) == -1 ||
+		req->http_req->state == GG_STATE_ERROR)
+		goto exit_error;
+
+	if (req->http_req->state != GG_STATE_DONE)
+	{
+		req->inpa = ggp_http_input_add(req->http_req,
+			ggp_callback_change_passwd_handler, req);
+		return;
+	}
+
+	if (req->http_req->data != NULL &&
+		((struct gg_pubdir*)req->http_req->data)->success == 1)
+	{
+		purple_account_set_password(req->account, req->new_password);
+		purple_notify_info(req->account, messagesTitle,
+			_("Password was changed successfully!"), NULL);
+		goto exit_cleanup;
+	}
+
+exit_error:
+	purple_notify_error(req->account, messagesTitle,
+		_("Unable to change password. Error occurred.\n"), NULL);
+
+exit_cleanup:
+	gg_change_passwd_free(req->http_req);
+	g_free(req->new_password);
+	g_free(req);
+}
+
+static void ggp_callback_change_passwd_ok(PurpleConnection *gc,
+	PurpleRequestFields *fields)
 {
 	PurpleAccount *account;
 	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	struct gg_http *h;
-	gchar *cur, *p1, *p2, *t;
-
-	cur = charset_convert(
-			purple_request_fields_get_string(fields, "password_cur"),
-			"UTF-8", "CP1250");
-	p1  = charset_convert(
-			purple_request_fields_get_string(fields, "password1"),
-			"UTF-8", "CP1250");
-	p2  = charset_convert(
-			purple_request_fields_get_string(fields, "password2"),
-			"UTF-8", "CP1250");
-	t   = charset_convert(
-			purple_request_fields_get_string(fields, "token"),
-			"UTF-8", "CP1250");
+	gchar *cur, *p1, *p2, *t, *mail;
+	const char *messagesTitle =
+		_("Change password for the Gadu-Gadu account");
+
+	cur = g_strdup(purple_request_fields_get_string(fields,
+		"password_cur"));
+	p1 = g_strdup(purple_request_fields_get_string(fields, "password1"));
+	p2 = g_strdup(purple_request_fields_get_string(fields, "password2"));
+	t = g_strdup(purple_request_fields_get_string(fields, "token"));
+	mail = g_strdup(purple_request_fields_get_string(fields, "email"));
 
 	account = purple_connection_get_account(gc);
 
 	if (cur == NULL || p1 == NULL || p2 == NULL || t == NULL ||
-	    *cur == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
-		purple_notify_error(account, NULL, _("Fill in the fields."), NULL);
+		mail == NULL || *cur == '\0' || *p1 == '\0' || *p2 == '\0' ||
+		*t == '\0' || *mail == '\0') {
+		purple_notify_error(account, messagesTitle,
+			_("Fill in the fields."), NULL);
 		goto exit_err;
 	}
 
 	if (g_utf8_collate(p1, p2) != 0) {
-		purple_notify_error(account, NULL,
-				  _("New passwords do not match."), NULL);
+		purple_notify_error(account, messagesTitle,
+			_("New passwords do not match."), NULL);
+		goto exit_err;
+	}
+
+	if (strlen(p1) > 15) {
+		purple_notify_error(account, messagesTitle,
+			_("New password should be at most 15 characters long."),
+			NULL);
 		goto exit_err;
 	}
 
 	if (g_utf8_collate(cur, purple_account_get_password(account)) != 0) {
-		purple_notify_error(account, NULL,
-			_("Your current password is different from the one that you specified."),
-			NULL);
+		purple_notify_error(account, messagesTitle,
+			_("Your current password is different from the one that"
+			" you specified."), NULL);
+		goto exit_err;
+	}
+
+	if (!purple_email_is_valid(mail)) {
+		purple_notify_error(account, messagesTitle,
+			_("Invalid email address"), NULL);
 		goto exit_err;
 	}
 
-	purple_debug_info("gg", "Changing password\n");
-
-	/* XXX: this email should be a pref... */
-	h = gg_change_passwd4(ggp_get_uin(account),
-			      "user@example.net", purple_account_get_password(account),
-			      p1, info->token->id, t, 0);
-
-	if (h == NULL) {
-		purple_notify_error(account, NULL,
+	purple_debug_info("gg", "Changing password with email \"%s\"...\n",
+		mail);
+
+	h = gg_change_passwd4(ggp_get_uin(account), mail,
+		purple_account_get_password(account), p1, info->token->id, t,
+		1);
+
+	if (h == NULL)
+		purple_notify_error(account, messagesTitle,
 			_("Unable to change password. Error occurred.\n"),
 			NULL);
-		goto exit_err;
+	else
+	{
+		ggp_change_passwd_request *req =
+			g_new(ggp_change_passwd_request, 1);
+		req->http_req = h;
+		req->new_password = g_strdup(p1);
+		req->account = account;
+		
+		req->inpa = ggp_http_input_add(h,
+			ggp_callback_change_passwd_handler, req);
 	}
-
-	purple_account_set_password(account, p1);
-
-	gg_change_passwd_free(h);
-
-	purple_notify_info(account, _("Change password for the Gadu-Gadu account"),
-			 _("Password was changed successfully!"), NULL);
-
+	
 exit_err:
 	g_free(cur);
 	g_free(p1);
 	g_free(p2);
 	g_free(t);
+	g_free(mail);
 	g_free(info->token->id);
 	g_free(info->token->data);
 	g_free(info->token);
@@ -701,7 +764,6 @@
 
 	char *msg;
 
-
 	fields = purple_request_fields_new();
 	group = purple_request_field_group_new(NULL);
 	purple_request_fields_add_group(fields, group);
@@ -721,6 +783,11 @@
 	purple_request_field_string_set_masked(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
+	field = purple_request_field_string_new("email",
+			_("Email Address"), "", FALSE);
+	purple_request_field_string_set_masked(field, FALSE);
+	purple_request_field_group_add_field(group, field);
+
 	field = purple_request_field_string_new("token",
 			_("Enter current token"), "", FALSE);
 	purple_request_field_string_set_masked(field, FALSE);
@@ -732,8 +799,8 @@
 	purple_request_field_group_add_field(group, field);
 
 	msg = g_strdup_printf("%s %d",
-		_("Please, enter your current password and your new password for UIN: "),
-		ggp_get_uin(purple_connection_get_account(gc)));
+		_("Please, enter your current password and your new password "
+		"for UIN: "), ggp_get_uin(purple_connection_get_account(gc)));
 
 	purple_request_fields(gc,
 		_("Change Gadu-Gadu Password"),
@@ -1024,6 +1091,7 @@
 
 				purple_debug_info("gg", "gg_get_avatar_url_cb: "
 					"requesting avatar for %s\n", uin);
+				/* FIXME: This should be cancelled somewhere if not needed. */
 				url_data = purple_util_fetch_url_request(account,
 						bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)",
 						FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data);
@@ -1052,6 +1120,7 @@
 
 	avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin);
 
+	/* FIXME: This should be cancelled somewhere if not needed. */
 	url_data = purple_util_fetch_url_request(
 			purple_connection_get_account(gc), avatarurl, TRUE,
 			"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
@@ -1086,7 +1155,7 @@
 			break;
 		case GG_STATUS_FFC:
 		case GG_STATUS_FFC_DESCR:
-			st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
+			st = "freeforchat";
 			break;
 		case GG_STATUS_AVAIL:
 		case GG_STATUS_AVAIL_DESCR:
@@ -1096,6 +1165,10 @@
 		case GG_STATUS_BUSY_DESCR:
 			st = purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY);
 			break;
+		case GG_STATUS_INVISIBLE:
+		case GG_STATUS_INVISIBLE_DESCR:
+			st = purple_primitive_get_id_from_type(PURPLE_STATUS_INVISIBLE);
+			break;
 		case GG_STATUS_DND:
 		case GG_STATUS_DND_DESCR:
 			st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE);
@@ -1444,6 +1517,7 @@
 	gchar *from;
 	gchar *msg;
 	gchar *tmp;
+	time_t mtime;
 
 	if (ev->event.msg.message == NULL)
 	{
@@ -1572,8 +1646,13 @@
 			from, msg, ev->event.msg.msgclass,
 			ev->event.msg.recipients_count);
 
+	if (ev->event.msg.msgclass & GG_CLASS_QUEUED)
+		mtime = ev->event.msg.time;
+	else
+		mtime = time(NULL);
+
 	if (ev->event.msg.recipients_count == 0) {
-		serv_got_im(gc, from, msg, 0, ev->event.msg.time);
+		serv_got_im(gc, from, msg, 0, mtime);
 	} else {
 		const char *chat_name;
 		int chat_id;
@@ -1599,7 +1678,7 @@
 
 		buddy_name = ggp_buddy_get_name(gc, ev->event.msg.sender);
 		serv_got_chat_in(gc, chat_id, buddy_name,
-				 PURPLE_MESSAGE_RECV, msg, ev->event.msg.time);
+				 PURPLE_MESSAGE_RECV, msg, mtime);
 		g_free(buddy_name);
 	}
 	g_free(msg);
@@ -1896,11 +1975,12 @@
 	purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
 			info->session->check, info->session->state);
 
-	purple_input_remove(gc->inpa);
+	purple_input_remove(info->inpa);
+	info->inpa = 0;
 
 	/** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */
 	if (info->session->fd >= 0)
-		gc->inpa = purple_input_add(info->session->fd,
+		info->inpa = purple_input_add(info->session->fd,
 			(info->session->check == 1) ? PURPLE_INPUT_WRITE :
 				PURPLE_INPUT_READ,
 			ggp_async_login_handler, gc);
@@ -1913,8 +1993,8 @@
 		case GG_EVENT_CONN_SUCCESS:
 			{
 				purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n");
-				purple_input_remove(gc->inpa);
-				gc->inpa = purple_input_add(info->session->fd,
+				purple_input_remove(info->inpa);
+				info->inpa = purple_input_add(info->session->fd,
 							  PURPLE_INPUT_READ,
 							  ggp_callback_recv, gc);
 
@@ -1924,17 +2004,69 @@
 			}
 			break;
 		case GG_EVENT_CONN_FAILED:
-			purple_input_remove(gc->inpa);
-			gc->inpa = 0;
-			purple_connection_error (gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Connection failed"));
+			purple_input_remove(info->inpa);
+			info->inpa = 0;
+			purple_debug_info("gg", "Connection failure: %d\n",
+				ev->event.failure);
+			switch (ev->event.failure) {
+				case GG_FAILURE_RESOLVING:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Unable to resolve "
+						"hostname"));
+					break;
+				case GG_FAILURE_PASSWORD:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+						_("Incorrect password"));
+					break;
+				case GG_FAILURE_TLS:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
+						_("SSL Connection Failed"));
+					break;
+				case GG_FAILURE_INTRUDER:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+						_("Your account has been "
+						"disabled because too many "
+						"incorrect passwords were "
+						"entered"));
+					break;
+				case GG_FAILURE_UNAVAILABLE:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Service temporarily "
+						"unavailable"));
+					break;
+				case GG_FAILURE_PROXY:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Error connecting to proxy "
+						"server"));
+					break;
+				case GG_FAILURE_HUB:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Error connecting to master "
+						"server"));
+					break;
+				default:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Connection failed"));
+			}
 			break;
 		case GG_EVENT_MSG:
 			if (ev->event.msg.sender == 0)
+			{
+				if (ev->event.msg.message == NULL)
+					break;
+
 				/* system messages are mostly ads */
 				purple_debug_info("gg", "System message:\n%s\n",
 					ev->event.msg.message);
+			}
 			else
 				purple_debug_warning("gg", "GG_EVENT_MSG: message from user %u "
 					"unexpected while connecting:\n%s\n",
@@ -1958,6 +2090,19 @@
 	return "gadu-gadu";
 }
 
+static const char *ggp_normalize(const PurpleAccount *account, const char *who)
+{
+	static char normalized[21]; /* maximum unsigned long long int size */
+
+	uin_t uin = ggp_str_to_uin(who);
+	if (uin <= 0)
+		return NULL;
+
+	g_snprintf(normalized, sizeof(normalized), "%u", uin);
+
+	return normalized;
+}
+
 static char *ggp_status_text(PurpleBuddy *b)
 {
 	PurpleStatus *status;
@@ -2013,50 +2158,60 @@
 	PurpleStatusType *type;
 	GList *types = NULL;
 
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	/*
-	 * Without this selecting Invisible as own status doesn't
-	 * work. It's not used and not needed to show status of buddies.
+	 * New status for GG 8.0: PoGGadaj ze mna (chatty).
+	 * NOTE: at this time, this is used only to set our own status.
 	 */
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+		"freeforchat", _("Chatty"), TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	/*
-	 * New statuses for GG 8.0 like PoGGadaj ze mna (not yet because
-	 * libpurple can't support Chatty status) and Nie przeszkadzac
+	 * New status for GG 8.0: Nie przeszkadzac (do not disturb).
 	 */
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
+	types = g_list_append(types, type);
+
+	/*
+	 * It's used on buddy list if and only if it's showing our own
+	 * (invisible) status.
+	 */
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	/*
 	 * This status is necessary to display guys who are blocking *us*.
 	 */
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_INVISIBLE, "blocked", _("Blocked"), TRUE, FALSE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
+		"blocked", _("Blocked"), TRUE, FALSE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	return types;
@@ -2130,8 +2285,22 @@
 	purple_connection_set_protocol_data(gc, info);
 
 	glp->uin = ggp_get_uin(account);
-	glp->password = (char *)purple_account_get_password(account);
+	glp->password = charset_convert(purple_account_get_password(account),
+		"UTF-8", "CP1250");
+
+	if (glp->uin == 0) {
+		purple_connection_error(gc,
+			PURPLE_CONNECTION_ERROR_INVALID_USERNAME,
+			_("The username specified is invalid."));
+		g_free(glp);
+		return;
+	}
+
 	glp->image_size = 255;
+	glp->status_flags = GG_STATUS_FLAG_UNKNOWN;
+
+	if (purple_account_get_bool(account, "show_links_from_strangers", 1))
+		glp->status_flags |= GG_STATUS_FLAG_SPAM;
 
 	presence = purple_account_get_presence(account);
 	status = purple_presence_get_active_status(presence);
@@ -2143,13 +2312,26 @@
 	glp->async = 1;
 	glp->status = ggp_to_gg_status(status, &glp->status_descr);
 	
-	encryption_type = purple_account_get_string(account, "encryption", "none");
-	purple_debug_info("gg", "Requested encryption type: %s\n", encryption_type);
+	encryption_type = purple_account_get_string(account, "encryption",
+		"opportunistic_tls");
+	purple_debug_info("gg", "Requested encryption type: %s\n",
+		encryption_type);
 	if (strcmp(encryption_type, "opportunistic_tls") == 0)
-		glp->tls = 1;
-	else
-		glp->tls = 0;
-	purple_debug_info("gg", "TLS enabled: %d\n", glp->tls);
+		glp->tls = GG_SSL_ENABLED;
+	else if (strcmp(encryption_type, "require_tls") == 0) {
+		if (gg_libgadu_check_feature(GG_LIBGADU_FEATURE_SSL))
+			glp->tls = GG_SSL_REQUIRED;
+		else {
+			purple_connection_error(gc,
+				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+				_("SSL support unavailable"));
+			g_free(glp);
+			return;
+		}
+	}
+	else /* encryption_type == "none" */
+		glp->tls = GG_SSL_DISABLED;
+	purple_debug_info("gg", "TLS mode: %d\n", glp->tls);
 
 	if (!info->status_broadcasting)
 		glp->status = glp->status|GG_STATUS_FRIENDS_MASK;
@@ -2185,7 +2367,7 @@
 		g_free(glp);
 		return;
 	}
-	gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ,
+	info->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ,
 				  ggp_async_login_handler, gc);
 }
 
@@ -2221,13 +2403,14 @@
 		ggp_search_destroy(info->searches);
 		g_list_free(info->pending_richtext_messages);
 		g_hash_table_destroy(info->pending_images);
+
+		if (info->inpa > 0)
+			purple_input_remove(info->inpa);
+
+		purple_connection_set_protocol_data(gc, NULL);
 		g_free(info);
-		purple_connection_set_protocol_data(gc, NULL);
 	}
 
-	if (gc->inpa > 0)
-		purple_input_remove(gc->inpa);
-
 	purple_debug_info("gg", "Connection closed.\n");
 }
 
@@ -2401,6 +2584,9 @@
 	if (strcmp(status_id, "available") == 0) {
 		new_status = GG_STATUS_AVAIL;
 		new_status_descr = GG_STATUS_AVAIL_DESCR;
+	} else if (strcmp(status_id, "freeforchat") == 0) {
+		new_status = GG_STATUS_FFC;
+		new_status_descr = GG_STATUS_FFC_DESCR;
 	} else if (strcmp(status_id, "away") == 0) {
 		new_status = GG_STATUS_BUSY;
 		new_status_descr = GG_STATUS_BUSY_DESCR;
@@ -2609,14 +2795,16 @@
 	GList *m = NULL;
 	PurplePluginAction *act;
 
+	act = purple_plugin_action_new(_("Change password..."),
+				     ggp_change_passwd);
+	m = g_list_append(m, act);
+
 	act = purple_plugin_action_new(_("Find buddies..."),
 				     ggp_find_buddies);
 	m = g_list_append(m, act);
 
-	m = g_list_append(m, NULL);
-
-	act = purple_plugin_action_new(_("Change password..."),
-				     ggp_change_passwd);
+	act = purple_plugin_action_new(_("Change status broadcasting"),
+				     ggp_action_change_status_broadcasting);
 	m = g_list_append(m, act);
 
 	m = g_list_append(m, NULL);
@@ -2641,10 +2829,6 @@
 				     ggp_action_buddylist_load);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Change status broadcasting"),
-				     ggp_action_change_status_broadcasting);
-	m = g_list_append(m, act);
-	
 	return m;
 }
 
@@ -2701,7 +2885,7 @@
 	NULL,				/* rename_group */
 	NULL,				/* buddy_free */
 	NULL,				/* convo_closed */
-	NULL,				/* normalize */
+	ggp_normalize,			/* normalize */
 	NULL,				/* set_buddy_icon */
 	NULL,				/* remove_group */
 	NULL,				/* get_cb_real_name */
@@ -2791,11 +2975,6 @@
 	PurpleAccountOption *option;
 	GList *encryption_options = NULL;
 
-	option = purple_account_option_string_new(_("Nickname"),
-			"nick", _("Gadu-Gadu User"));
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-						   option);
-
 	option = purple_account_option_string_new(_("GG server"),
 			"gg_server", "");
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
@@ -2808,22 +2987,29 @@
 	list = g_list_append(list, kvp); \
 }
 
-	ADD_VALUE(encryption_options, _("Don't use encryption"), "none");
 	ADD_VALUE(encryption_options, _("Use encryption if available"),
 		"opportunistic_tls");
-#if 0
-	/* TODO */
 	ADD_VALUE(encryption_options, _("Require encryption"), "require_tls");
-#endif
+	ADD_VALUE(encryption_options, _("Don't use encryption"), "none");
 
 	option = purple_account_option_list_new(_("Connection security"),
 		"encryption", encryption_options);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 		option);
 
+	option = purple_account_option_bool_new(_("Show links from strangers"),
+		"show_links_from_strangers", 1);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+		option);
+
 	my_protocol = plugin;
 
 	gg_debug_handler = purple_gg_debug_handler;
+	
+#ifdef _WIN32
+	gg_global_set_custom_resolver(ggp_resolver_win32thread_start,
+		ggp_resolver_win32thread_cleanup);
+#endif
 }
 
 PURPLE_INIT_PLUGIN(gg, init_plugin, info);
--- a/libpurple/protocols/gg/gg.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/gg.h	Fri Dec 23 06:58:52 2011 +0000
@@ -24,6 +24,7 @@
 #ifndef _PURPLE_GG_H
 #define _PURPLE_GG_H
 
+#undef printf
 #include <libgadu.h>
 #include "internal.h"
 #include "search.h"
@@ -58,6 +59,7 @@
 typedef struct {
 
 	struct gg_session *session;
+	guint inpa;
 	GGPToken *token;
 	GList *chats;
 	GGPSearches *searches;
--- a/libpurple/protocols/gg/lib/common.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/common.c	Fri Dec 23 06:58:52 2011 +0000
@@ -24,22 +24,14 @@
  *
  * \brief Funkcje wykorzystywane przez różne moduły biblioteki
  */
-#ifndef _WIN32
-#  include <sys/types.h>
-#  include <sys/ioctl.h>
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  ifdef sun
-#    include <sys/filio.h>
-#  endif
+#include "compat.h"
+#include <sys/types.h>
+#ifdef sun
+#  include <sys/filio.h>
 #endif
 
 #include <errno.h>
 #include <fcntl.h>
-#ifndef _WIN32
-#  include <netdb.h>
-#endif
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -92,7 +84,7 @@
 			}
 			buf = tmp;
 			res = vsnprintf(buf, size, format, ap);
-		} while (res == size - 1 || res == -1);
+		} while (res >= size - 1 || res == -1);
 	}
 #else
 	{
--- a/libpurple/protocols/gg/lib/compat.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/compat.h	Fri Dec 23 06:58:52 2011 +0000
@@ -28,6 +28,21 @@
 #ifndef __COMPAT_H
 #define __COMPAT_H
 
+#ifdef _WIN32
+#  include <ws2tcpip.h>
+#  include <winsock2.h>
+#  define EINPROGRESS WSAEINPROGRESS
+#  define ETIMEDOUT WSAETIMEDOUT
+#  define ENOTCONN WSAENOTCONN
+#  define ECONNRESET WSAECONNRESET
+#else
+#  include <sys/ioctl.h>
+#  include <sys/socket.h>
+#  include <netinet/in.h>
+#  include <arpa/inet.h>
+#  include <netdb.h>
+#endif
+
 #ifdef sun
 #  define INADDR_NONE   ((in_addr_t) 0xffffffff)
 #endif
--- a/libpurple/protocols/gg/lib/dcc.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/dcc.c	Fri Dec 23 06:58:52 2011 +0000
@@ -26,16 +26,11 @@
  * \brief Obsługa połączeń bezpośrednich do wersji Gadu-Gadu 6.x
  */
 
+#include "compat.h"
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifndef _WIN32
-#  include <sys/ioctl.h>
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  ifdef sun
-#    include <sys/filio.h>
-#  endif
+#ifdef sun
+#  include <sys/filio.h>
 #endif
 
 #include <ctype.h>
@@ -601,7 +596,7 @@
 		struct sockaddr_in sin;
 		struct gg_dcc *c;
 		int fd, one = 1;
-		unsigned int sin_len = sizeof(sin);
+		socklen_t sin_len = sizeof(sin);
 
 		if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
 			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno));
@@ -648,7 +643,8 @@
 		struct gg_dcc_small_packet small;
 		struct gg_dcc_big_packet big;
 		int size, tmp, res;
-		unsigned int utmp, res_size = sizeof(res);
+		unsigned int utmp;
+		socklen_t res_size = sizeof(res);
 		char buf[1024], ack[] = "UDAG";
 
 		struct gg_dcc_file_info_packet {
--- a/libpurple/protocols/gg/lib/dcc7.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/dcc7.c	Fri Dec 23 06:58:52 2011 +0000
@@ -31,14 +31,8 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifndef _WIN32
-#  include <sys/ioctl.h>
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  ifdef sun
-#    include <sys/filio.h>
-#  endif
+#ifdef sun
+#  include <sys/filio.h>
 #endif
 #include <time.h>
 
@@ -1095,7 +1089,7 @@
 		case GG_STATE_CONNECTING:
 		{
 			int res = 0, error = 0;
-			unsigned int error_size = sizeof(error);
+			socklen_t error_size = sizeof(error);
 
 			gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n");
 
@@ -1384,7 +1378,7 @@
 		case GG_STATE_CONNECTING_RELAY:
 		{
 			int res;
-			unsigned int res_size = sizeof(res);
+			socklen_t res_size = sizeof(res);
 			struct gg_dcc7_relay_req pkt;
 
 			gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n");
--- a/libpurple/protocols/gg/lib/events.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/events.c	Fri Dec 23 06:58:52 2011 +0000
@@ -28,17 +28,10 @@
  */
 
 #include <sys/types.h>
-#ifndef _WIN32
-#  include <sys/ioctl.h>
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#endif
 #include <ctype.h>
 
 #include "compat.h"
 #include "libgadu.h"
-#include "libgadu-config.h"
 #include "protocol.h"
 #include "libgadu-internal.h"
 #include "encoding.h"
--- a/libpurple/protocols/gg/lib/handlers.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/handlers.c	Fri Dec 23 06:58:52 2011 +0000
@@ -27,21 +27,13 @@
  */
 
 #include <sys/types.h>
-#ifndef _WIN32
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#endif
 #include <ctype.h>
-#ifndef _WIN32
-#  ifdef sun
-#    include <sys/filio.h>
-#  endif
+#ifdef sun
+#  include <sys/filio.h>
 #endif
 
 #include "compat.h"
 #include "libgadu.h"
-#include "libgadu-config.h"
 #include "resolver.h"
 #include "session.h"
 #include "protocol.h"
@@ -51,9 +43,6 @@
 #include "deflate.h"
 
 #include <errno.h>
-#ifndef _WIN32
-#  include <netdb.h>
-#endif
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -92,7 +81,7 @@
 	uint8_t hash_buf[64];
 	uint32_t local_ip;
 	struct sockaddr_in sin;
-	unsigned int sin_len = sizeof(sin);
+	socklen_t sin_len = sizeof(sin);
 
 	if (len < sizeof(struct gg_welcome)) {
 		ge->type = GG_EVENT_CONN_FAILED;
--- a/libpurple/protocols/gg/lib/http.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/http.c	Fri Dec 23 06:58:52 2011 +0000
@@ -25,11 +25,6 @@
  */
 
 #include <sys/types.h>
-#ifndef _WIN32
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#endif
 
 #include "compat.h"
 #include "libgadu.h"
@@ -37,9 +32,6 @@
 
 #include <ctype.h>
 #include <errno.h>
-#ifndef _WIN32
-#  include <netdb.h>
-#endif
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -258,7 +250,7 @@
 	}
 
 	if (h->state == GG_STATE_SENDING_QUERY) {
-		size_t res;
+		ssize_t res;
 
 		if ((res = write(h->fd, h->query, strlen(h->query))) < 1) {
 			gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno);
--- a/libpurple/protocols/gg/lib/libgadu-config.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu-config.h	Fri Dec 23 06:58:52 2011 +0000
@@ -8,8 +8,30 @@
 /* Defined if libgadu was compiled for bigendian machine. */
 #undef __GG_LIBGADU_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
-#define __GG_LIBGADU_BIGENDIAN
-#endif /* WORDS_BIGENDIAN */
+#  define __GG_LIBGADU_BIGENDIAN
+#endif
+
+/* Defined if this machine has gethostbyname_r(). */
+#undef GG_CONFIG_HAVE_GETHOSTBYNAME_R
+
+/* Defined if this machine has _exit(). */
+#define GG_CONFIG_HAVE__EXIT
+
+/* Defined if libgadu was compiled and linked with fork support. */
+#undef GG_CONFIG_HAVE_FORK
+#ifndef _WIN32
+#  define GG_CONFIG_HAVE_FORK
+#endif
+
+/* Defined if libgadu was compiled and linked with pthread support. */
+/* We don't like pthreads. */
+#undef __GG_LIBGADU_HAVE_PTHREAD
+
+/* Defined if this machine has C99-compiliant vsnprintf(). */
+#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF
+#ifndef _WIN32
+#  define __GG_LIBGADU_HAVE_C99_VSNPRINTF
+#endif
 
 /* Defined if this machine has va_copy(). */
 #define __GG_LIBGADU_HAVE_VA_COPY
@@ -20,40 +42,29 @@
 /* Defined if this machine supports long long. */
 #undef __GG_LIBGADU_HAVE_LONG_LONG
 #ifdef HAVE_LONG_LONG
-#define __GG_LIBGADU_HAVE_LONG_LONG
-#endif /* HAVE_LONG_LONG */
+#  define __GG_LIBGADU_HAVE_LONG_LONG
+#endif
 
-/* Defined if libgadu was compiled and linked with pthread support. */
-/* We don't like pthreads. */
-#undef __GG_LIBGADU_HAVE_PTHREAD
-
-/* Defined if libgadu was compiled and linked with GnuTLS encryption support. */
+/* Defined if libgadu was compiled and linked with GnuTLS support. */
+#undef GG_CONFIG_HAVE_GNUTLS
 #ifdef HAVE_GNUTLS
 #  define GG_CONFIG_HAVE_GNUTLS
-#else
-#  undef GG_CONFIG_HAVE_GNUTLS
 #endif
 
-/* Defined if libgadu was compiled and linked with TLS support. */
+/* Defined if libgadu was compiled and linked with OpenSSL support. */
 /* Always undefined in Purple. */
 #undef __GG_LIBGADU_HAVE_OPENSSL
 
-/* Include file containing uintXX_t declarations. */
+/* Defined if libgadu was compiled and linked with zlib support. */
+#undef GG_CONFIG_HAVE_ZLIB
+
+/* Defined if uintX_t types are defined in <stdint.h>. */
+#undef GG_CONFIG_HAVE_STDINT_H
 #if HAVE_STDINT_H
-#include <stdint.h>
+#  define GG_CONFIG_HAVE_STDINT_H
 #endif
 
-/* Defined if this machine has C99-compiliant vsnprintf(). */
-#ifndef _WIN32
-#define __GG_LIBGADU_HAVE_C99_VSNPRINTF
-#else
-#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF
-#endif
 
 #define vnsprintf g_vnsprintf
 
-#ifdef _WIN32
-#define random (long) rand
 #endif
-
-#endif /* __GG_LIBGADU_CONFIG_H */
--- a/libpurple/protocols/gg/lib/libgadu.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu.c	Fri Dec 23 06:58:52 2011 +0000
@@ -29,23 +29,12 @@
  */
 
 #include <sys/types.h>
-#ifdef _WIN32
-#  include <io.h>
-#  include <fcntl.h>
-#  include <errno.h>
-#  define SHUT_RDWR SD_BOTH
-#else
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  ifdef sun
-#    include <sys/filio.h>
-#  endif
+#ifdef sun
+#  include <sys/filio.h>
 #endif
 
 #include "compat.h"
 #include "libgadu.h"
-#include "libgadu-config.h"
 #include "protocol.h"
 #include "resolver.h"
 #include "libgadu-internal.h"
@@ -55,10 +44,7 @@
 #include "message.h"
 #include "deflate.h"
 
-#ifndef _WIN32
-#  include <errno.h> /* on Win32 this is included above */
-#  include <netdb.h>
-#endif
+#include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1122,7 +1108,6 @@
 	sess->resolver_cleanup(&sess->resolver, 1);
 
 	if (sess->fd != -1) {
-		shutdown(sess->fd, SHUT_RDWR);
 		close(sess->fd);
 		sess->fd = -1;
 	}
--- a/libpurple/protocols/gg/lib/libgadu.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu.h	Fri Dec 23 06:58:52 2011 +0000
@@ -33,7 +33,7 @@
 #ifndef __GG_LIBGADU_H
 #define __GG_LIBGADU_H
 
-#ifdef _WIN32
+#if defined(__cplusplus) || defined(_WIN32)
 #pragma pack(push, 1)
 #endif
 
@@ -53,6 +53,12 @@
 /* Defined if this machine has gethostbyname_r(). */
 #undef GG_CONFIG_HAVE_GETHOSTBYNAME_R
 
+/* Defined if this machine has _exit(). */
+#undef GG_CONFIG_HAVE__EXIT
+
+/* Defined if libgadu was compiled and linked with fork support. */
+#undef GG_CONFIG_HAVE_FORK
+
 /* Defined if libgadu was compiled and linked with pthread support. */
 #undef GG_CONFIG_HAVE_PTHREAD
 
@@ -95,6 +101,8 @@
 /* Defined if uintX_t types are defined in <sys/types.h>. */
 #undef GG_CONFIG_HAVE_SYS_TYPES_H
 
+#include "libgadu-config.h"
+
 #ifdef GG_CONFIG_HAVE_OPENSSL
 #include <openssl/ssl.h>
 #endif
@@ -115,24 +123,12 @@
 #        include <sys/types.h>
 #        else
 
-#ifndef __AC_STDINT_H
-#define __AC_STDINT_H
-
 /* ISO C 9X: 7.18 Integer types <stdint.h> */
 
 typedef unsigned char   uint8_t;
 typedef unsigned short uint16_t;
 typedef unsigned int   uint32_t;
 
-#if !defined(__CYGWIN__) && !defined(__SunOS) && !defined(_INCLUDE_HPUX_SOURCE)
-#define __int8_t_defined
-typedef   signed char    int8_t;
-typedef   signed short  int16_t;
-typedef   signed int    int32_t;
-#endif
-
-#endif /* __AC_STDINT_H */
-
 #        endif
 #      endif
 #    endif
@@ -195,7 +191,6 @@
 	GG_RESOLVER_DEFAULT = 0,	/**< Domyślny sposób rozwiązywania nazw (jeden z poniższych) */
 	GG_RESOLVER_FORK,		/**< Rozwiązywanie nazw bazujące na procesach */
 	GG_RESOLVER_PTHREAD,		/**< Rozwiązywanie nazw bazujące na wątkach */
-	GG_RESOLVER_WIN32,
 	GG_RESOLVER_CUSTOM,		/**< Funkcje rozwiązywania nazw dostarczone przed aplikację */
 	GG_RESOLVER_INVALID = -1	/**< Nieprawidłowy sposób rozwiązywania nazw (wynik \c gg_session_get_resolver) */
 } gg_resolver_t;
@@ -1442,7 +1437,6 @@
 
 int gg_file_hash_sha1(int fd, uint8_t *result) GG_DEPRECATED;
 
-#undef printf
 #ifdef __GNUC__
 char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))) GG_DEPRECATED;
 #else
@@ -2298,12 +2292,12 @@
 #define GG_DCC7_TIMEOUT_FILE_ACK 300	/* 5 minut */
 #define GG_DCC7_TIMEOUT_VOICE_ACK 300	/* 5 minut */
 
-#ifdef _WIN32
-#pragma pack(pop)
+#ifdef __cplusplus
+}
 #endif
 
-#ifdef __cplusplus
-}
+#if defined(__cplusplus) || defined(_WIN32)
+#pragma pack(pop)
 #endif
 
 #endif /* __GG_LIBGADU_H */
--- a/libpurple/protocols/gg/lib/pubdir.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/pubdir.c	Fri Dec 23 06:58:52 2011 +0000
@@ -35,7 +35,6 @@
 #include <unistd.h>
 
 #include "libgadu.h"
-#include "libgadu-config.h"
 
 /**
  * Rejestruje nowego użytkownika.
@@ -194,7 +193,7 @@
 		return NULL;
 	}
     
-	__pwd = gg_saprintf("%ld", random());
+	__pwd = gg_saprintf("%d", rand());
 	__fmpwd = gg_urlencode(password);
 	__tokenid = gg_urlencode(tokenid);
 	__tokenval = gg_urlencode(tokenval);
--- a/libpurple/protocols/gg/lib/pubdir50.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/pubdir50.c	Fri Dec 23 06:58:52 2011 +0000
@@ -31,7 +31,6 @@
 #include <time.h>
 
 #include "libgadu.h"
-#include "libgadu-config.h"
 #include "libgadu-internal.h"
 #include "encoding.h"
 
--- a/libpurple/protocols/gg/lib/resolver.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/resolver.c	Fri Dec 23 06:58:52 2011 +0000
@@ -26,26 +26,21 @@
  * \brief Funkcje rozwiązywania nazw
  */
 
-#ifndef _WIN32
-#  include <sys/wait.h>
-#  include <netdb.h>
-#endif
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#ifndef _WIN32
-#  include <signal.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#endif
 
 #include "libgadu.h"
-#include "libgadu-config.h"
 #include "resolver.h"
 #include "compat.h"
 #include "session.h"
 
+#ifdef GG_CONFIG_HAVE_FORK
+#include <sys/wait.h>
+#include <signal.h>
+#endif
+
 /** Sposób rozwiązywania nazw serwerów */
 static gg_resolver_t gg_global_resolver_type = GG_RESOLVER_DEFAULT;
 
@@ -249,7 +244,8 @@
 #endif /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
 }
 
-#if defined(GG_CONFIG_HAVE_PTHREAD) || !defined(_WIN32)
+#if defined(GG_CONFIG_HAVE_PTHREAD) || defined(GG_CONFIG_HAVE_FORK)
+
 /**
  * \internal Rozwiązuje nazwę i zapisuje wynik do podanego desktyptora.
  *
@@ -287,7 +283,8 @@
 
 	return res;
 }
-#endif
+
+#endif /* GG_CONFIG_HAVE_PTHREAD || GG_CONFIG_HAVE_FORK */
 
 /**
  * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
@@ -312,6 +309,8 @@
 	return result;
 }
 
+#ifdef GG_CONFIG_HAVE_FORK
+
 /**
  * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
  */
@@ -319,280 +318,6 @@
 	int pid;		/*< Identyfikator procesu */
 };
 
-#ifdef _WIN32
-/**
- *  Deal with the fact that you can't select() on a win32 file fd.
- *  This makes it practically impossible to tie into purple's event loop.
- *
- *  -This is thanks to Tor Lillqvist.
- *  XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu.
- */
-static int
-socket_pipe (int *fds)
-{
-	SOCKET temp, socket1 = -1, socket2 = -1;
-	struct sockaddr_in saddr;
-	int len;
-	u_long arg;
-	fd_set read_set, write_set;
-	struct timeval tv;
-
-	temp = socket(AF_INET, SOCK_STREAM, 0);
-
-	if (temp == INVALID_SOCKET) {
-		goto out0;
-	}
-
-	arg = 1;
-	if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
-		goto out0;
-	}
-
-	memset(&saddr, 0, sizeof(saddr));
-	saddr.sin_family = AF_INET;
-	saddr.sin_port = 0;
-	saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-	if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
-		goto out0;
-	}
-
-	if (listen(temp, 1) == SOCKET_ERROR) {
-		goto out0;
-	}
-
-	len = sizeof(saddr);
-	if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
-		goto out0;
-	}
-
-	socket1 = socket(AF_INET, SOCK_STREAM, 0);
-
-	if (socket1 == INVALID_SOCKET) {
-		goto out0;
-	}
-
-	arg = 1;
-	if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
-		goto out1;
-	}
-
-	if (connect(socket1, (struct sockaddr  *)&saddr, len) != SOCKET_ERROR ||
-			WSAGetLastError() != WSAEWOULDBLOCK) {
-		goto out1;
-	}
-
-	FD_ZERO(&read_set);
-	FD_SET(temp, &read_set);
-
-	tv.tv_sec = 0;
-	tv.tv_usec = 0;
-
-	if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
-		goto out1;
-	}
-
-	if (!FD_ISSET(temp, &read_set)) {
-		goto out1;
-	}
-
-	socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
-	if (socket2 == INVALID_SOCKET) {
-		goto out1;
-	}
-
-	FD_ZERO(&write_set);
-	FD_SET(socket1, &write_set);
-
-	tv.tv_sec = 0;
-	tv.tv_usec = 0;
-
-	if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
-		goto out2;
-	}
-
-	if (!FD_ISSET(socket1, &write_set)) {
-		goto out2;
-	}
-
-	arg = 0;
-	if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
-		goto out2;
-	}
-
-	arg = 0;
-	if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
-		goto out2;
-	}
-
-	fds[0] = socket1;
-	fds[1] = socket2;
-
-	closesocket (temp);
-
-	return 0;
-
-out2:
-	closesocket (socket2);
-out1:
-	closesocket (socket1);
-out0:
-	closesocket (temp);
-	errno = EIO;            /* XXX */
-
-	return -1;
-}
-#endif
-
-
-
-#ifdef _WIN32
-struct gg_resolve_win32thread_data {
-	char *hostname;
-	int fd;
-};
-
-static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg)
-{
-	struct gg_resolve_win32thread_data *d = arg;
-	struct in_addr addr_ip[2], *addr_list;
-	int addr_count;
-
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() host: %s, fd: %i called\n", d->hostname, d->fd);
-
-	if ((addr_ip[0].s_addr = inet_addr(d->hostname)) == INADDR_NONE) {
-		/* W przypadku błędu gg_gethostbyname_real() zwróci -1
-					 * i nie zmieni &addr. Tam jest już INADDR_NONE,
-					 * więc nie musimy robić nic więcej. */
-		if (gg_gethostbyname_real(d->hostname, &addr_list, &addr_count, 0) == -1)
-		{
-		    addr_list = addr_ip;
-		}
-	} else {
-		addr_list = addr_ip;
-		addr_ip[1].s_addr = INADDR_NONE;
-		addr_count = 1;
-	}
-
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() count = %d\n", addr_count);
-
-	write(d->fd, addr_list, (addr_count+1) * sizeof(struct in_addr));
-	close(d->fd);
-
-	free(d->hostname);
-	d->hostname = NULL;
-
-	free(d);
-
-    if (addr_list != addr_ip)
-		free(addr_list);
-
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() done\n");
-
-	return 0;
-}
-
-
-static int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname)
-{
-	struct gg_resolve_win32thread_data *d = NULL;
-	HANDLE h;
-	DWORD dwTId;
-	int pipes[2], new_errno;
-
-	gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname);
-
-	if (!resolver || !fd || !hostname) {
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n");
-		errno = EFAULT;
-		return -1;
-	}
-
-	if (socket_pipe(pipes) == -1) {
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
-		return -1;
-	}
-
-	if (!(d = malloc(sizeof(*d)))) {
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
-		new_errno = errno;
-		goto cleanup;
-	}
-
-	d->hostname = NULL;
-
-	if (!(d->hostname = strdup(hostname))) {
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
-		new_errno = errno;
-		goto cleanup;
-	}
-
-	d->fd = pipes[1];
-
-	h = CreateThread(NULL, 0, gg_resolve_win32thread_thread,
-		d, 0, &dwTId);
-
-	if (h == NULL) {
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n");
-		new_errno = errno;
-		goto cleanup;
-	}
-
-	*resolver = h;
-	*fd = pipes[0];
-
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() done\n");
-
-	return 0;
-
-cleanup:
-	if (d) {
-		free(d->hostname);
-		free(d);
-	}
-
-	close(pipes[0]);
-	close(pipes[1]);
-
-	errno = new_errno;
-
-	return -1;
-
-}
-
-static void gg_resolve_win32thread_cleanup(void **priv_data, int force)
-{
-	struct gg_resolve_win32thread_data *data;
-
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force: %i called\n", force);
-
-	if (priv_data == NULL || *priv_data == NULL)
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() priv_data: NULL\n");
-		return;
-
-	data = (struct gg_resolve_win32thread_data*) *priv_data;
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() data: %s called\n", data->hostname);
-	*priv_data = NULL;
-
-	if (force) {
-		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force called\n", force);
-		//pthread_cancel(data->thread);
-		//pthread_join(data->thread, NULL);
-	}
-
-	free(data->hostname);
-	data->hostname = NULL;
-
-	if (data->fd != -1) {
-		close(data->fd);
-		data->fd = -1;
-	}
-	gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() done\n");
-	free(data);
-}
-#endif
-
-#ifndef _WIN32
 /**
  * \internal Rozwiązuje nazwę serwera w osobnym procesie.
  *
@@ -644,12 +369,17 @@
 	}
 
 	if (data->pid == 0) {
+		int status;
+
 		close(pipes[0]);
 
-		if (gg_resolver_run(pipes[1], hostname) == -1)
-			_exit(1);
-		else
-			_exit(0);
+		status = (gg_resolver_run(pipes[1], hostname) == -1) ? 1 : 0;
+
+#ifdef GG_CONFIG_HAVE__EXIT
+		_exit(status);
+#else
+		exit(status);
+#endif
 	}
 
 	close(pipes[1]);
@@ -698,7 +428,8 @@
 
 	free(data);
 }
-#endif
+
+#endif /* GG_CONFIG_HAVE_FORK */
 
 #ifdef GG_CONFIG_HAVE_PTHREAD
 
@@ -868,25 +599,15 @@
 			return 0;
 		}
 
-#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
-#  ifdef _WIN32
-		type = GG_RESOLVER_WIN32;
-#  else
+#if defined(GG_CONFIG_HAVE_PTHREAD) && defined(GG_CONFIG_PTHREAD_DEFAULT)
+		type = GG_RESOLVER_PTHREAD;
+#elif defined(GG_CONFIG_HAVE_FORK)
 		type = GG_RESOLVER_FORK;
-#  endif
-#else
-		type = GG_RESOLVER_PTHREAD;
 #endif
 	}
 
 	switch (type) {
-#ifdef _WIN32
-		case GG_RESOLVER_WIN32:
-			gs->resolver_type = type;
-			gs->resolver_start = gg_resolve_win32thread;
-			gs->resolver_cleanup = gg_resolve_win32thread_cleanup;
-			return 0;
-#else
+#ifdef GG_CONFIG_HAVE_FORK
 		case GG_RESOLVER_FORK:
 			gs->resolver_type = type;
 			gs->resolver_start = gg_resolver_fork_start;
@@ -989,25 +710,15 @@
 			return 0;
 		}
 
-#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
-#  ifdef _WIN32
-		type = GG_RESOLVER_WIN32;
-#  else
+#if defined(GG_CONFIG_HAVE_PTHREAD) && defined(GG_CONFIG_PTHREAD_DEFAULT)
+		type = GG_RESOLVER_PTHREAD;
+#elif defined(GG_CONFIG_HAVE_FORK)
 		type = GG_RESOLVER_FORK;
-#  endif
-#else
-		type = GG_RESOLVER_PTHREAD;
 #endif
 	}
 
 	switch (type) {
-#ifdef _WIN32
-		case GG_RESOLVER_WIN32:
-			gh->resolver_type = type;
-			gh->resolver_start = gg_resolve_win32thread;
-			gh->resolver_cleanup = gg_resolve_win32thread_cleanup;
-			return 0;
-#else
+#ifdef GG_CONFIG_HAVE_FORK
 		case GG_RESOLVER_FORK:
 			gh->resolver_type = type;
 			gh->resolver_start = gg_resolver_fork_start;
@@ -1085,13 +796,7 @@
 			gg_global_resolver_cleanup = NULL;
 			return 0;
 
-#ifdef _WIN32
-		case GG_RESOLVER_WIN32:
-			gg_global_resolver_type = type;
-			gg_global_resolver_start = gg_resolve_win32thread;
-			gg_global_resolver_cleanup = gg_resolve_win32thread_cleanup;
-			return 0;
-#else
+#ifdef GG_CONFIG_HAVE_FORK
 		case GG_RESOLVER_FORK:
 			gg_global_resolver_type = type;
 			gg_global_resolver_start = gg_resolver_fork_start;
--- a/libpurple/protocols/gg/lib/resolver.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/gg/lib/resolver.h	Fri Dec 23 06:58:52 2011 +0000
@@ -19,9 +19,7 @@
 #ifndef LIBGADU_RESOLVER_H
 #define LIBGADU_RESOLVER_H
 
-#ifndef _WIN32
-#  include <arpa/inet.h>
-#endif
+#include "compat.h"
 
 int gg_gethostbyname_real(const char *hostname, struct in_addr **result, int *count, int pthread);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/gg/win32-resolver.c	Fri Dec 23 06:58:52 2011 +0000
@@ -0,0 +1,322 @@
+/**
+ * @file win32-resolver.c
+ *
+ * purple
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301 USA
+ */
+
+#include "win32-resolver.h"
+
+#include <errno.h>
+#include <resolver.h>
+#include "debug.h"
+
+#ifndef _WIN32
+#error "win32thread resolver is not supported on current platform"
+#endif
+
+/**
+ * Deal with the fact that you can't select() on a win32 file fd.
+ * This makes it practically impossible to tie into purple's event loop.
+ *
+ * -This is thanks to Tor Lillqvist.
+ */
+static int ggp_resolver_win32thread_socket_pipe(int *fds)
+{
+	SOCKET temp, socket1 = -1, socket2 = -1;
+	struct sockaddr_in saddr;
+	int len;
+	u_long arg;
+	fd_set read_set, write_set;
+	struct timeval tv;
+
+	purple_debug_misc("gg", "ggp_resolver_win32thread_socket_pipe(&%d)\n",
+		*fds);
+
+	temp = socket(AF_INET, SOCK_STREAM, 0);
+
+	if (temp == INVALID_SOCKET) {
+		goto out0;
+	}
+
+	arg = 1;
+	if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out0;
+	}
+
+	memset(&saddr, 0, sizeof(saddr));
+	saddr.sin_family = AF_INET;
+	saddr.sin_port = 0;
+	saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
+		goto out0;
+	}
+
+	if (listen(temp, 1) == SOCKET_ERROR) {
+		goto out0;
+	}
+
+	len = sizeof(saddr);
+	if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
+		goto out0;
+	}
+
+	socket1 = socket(AF_INET, SOCK_STREAM, 0);
+
+	if (socket1 == INVALID_SOCKET) {
+		goto out0;
+	}
+
+	arg = 1;
+	if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out1;
+	}
+
+	if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR ||
+			WSAGetLastError() != WSAEWOULDBLOCK) {
+		goto out1;
+	}
+
+	FD_ZERO(&read_set);
+	FD_SET(temp, &read_set);
+
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+
+	if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
+		goto out1;
+	}
+
+	if (!FD_ISSET(temp, &read_set)) {
+		goto out1;
+	}
+
+	socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
+	if (socket2 == INVALID_SOCKET) {
+		goto out1;
+	}
+
+	FD_ZERO(&write_set);
+	FD_SET(socket1, &write_set);
+
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+
+	if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
+		goto out2;
+	}
+
+	if (!FD_ISSET(socket1, &write_set)) {
+		goto out2;
+	}
+
+	arg = 0;
+	if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out2;
+	}
+
+	arg = 0;
+	if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out2;
+	}
+
+	fds[0] = socket1;
+	fds[1] = socket2;
+
+	closesocket (temp);
+
+	return 0;
+
+out2:
+	closesocket (socket2);
+out1:
+	closesocket (socket1);
+out0:
+	closesocket (temp);
+	errno = EIO; /* XXX */
+
+	return -1;
+}
+
+struct ggp_resolver_win32thread_data {
+	char *hostname;
+	int fd;
+};
+
+/**
+ * Copy-paste from gg_resolver_run().
+ */
+static DWORD WINAPI ggp_resolver_win32thread_thread(LPVOID arg)
+{
+	struct ggp_resolver_win32thread_data *data = arg;
+	struct in_addr addr_ip[2], *addr_list;
+	int addr_count;
+
+	purple_debug_info("gg", "ggp_resolver_win32thread_thread() host: %s, "
+		"fd: %i called\n", data->hostname, data->fd);
+
+	if ((addr_ip[0].s_addr = inet_addr(data->hostname)) == INADDR_NONE) {
+		if (gg_gethostbyname_real(data->hostname, &addr_list,
+			&addr_count, 0) == -1) {
+			addr_list = addr_ip;
+			/* addr_ip[0] już zawiera INADDR_NONE */
+		}
+	} else {
+		addr_list = addr_ip;
+		addr_ip[1].s_addr = INADDR_NONE;
+		addr_count = 1;
+	}
+
+	purple_debug_misc("gg", "ggp_resolver_win32thread_thread() "
+		"count = %d\n", addr_count);
+
+	write(data->fd, addr_list, (addr_count + 1) * sizeof(struct in_addr));
+	close(data->fd);
+
+	free(data->hostname);
+	data->hostname = NULL;
+
+	free(data);
+
+	if (addr_list != addr_ip)
+		free(addr_list);
+
+	purple_debug_misc("gg", "ggp_resolver_win32thread_thread() done\n");
+
+	return 0;
+}
+
+
+int ggp_resolver_win32thread_start(int *fd, void **private_data,
+	const char *hostname)
+{
+	struct ggp_resolver_win32thread_data *data = NULL;
+	HANDLE h;
+	DWORD dwTId;
+	int pipes[2], new_errno;
+
+	purple_debug_info("gg", "ggp_resolver_win32thread_start(%p, %p, "
+		"\"%s\");\n", fd, private_data, hostname);
+
+	if (!private_data || !fd || !hostname) {
+		purple_debug_error("gg", "ggp_resolver_win32thread_start() "
+			"invalid arguments\n");
+		errno = EFAULT;
+		return -1;
+	}
+
+	purple_debug_misc("gg", "ggp_resolver_win32thread_start() creating "
+		"pipes...\n");
+
+	if (ggp_resolver_win32thread_socket_pipe(pipes) == -1) {
+		purple_debug_error("gg", "ggp_resolver_win32thread_start() "
+			"unable to create pipes (errno=%d, %s)\n",
+			errno, strerror(errno));
+		return -1;
+	}
+
+	if (!(data = malloc(sizeof(*data)))) {
+		purple_debug_error("gg", "ggp_resolver_win32thread_start() out "
+			"of memory\n");
+		new_errno = errno;
+		goto cleanup;
+	}
+
+	data->hostname = NULL;
+
+	if (!(data->hostname = strdup(hostname))) {
+		purple_debug_error("gg", "ggp_resolver_win32thread_start() out "
+			"of memory\n");
+		new_errno = errno;
+		goto cleanup;
+	}
+
+	data->fd = pipes[1];
+
+	purple_debug_misc("gg", "ggp_resolver_win32thread_start() creating "
+		"thread...\n");
+
+	h = CreateThread(NULL, 0, ggp_resolver_win32thread_thread, data, 0,
+		&dwTId);
+
+	if (h == NULL) {
+		purple_debug_error("gg", "ggp_resolver_win32thread_start() "
+			"unable to create thread\n");
+		new_errno = errno;
+		goto cleanup;
+	}
+
+	*private_data = h;
+	*fd = pipes[0];
+
+	purple_debug_misc("gg", "ggp_resolver_win32thread_start() done\n");
+
+	return 0;
+
+cleanup:
+	if (data) {
+		free(data->hostname);
+		free(data);
+	}
+
+	close(pipes[0]);
+	close(pipes[1]);
+
+	errno = new_errno;
+
+	return -1;
+
+}
+
+void ggp_resolver_win32thread_cleanup(void **private_data, int force)
+{
+	struct ggp_resolver_win32thread_data *data;
+
+	purple_debug_info("gg", "ggp_resolver_win32thread_cleanup() force: %i "
+		"called\n", force);
+
+	if (private_data == NULL || *private_data == NULL) {
+		purple_debug_error("gg", "ggp_resolver_win32thread_cleanup() "
+			"private_data: NULL\n");
+		return;
+	}
+	return; /* XXX */
+
+	data = (struct ggp_resolver_win32thread_data*) *private_data;
+	purple_debug_misc("gg", "ggp_resolver_win32thread_cleanup() data: "
+		"%s called\n", data->hostname);
+	*private_data = NULL;
+
+	if (force) {
+		purple_debug_misc("gg", "ggp_resolver_win32thread_cleanup() "
+			"force called\n");
+		//pthread_cancel(data->thread);
+		//pthread_join(data->thread, NULL);
+	}
+
+	free(data->hostname);
+	data->hostname = NULL;
+
+	if (data->fd != -1) {
+		close(data->fd);
+		data->fd = -1;
+	}
+	purple_debug_info("gg", "ggp_resolver_win32thread_cleanup() done\n");
+	free(data);
+}
+
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/gg/win32-resolver.h	Fri Dec 23 06:58:52 2011 +0000
@@ -0,0 +1,46 @@
+/**
+ * @file win32-resolver.h
+ *
+ * purple
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301 USA
+ */
+
+#ifndef _PURPLE_GG_WIN32_RESOLVER
+#define _PURPLE_GG_WIN32_RESOLVER
+
+/**
+ * Starts hostname resolving in new win32 thread.
+ *
+ * @param fd           Pointer to variable, where pipe descriptor will be saved.
+ * @param private_data Pointer to variable, where pointer to private data will
+ *                     be saved.
+ * @param hostname     Hostname to resolve.
+ */
+int ggp_resolver_win32thread_start(int *fd, void **private_data,
+	const char *hostname);
+
+/**
+ * Cleans up resources after hostname resolving.
+ *
+ * @param private_data Pointer to variable storing pointer to private data.
+ * @param force        TRUE, if resources should be cleaned up even, if
+ *                     resolving process didn't finished.
+ */
+void ggp_resolver_win32thread_cleanup(void **private_data, int force);
+
+#endif /* _PURPLE_GG_WIN32_RESOLVER */
+
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/irc/cmds.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/irc/cmds.c	Fri Dec 23 06:58:52 2011 +0000
@@ -423,7 +423,7 @@
 
 		irc->quitting = TRUE;
 
-		if (!irc->account->disconnecting)
+		if (!purple_account_is_disconnecting(irc->account))
 			purple_account_set_status(irc->account, "offline", TRUE, NULL);
 	}
 
--- a/libpurple/protocols/irc/dcc_send.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/irc/dcc_send.c	Fri Dec 23 06:58:52 2011 +0000
@@ -258,8 +258,8 @@
 		return;
 	}
 
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
+	purple_input_remove(purple_xfer_get_watcher(xfer));
+	purple_xfer_set_watcher(xfer, 0);
 	close(xd->fd);
 	xd->fd = -1;
 
@@ -313,13 +313,13 @@
 	port = purple_network_get_port_from_fd(sock);
 	purple_debug_misc("irc", "port is %hu\n", port);
 	/* Monitor the listening socket */
-	xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ,
-	                                 irc_dccsend_send_connected, xfer);
+	purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ,
+	                                 irc_dccsend_send_connected, xfer));
 
 	/* Send the intended recipient the DCC request */
 	arg[0] = purple_xfer_get_remote_user(xfer);
 	inet_aton(purple_network_get_my_ip(irc->fd), &addr);
-	arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GSIZE_FORMAT "\001",
+	arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001",
 	                               purple_xfer_get_filename(xfer), ntohl(addr.s_addr),
 	                               port, purple_xfer_get_size(xfer));
 
--- a/libpurple/protocols/irc/irc.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/irc/irc.c	Fri Dec 23 06:58:52 2011 +0000
@@ -356,7 +356,7 @@
 	const char *username = purple_account_get_username(account);
 
 	gc = purple_account_get_connection(account);
-	gc->flags |= PURPLE_CONNECTION_NO_NEWLINES;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_NEWLINES);
 
 	if (strpbrk(username, " \t\v\r\n") != NULL) {
 		purple_connection_error (gc,
@@ -500,7 +500,7 @@
 	irc->fd = source;
 
 	if (do_login(gc)) {
-		gc->inpa = purple_input_add(irc->fd, PURPLE_INPUT_READ, irc_input_cb, gc);
+		irc->inpa = purple_input_add(irc->fd, PURPLE_INPUT_READ, irc_input_cb, gc);
 	}
 }
 
@@ -526,8 +526,10 @@
 	if (irc->gsc || (irc->fd >= 0))
 		irc_cmd_quit(irc, "quit", NULL, NULL);
 
-	if (gc->inpa)
-		purple_input_remove(gc->inpa);
+	if (irc->inpa) {
+		purple_input_remove(irc->inpa);
+		irc->inpa = 0;
+	}
 
 	g_free(irc->inbuf);
 	if (irc->gsc) {
@@ -648,7 +650,7 @@
 	PurpleConnection *connection = purple_account_get_connection(irc->account);
 	char *cur, *end;
 
-	connection->last_received = time(NULL);
+	purple_connection_update_last_received(connection);
 	irc->inbufused += len;
 	irc->inbuf[irc->inbufused] = '\0';
 
--- a/libpurple/protocols/irc/irc.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/irc/irc.h	Fri Dec 23 06:58:52 2011 +0000
@@ -54,6 +54,7 @@
 	GHashTable *cmds;
 	char *server;
 	int fd;
+	guint inpa;
 	guint timer;
 	guint who_channel_timer;
 	GHashTable *buddies;
--- a/libpurple/protocols/irc/msgs.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/irc/msgs.c	Fri Dec 23 06:58:52 2011 +0000
@@ -92,7 +92,7 @@
 	/* If we're away then set our away message */
 	status = purple_account_get_active_status(irc->account);
 	if (!purple_status_get_type(status) != PURPLE_STATUS_AVAILABLE) {
-		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 		prpl_info->set_status(irc->account, status);
 	}
 
--- a/libpurple/protocols/irc/parse.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/irc/parse.c	Fri Dec 23 06:58:52 2011 +0000
@@ -171,7 +171,7 @@
 	struct irc_conn *irc;
 	struct _irc_user_cmd *cmdent;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	if (!gc)
 		return PURPLE_CMD_RET_FAILED;
 
@@ -260,6 +260,12 @@
 	gboolean autodetect;
 	int i;
 
+	autodetect = purple_account_get_bool(irc->account, "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
+
+	if (autodetect && g_utf8_validate(string, -1, NULL)) {
+		return g_strdup(string);
+	}
+
 	enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);
 	encodings = g_strsplit(enclist, ",", -1);
 
@@ -268,12 +274,6 @@
 		return purple_utf8_salvage(string);
 	}
 
-	autodetect = purple_account_get_bool(irc->account, "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
-
-	if (autodetect && g_utf8_validate(string, -1, NULL)) {
-		return g_strdup(string);
-	}
-
 	for (i = 0; encodings[i] != NULL; i++) {
 		charset = encodings[i];
 		while (*charset == ' ')
--- a/libpurple/protocols/jabber/buddy.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Fri Dec 23 06:58:52 2011 +0000
@@ -501,7 +501,7 @@
 		vc_node = NULL;
 	}
 
-	if ((img = purple_buddy_icons_find_account_icon(gc->account))) {
+	if ((img = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc)))) {
 		gconstpointer avatar_data;
 		gsize avatar_len;
 		xmlnode *photo, *binval, *type;
@@ -642,7 +642,7 @@
 	/*
 	 * Get existing, XML-formatted, user info
 	 */
-	if((user_info = purple_account_get_user_info(gc->account)) != NULL)
+	if((user_info = purple_account_get_user_info(purple_connection_get_account(gc))) != NULL)
 		x_vc_data = xmlnode_from_str(user_info, -1);
 
 	/*
@@ -1360,7 +1360,7 @@
 
 									if (jbr ==
 										jabber_buddy_find_resource(jb, NULL)) {
-										purple_prpl_got_user_idle(js->gc->account,
+										purple_prpl_got_user_idle(purple_connection_get_account(js->gc),
 											buddy_name, jbr->idle, jbr->idle);
 									}
 								}
@@ -2255,10 +2255,10 @@
 	   make sure we aren't persisting an old value */
 	if(js->user_directories && js->user_directories->data &&
 	   !strcmp(directory, js->user_directories->data)) {
-		purple_account_set_string(js->gc->account, "user_directory", "");
+		purple_account_set_string(purple_connection_get_account(js->gc), "user_directory", "");
 	}
 	else {
-		purple_account_set_string(js->gc->account, "user_directory", directory);
+		purple_account_set_string(purple_connection_get_account(js->gc), "user_directory", directory);
 	}
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search");
@@ -2273,7 +2273,7 @@
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
-	const char *def_val = purple_account_get_string(js->gc->account, "user_directory", "");
+	const char *def_val = purple_account_get_string(purple_connection_get_account(js->gc), "user_directory", "");
 	if(!*def_val && js->user_directories)
 		def_val = js->user_directories->data;
 
--- a/libpurple/protocols/jabber/caps.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/caps.c	Fri Dec 23 06:58:52 2011 +0000
@@ -794,11 +794,11 @@
 
 		for (value = xmlnode_get_child(field, "value"); value; value = xmlnode_get_next_twin(value)) {
 			gchar *val = xmlnode_get_data(value);
-			xdatafield->values = g_list_append(xdatafield->values, val);
+			xdatafield->values = g_list_prepend(xdatafield->values, val);
 		}
 
 		xdatafield->values = g_list_sort(xdatafield->values, (GCompareFunc)strcmp);
-		fields = g_list_append(fields, xdatafield);
+		fields = g_list_prepend(fields, xdatafield);
 	}
 
 	fields = g_list_sort(fields, jabber_caps_xdata_field_compare);
@@ -875,21 +875,24 @@
 		g_free(formtype);
 
 		while (fields) {
-			GList *value;
 			JabberDataFormField *field = (JabberDataFormField*)fields->data;
 
 			if (!g_str_equal(field->var, "FORM_TYPE")) {
 				/* Append the "var" attribute */
 				append_escaped_string(context, field->var);
 				/* Append <value/> elements' cdata */
-				for (value = field->values; value; value = value->next) {
-					append_escaped_string(context, value->data);
-					g_free(value->data);
+				while (field->values) {
+					append_escaped_string(context, field->values->data);
+					g_free(field->values->data);
+					field->values = g_list_delete_link(field->values,
+					                                   field->values);
 				}
+			} else {
+				g_list_free_full(field->values, g_free);
 			}
 
 			g_free(field->var);
-			g_list_free(field->values);
+			g_free(field);
 
 			fields = g_list_delete_link(fields, fields);
 		}
--- a/libpurple/protocols/jabber/disco.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/disco.c	Fri Dec 23 06:58:52 2011 +0000
@@ -387,7 +387,7 @@
 	}
 
 	/* If there are manually specified bytestream proxies, query them */
-	ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL);
+	ft_proxies = purple_account_get_string(purple_connection_get_account(js->gc), "ft_proxies", NULL);
 	if (ft_proxies) {
 		JabberIq *iq;
 		JabberBytestreamsStreamhost *sh;
@@ -524,8 +524,10 @@
 		if(category && type && !strcmp(category, "pubsub") && !strcmp(type,"pep")) {
 			PurpleConnection *gc = js->gc;
 			js->pep = TRUE;
-			gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS |
-				PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES;
+			purple_connection_set_flags(gc,
+					  purple_connection_get_flags(gc)
+					| PURPLE_CONNECTION_SUPPORT_MOODS
+					| PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES);
 		}
 		if (!category || strcmp(category, "server"))
 			continue;
--- a/libpurple/protocols/jabber/google/gmail.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/google/gmail.c	Fri Dec 23 06:58:52 2011 +0000
@@ -150,7 +150,7 @@
 	JabberIq *iq;
 
 	/* bail if the user isn't interested */
-	if (!purple_account_get_check_mail(js->gc->account))
+	if (!purple_account_get_check_mail(purple_connection_get_account(js->gc)))
 		return;
 
 	/* Is this an initial incoming mail notification? If so, send a request for more info */
--- a/libpurple/protocols/jabber/google/google_presence.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/google/google_presence.c	Fri Dec 23 06:58:52 2011 +0000
@@ -27,12 +27,12 @@
 	if (!js->googletalk)
 		return;
 	if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) {
-		purple_prpl_got_user_status(js->gc->account, user, "tune",
+		purple_prpl_got_user_status(purple_connection_get_account(js->gc), user, "tune",
 					    PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL);
 		g_free(jbr->status);
 		jbr->status = NULL;
 	} else {
-		purple_prpl_got_user_status_deactive(js->gc->account, user, "tune");
+		purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), user, "tune");
 	}
 }
 
--- a/libpurple/protocols/jabber/jabber.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Fri Dec 23 06:58:52 2011 +0000
@@ -440,7 +440,7 @@
 		 * we're disconnecting, don't generate (possibly another) error that
 		 * (for some UIs) would mask the first.
 		 */
-		if (!account->disconnecting) {
+		if (!purple_account_is_disconnecting(account)) {
 			gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 					g_strerror(errno));
 			purple_connection_error(js->gc,
@@ -653,7 +653,7 @@
 	}
 
 	while((len = purple_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) {
-		gc->last_received = time(NULL);
+		purple_connection_update_last_received(gc);
 		buf[len] = '\0';
 		purple_debug_info("jabber", "Recv (ssl)(%d): %s\n", len, buf);
 		jabber_parser_process(js, buf, len);
@@ -687,7 +687,7 @@
 	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
 	if((len = read(js->fd, buf, sizeof(buf) - 1)) > 0) {
-		gc->last_received = time(NULL);
+		purple_connection_update_last_received(gc);
 #ifdef HAVE_CYRUS_SASL
 		if (js->sasl_maxbuf > 0) {
 			const char *out;
@@ -829,7 +829,7 @@
 		jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
 
 	jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
-	gc->inpa = purple_input_add(js->fd, PURPLE_INPUT_READ, jabber_recv_cb, gc);
+	js->inpa = purple_input_add(js->fd, PURPLE_INPUT_READ, jabber_recv_cb, gc);
 }
 
 static void
@@ -850,9 +850,9 @@
 
 static void tls_init(JabberStream *js)
 {
-	purple_input_remove(js->gc->inpa);
-	js->gc->inpa = 0;
-	js->gsc = purple_ssl_connect_with_host_fd(js->gc->account, js->fd,
+	purple_input_remove(js->inpa);
+	js->inpa = 0;
+	js->gsc = purple_ssl_connect_with_host_fd(purple_connection_get_account(js->gc), js->fd,
 			jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
 	/* The fd is no longer our concern */
 	js->fd = -1;
@@ -1086,8 +1086,7 @@
 	JabberStream *js;
 	PurpleStoredImage *image;
 
-	gc->flags |= PURPLE_CONNECTION_HTML |
-		PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY);
 	js = jabber_stream_new(account);
 	if (js == NULL)
 		return;
@@ -1145,8 +1144,7 @@
 		if(js->registration) {
 			buf = g_strdup_printf(_("Registration of %s@%s successful"),
 					js->user->node, js->user->domain);
-			if(account->registration_cb)
-				(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+			purple_account_register_completed(account, TRUE);
 		} else {
 			g_return_if_fail(to != NULL);
 			buf = g_strdup_printf(_("Registration to %s successful"),
@@ -1164,8 +1162,7 @@
 		purple_notify_error(NULL, _("Registration Failed"),
 				_("Registration Failed"), msg);
 		g_free(msg);
-		if(account->registration_cb)
-			(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+		purple_account_register_completed(account, FALSE);
 	}
 	g_free(to);
 	if(js->registration)
@@ -1265,7 +1262,7 @@
 					cbdata->js->user->node = g_strdup(value);
 				}
 				if(cbdata->js->registration && !strcmp(id, "password"))
-					purple_account_set_password(cbdata->js->gc->account, value);
+					purple_account_set_password(purple_connection_get_account(cbdata->js->gc), value);
 			}
 		}
 	}
@@ -1274,7 +1271,7 @@
 		username = g_strdup_printf("%s@%s%s%s", cbdata->js->user->node, cbdata->js->user->domain,
 			cbdata->js->user->resource ? "/" : "",
 			cbdata->js->user->resource ? cbdata->js->user->resource : "");
-		purple_account_set_username(cbdata->js->gc->account, username);
+		purple_account_set_username(purple_connection_get_account(cbdata->js->gc), username);
 		g_free(username);
 	}
 
@@ -1289,8 +1286,7 @@
 {
 	PurpleAccount *account = purple_connection_get_account(cbdata->js->gc);
 	if(account && cbdata->js->registration) {
-		if(account->registration_cb)
-			(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+		purple_account_register_completed(account, FALSE);
 		jabber_connection_schedule_close(cbdata->js);
 	}
 	g_free(cbdata->who);
@@ -1359,8 +1355,7 @@
 		if(js->registration) {
 			purple_notify_error(NULL, _("Already Registered"),
 								_("Already Registered"), NULL);
-			if(account->registration_cb)
-				(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+			purple_account_register_completed(account, FALSE);
 			jabber_connection_schedule_close(js);
 			return;
 		}
@@ -1381,8 +1376,8 @@
 
 				if(js->registration) {
 					js->gc->wants_to_die = TRUE;
-					if(account->registration_cb) /* succeeded, but we have no login info */
-						(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+					/* succeeded, but we have no login info */
+					purple_account_register_completed(account, TRUE);
 					jabber_connection_schedule_close(js);
 				}
 				return;
@@ -1423,7 +1418,7 @@
 	if((node = xmlnode_get_child(query, "name"))) {
 		if(js->registration)
 			field = purple_request_field_string_new("name", _("Name"),
-													purple_account_get_alias(js->gc->account), FALSE);
+													purple_account_get_alias(purple_connection_get_account(js->gc)), FALSE);
 		else {
 			char *data = xmlnode_get_data(node);
 			field = purple_request_field_string_new("name", _("Name"), data, FALSE);
@@ -1557,8 +1552,8 @@
 	PurpleConnection *gc = purple_account_get_connection(account);
 	JabberStream *js;
 
-	if(gc->state != PURPLE_CONNECTED) {
-		if(gc->state != PURPLE_CONNECTING)
+	if (purple_connection_get_state(gc) != PURPLE_CONNECTED) {
+		if (purple_connection_get_state(gc) != PURPLE_CONNECTING)
 			jabber_login(account);
 		js = purple_connection_get_protocol_data(gc);
 		js->unregistration = TRUE;
@@ -1604,8 +1599,10 @@
 	if(js->gsc) {
 		purple_ssl_close(js->gsc);
 	} else if (js->fd > 0) {
-		if(js->gc->inpa)
-			purple_input_remove(js->gc->inpa);
+		if(js->inpa) {
+			purple_input_remove(js->inpa);
+			js->inpa = 0;
+		}
 		close(js->fd);
 	}
 
@@ -2487,7 +2484,7 @@
 		purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"),
 				_("Your password has been changed."));
 
-		purple_account_set_password(js->gc->account, (char *)data);
+		purple_account_set_password(purple_connection_get_account(js->gc), (char *)data);
 	} else {
 		char *msg = jabber_parse_error(js, packet, NULL);
 
@@ -2742,8 +2739,8 @@
 		} else if(xmlnode_get_child(packet, "not-authorized")) {
 			SET_REASON(PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED);
 			/* Clear the pasword if it isn't being saved */
-			if (!purple_account_get_remember_password(js->gc->account))
-				purple_account_set_password(js->gc->account, NULL);
+			if (!purple_account_get_remember_password(purple_connection_get_account(js->gc)))
+				purple_account_set_password(purple_connection_get_account(js->gc), NULL);
 			text = _("Not Authorized");
 		} else if(xmlnode_get_child(packet, "temporary-auth-failure")) {
 			text = _("Temporary Authentication Failure");
@@ -3000,7 +2997,7 @@
 	if(!args || !args[0])
 		return PURPLE_CMD_RET_FAILED;
 
-	jabber_chat_invite(purple_conversation_get_gc(conv),
+	jabber_chat_invite(purple_conversation_get_connection(conv),
 			purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), args[1] ? args[1] : "",
 			args[0]);
 
@@ -3047,7 +3044,7 @@
 	if (args[1])
 		g_hash_table_insert(components, "password", args[1]);
 
-	jabber_chat_join(purple_conversation_get_gc(conv), components);
+	jabber_chat_join(purple_conversation_get_connection(conv), components);
 
 	g_hash_table_destroy(components);
 	jabber_id_free(jid);
@@ -3081,7 +3078,7 @@
 
 	who = g_strdup_printf("%s@%s/%s", chat->room, chat->server, args[0]);
 
-	jabber_message_send_im(purple_conversation_get_gc(conv), who, args[1], 0);
+	jabber_message_send_im(purple_conversation_get_connection(conv), who, args[1], 0);
 
 	g_free(who);
 	return PURPLE_CMD_RET_OK;
--- a/libpurple/protocols/jabber/jabber.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Fri Dec 23 06:58:52 2011 +0000
@@ -99,6 +99,7 @@
 struct _JabberStream
 {
 	int fd;
+	guint inpa;
 
 	PurpleSrvTxtQueryData *srv_query_data;
 
--- a/libpurple/protocols/jabber/jingle/content.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/content.c	Fri Dec 23 06:58:52 2011 +0000
@@ -181,6 +181,8 @@
 jingle_content_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleContent *content;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_CONTENT(object));
 
 	content = JINGLE_CONTENT(object);
@@ -225,6 +227,8 @@
 jingle_content_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleContent *content;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_CONTENT(object));
 
 	content = JINGLE_CONTENT(object);
@@ -454,6 +458,7 @@
 xmlnode *
 jingle_content_to_xml(JingleContent *content, xmlnode *jingle, JingleActionType action)
 {
+	g_return_val_if_fail(content != NULL, NULL);
 	g_return_val_if_fail(JINGLE_IS_CONTENT(content), NULL);
 	return JINGLE_CONTENT_GET_CLASS(content)->to_xml(content, jingle, action);
 }
@@ -461,6 +466,7 @@
 void
 jingle_content_handle_action(JingleContent *content, xmlnode *xmlcontent, JingleActionType action)
 {
+	g_return_if_fail(content != NULL);
 	g_return_if_fail(JINGLE_IS_CONTENT(content));
 	JINGLE_CONTENT_GET_CLASS(content)->handle_action(content, xmlcontent, action);
 }
--- a/libpurple/protocols/jabber/jingle/iceudp.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/iceudp.c	Fri Dec 23 06:58:52 2011 +0000
@@ -202,6 +202,8 @@
 jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleIceUdp *iceudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_ICEUDP(object));
 
 	iceudp = JINGLE_ICEUDP(object);
@@ -225,6 +227,8 @@
 jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleIceUdp *iceudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_ICEUDP(object));
 
 	iceudp = JINGLE_ICEUDP(object);
--- a/libpurple/protocols/jabber/jingle/jingle.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/jingle.c	Fri Dec 23 06:58:52 2011 +0000
@@ -126,7 +126,7 @@
 		if (local_content != NULL) {
 			const gchar *senders = xmlnode_get_attrib(content, "senders");
 			gchar *local_senders = jingle_content_get_senders(local_content);
-			if (strcmp(senders, local_senders))
+			if (!purple_strequal(senders, local_senders))
 				jingle_content_modify(local_content, senders);
 			g_free(local_senders);
 		} else {
--- a/libpurple/protocols/jabber/jingle/rawudp.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/rawudp.c	Fri Dec 23 06:58:52 2011 +0000
@@ -174,6 +174,8 @@
 jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleRawUdp *rawudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_RAWUDP(object));
 
 	rawudp = JINGLE_RAWUDP(object);
@@ -197,6 +199,8 @@
 jingle_rawudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleRawUdp *rawudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_RAWUDP(object));
 
 	rawudp = JINGLE_RAWUDP(object);
--- a/libpurple/protocols/jabber/jingle/rtp.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c	Fri Dec 23 06:58:52 2011 +0000
@@ -577,11 +577,12 @@
 	guint num_params;
 
 	/* maybe this create ought to just be in initiate and handle initiate */
-	if (media == NULL)
+	if (media == NULL) {
 		media = jingle_rtp_create_media(content);
 
-	if (media == NULL)
-		return FALSE;
+		if (media == NULL)
+			return FALSE;
+	}
 
 	name = jingle_content_get_name(content);
 	media_type = jingle_rtp_get_media_type(content);
@@ -589,6 +590,16 @@
 	senders = jingle_content_get_senders(content);
 	transport = jingle_content_get_transport(content);
 
+	if (media_type == NULL) {
+		g_free(name);
+		g_free(remote_jid);
+		g_free(senders);
+		g_free(params);
+		g_object_unref(transport);
+		g_object_unref(session);
+		return FALSE;
+	}
+
 	if (JINGLE_IS_RAWUDP(transport))
 		transmitter = "rawudp";
 	else if (JINGLE_IS_ICEUDP(transport))
@@ -597,17 +608,17 @@
 		transmitter = "notransmitter";
 	g_object_unref(transport);
 
-	is_audio = !strcmp(media_type, "audio");
+	is_audio = g_str_equal(media_type, "audio");
 
-	if (!strcmp(senders, "both"))
-		type = is_audio == TRUE ? PURPLE_MEDIA_AUDIO
+	if (purple_strequal(senders, "both"))
+		type = is_audio ? PURPLE_MEDIA_AUDIO
 				: PURPLE_MEDIA_VIDEO;
-	else if ((strcmp(senders, "initiator") == 0) ==
+	else if (purple_strequal(senders, "initiator") ==
 			jingle_session_is_initiator(session))
-		type = is_audio == TRUE ? PURPLE_MEDIA_SEND_AUDIO
+		type = is_audio ? PURPLE_MEDIA_SEND_AUDIO
 				: PURPLE_MEDIA_SEND_VIDEO;
 	else
-		type = is_audio == TRUE ? PURPLE_MEDIA_RECV_AUDIO
+		type = is_audio ? PURPLE_MEDIA_RECV_AUDIO
 				: PURPLE_MEDIA_RECV_VIDEO;
 
 	params =
@@ -615,7 +626,17 @@
 			NULL, NULL, &num_params);
 
 	creator = jingle_content_get_creator(content);
-	if (!strcmp(creator, "initiator"))
+	if (creator == NULL) {
+		g_free(name);
+		g_free(media_type);
+		g_free(remote_jid);
+		g_free(senders);
+		g_free(params);
+		g_object_unref(session);
+		return FALSE;
+	}
+
+	if (g_str_equal(creator, "initiator"))
 		is_creator = jingle_session_is_initiator(session);
 	else
 		is_creator = !jingle_session_is_initiator(session);
@@ -624,6 +645,8 @@
 	if(!purple_media_add_stream(media, name, remote_jid,
 			type, is_creator, transmitter, num_params, params)) {
 		purple_media_end(media, NULL, NULL);
+		/* TODO: How much clean-up is necessary here? (does calling
+		         purple_media_end lead to cleaning up Jingle structs?) */
 		return FALSE;
 	}
 
@@ -645,9 +668,22 @@
 	const char *encoding_name,*id, *clock_rate;
 	PurpleMediaCodec *codec;
 	const gchar *media = xmlnode_get_attrib(description, "media");
-	PurpleMediaSessionType type =
-			!strcmp(media, "video") ? PURPLE_MEDIA_VIDEO :
-			!strcmp(media, "audio") ? PURPLE_MEDIA_AUDIO : 0;
+	PurpleMediaSessionType type;
+
+	if (media == NULL) {
+		purple_debug_warning("jingle-rtp", "missing media type\n");
+		return NULL;
+	}
+
+	if (g_str_equal(media, "video")) {
+		type = PURPLE_MEDIA_VIDEO;
+	} else if (g_str_equal(media, "audio")) {
+		type = PURPLE_MEDIA_AUDIO;
+	} else {
+		purple_debug_warning("jingle-rtp", "unknown media type: %s\n",
+				media);
+		return NULL;
+	}
 
 	for (codec_element = xmlnode_get_child(description, "payload-type") ;
 		 codec_element ;
@@ -768,19 +804,19 @@
 	switch (action) {
 		case JINGLE_SESSION_ACCEPT:
 		case JINGLE_SESSION_INITIATE: {
-			JingleSession *session = jingle_content_get_session(content);
-			JingleTransport *transport = jingle_transport_parse(
-					xmlnode_get_child(xmlcontent, "transport"));
-			xmlnode *description = xmlnode_get_child(xmlcontent, "description");
-			GList *candidates = jingle_rtp_transport_to_candidates(transport);
-			GList *codecs = jingle_rtp_parse_codecs(description);
-			gchar *name = jingle_content_get_name(content);
-			gchar *remote_jid =
-					jingle_session_get_remote_jid(session);
+			JingleSession *session;
+			JingleTransport *transport;
+			xmlnode *description;
+			GList *candidates;
+			GList *codecs;
+			gchar *name;
+			gchar *remote_jid;
 			PurpleMedia *media;
 
+			session = jingle_content_get_session(content);
+
 			if (action == JINGLE_SESSION_INITIATE &&
-					jingle_rtp_init_media(content) == FALSE) {
+					!jingle_rtp_init_media(content)) {
 				/* XXX: send error */
 				jabber_iq_send(jingle_session_terminate_packet(
 						session, "general-error"));
@@ -788,6 +824,14 @@
 				break;
 			}
 
+			transport = jingle_transport_parse(
+					xmlnode_get_child(xmlcontent, "transport"));
+			description = xmlnode_get_child(xmlcontent, "description");
+			candidates = jingle_rtp_transport_to_candidates(transport);
+			codecs = jingle_rtp_parse_codecs(description);
+			name = jingle_content_get_name(content);
+			remote_jid = jingle_session_get_remote_jid(session);
+
 			media = jingle_rtp_get_media(session);
 			purple_media_set_remote_codecs(media,
 					name, remote_jid, codecs);
--- a/libpurple/protocols/jabber/jingle/session.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/session.c	Fri Dec 23 06:58:52 2011 +0000
@@ -189,6 +189,8 @@
 jingle_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleSession *session;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_SESSION(object));
 
 	session = JINGLE_SESSION(object);
@@ -231,6 +233,8 @@
 jingle_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleSession *session;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_SESSION(object));
 
 	session = JINGLE_SESSION(object);
@@ -284,7 +288,7 @@
 	if (!js->sessions) {
 		purple_debug_info("jingle",
 				"Creating hash table for sessions\n");
-		js->sessions = g_hash_table_new(g_str_hash, g_str_equal);
+		js->sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 	}
 	purple_debug_info("jingle",
 			"inserting session with key: %s into table\n", sid);
@@ -407,26 +411,24 @@
 			xmlnode_new("jingle");
 	gchar *local_jid = jingle_session_get_local_jid(session);
 	gchar *remote_jid = jingle_session_get_remote_jid(session);
+	gchar *sid = jingle_session_get_sid(session);
 
 	xmlnode_set_namespace(jingle, JINGLE);
 	xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
 
 	if (jingle_session_is_initiator(session)) {
-		xmlnode_set_attrib(jingle, "initiator",
-				jingle_session_get_local_jid(session));
-		xmlnode_set_attrib(jingle, "responder",
-				jingle_session_get_remote_jid(session));
+		xmlnode_set_attrib(jingle, "initiator", local_jid);
+		xmlnode_set_attrib(jingle, "responder", remote_jid);
 	} else {
-		xmlnode_set_attrib(jingle, "initiator",
-				jingle_session_get_remote_jid(session));
-		xmlnode_set_attrib(jingle, "responder",
-				jingle_session_get_local_jid(session));
+		xmlnode_set_attrib(jingle, "initiator", remote_jid);
+		xmlnode_set_attrib(jingle, "responder", local_jid);
 	}
 
+	xmlnode_set_attrib(jingle, "sid", sid);
+
 	g_free(local_jid);
 	g_free(remote_jid);
-
-	xmlnode_set_attrib(jingle, "sid", jingle_session_get_sid(session));
+	g_free(sid);
 
 	return jingle;
 }
@@ -504,11 +506,16 @@
 JingleContent *
 jingle_session_find_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	GList *iter = session->priv->contents;
+	GList *iter;
+
+	if (name == NULL)
+		return NULL;
+
+	iter = session->priv->contents;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleContent *content = iter->data;
 		gchar *cname = jingle_content_get_name(content);
-		gboolean result = !strcmp(name, cname);
+		gboolean result = g_str_equal(name, cname);
 		g_free(cname);
 
 		if (creator != NULL) {
@@ -526,11 +533,16 @@
 JingleContent *
 jingle_session_find_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	GList *iter = session->priv->pending_contents;
+	GList *iter;
+
+	if (name == NULL)
+		return NULL;
+
+	iter = session->priv->pending_contents;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleContent *content = iter->data;
 		gchar *cname = jingle_content_get_name(content);
-		gboolean result = !strcmp(name, cname);
+		gboolean result = g_str_equal(name, cname);
 		g_free(cname);
 
 		if (creator != NULL) {
--- a/libpurple/protocols/jabber/jingle/transport.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/jingle/transport.c	Fri Dec 23 06:58:52 2011 +0000
@@ -108,6 +108,7 @@
 static void
 jingle_transport_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_TRANSPORT(object));
 
 	switch (prop_id) {
@@ -120,6 +121,7 @@
 static void
 jingle_transport_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_TRANSPORT(object));
 
 	switch (prop_id) {
@@ -170,6 +172,7 @@
 xmlnode *
 jingle_transport_to_xml(JingleTransport *transport, xmlnode *content, JingleActionType action)
 {
+	g_return_val_if_fail(transport != NULL, NULL);
 	g_return_val_if_fail(JINGLE_IS_TRANSPORT(transport), NULL);
 	return JINGLE_TRANSPORT_GET_CLASS(transport)->to_xml(transport, content, action);
 }
--- a/libpurple/protocols/jabber/oob.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/oob.c	Fri Dec 23 06:58:52 2011 +0000
@@ -119,10 +119,10 @@
 		jox->written_len = 0;
 	}
 
-	jox->writeh = purple_input_add(xfer->fd, PURPLE_INPUT_WRITE,
+	jox->writeh = purple_input_add(purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE,
 		jabber_oob_xfer_request_send, xfer);
 
-	jabber_oob_xfer_request_send(xfer, xfer->fd, PURPLE_INPUT_WRITE);
+	jabber_oob_xfer_request_send(xfer, purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE);
 }
 
 static gssize jabber_oob_xfer_read(guchar **buffer, PurpleXfer *xfer) {
@@ -131,14 +131,14 @@
 	char *tmp, *lenstr;
 	int len;
 
-	if((len = read(xfer->fd, test, sizeof(test))) > 0) {
+	if((len = read(purple_xfer_get_fd(xfer), test, sizeof(test))) > 0) {
 		jox->headers = g_string_append_len(jox->headers, test, len);
 		if((tmp = strstr(jox->headers->str, "\r\n\r\n"))) {
 			*tmp = '\0';
 			lenstr = strstr(jox->headers->str, "Content-Length: ");
 			if(lenstr) {
-				int size;
-				sscanf(lenstr, "Content-Length: %d", &size);
+				goffset size;
+				sscanf(lenstr, "Content-Length: %" G_GOFFSET_FORMAT, &size);
 				purple_xfer_set_size(xfer, size);
 			}
 			purple_xfer_set_read_fnc(xfer, NULL);
@@ -218,7 +218,7 @@
 	jox->headers = g_string_new("");
 	jox->iq_id = g_strdup(id);
 
-	xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from);
+	xfer = purple_xfer_new(purple_connection_get_account(js->gc), PURPLE_XFER_RECEIVE, from);
 	if (xfer)
 	{
 		purple_xfer_set_protocol_data(xfer, jox);
--- a/libpurple/protocols/jabber/presence.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/presence.c	Fri Dec 23 06:58:52 2011 +0000
@@ -459,7 +459,7 @@
 					hash = jabber_calculate_data_hash(data, size, "sha1");
 			}
 
-			purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash);
+			purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, data, size, hash);
 
 			g_free(hash);
 		}
--- a/libpurple/protocols/jabber/roster.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/roster.c	Fri Dec 23 06:58:52 2011 +0000
@@ -96,7 +96,7 @@
 {
 	GSList *buddies, *l;
 
-	buddies = purple_find_buddies(js->gc->account, jid);
+	buddies = purple_find_buddies(purple_connection_get_account(js->gc), jid);
 
 	for(l = buddies; l; l = l->next)
 		purple_blist_remove_buddy(l->data);
@@ -110,7 +110,7 @@
 	GSList *buddies, *l;
 	PurpleAccount *account = purple_connection_get_account(js->gc);
 
-	buddies = purple_find_buddies(js->gc->account, jid);
+	buddies = purple_find_buddies(purple_connection_get_account(js->gc), jid);
 
 	if(!groups) {
 		if(!buddies)
@@ -304,7 +304,7 @@
 	if (js->currently_parsing_roster_push)
 		return;
 
-	if(!(b = purple_find_buddy(js->gc->account, name)))
+	if(!(b = purple_find_buddy(purple_connection_get_account(js->gc), name)))
 		return;
 
 	if (groups) {
@@ -314,7 +314,7 @@
 		                  "groups]: groups: %s\n", name, tmp);
 		g_free(tmp);
 	} else {
-		GSList *buddies = purple_find_buddies(js->gc->account, name);
+		GSList *buddies = purple_find_buddies(purple_connection_get_account(js->gc), name);
 		char *tmp;
 
 		if(!buddies)
@@ -413,7 +413,7 @@
 	} else if(!jb || !(jb->subscription & JABBER_SUB_TO)) {
 		jabber_presence_subscription_set(js, who, "subscribe");
 	} else if((jbr =jabber_buddy_find_resource(jb, NULL))) {
-		purple_prpl_got_user_status(gc->account, who,
+		purple_prpl_got_user_status(purple_connection_get_account(gc), who,
 				jabber_buddy_state_get_status_id(jbr->state),
 				"priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL);
 	}
@@ -423,7 +423,7 @@
 
 void jabber_roster_alias_change(PurpleConnection *gc, const char *name, const char *alias)
 {
-	PurpleBuddy *b = purple_find_buddy(gc->account, name);
+	PurpleBuddy *b = purple_find_buddy(purple_connection_get_account(gc), name);
 
 	if(b != NULL) {
 		purple_blist_alias_buddy(b, alias);
@@ -446,7 +446,7 @@
 	if(!old_group || !new_group || !strcmp(old_group, new_group))
 		return;
 
-	buddies = purple_find_buddies(gc->account, name);
+	buddies = purple_find_buddies(purple_connection_get_account(gc), name);
 	while(buddies) {
 		b = buddies->data;
 		g = purple_buddy_get_group(b);
--- a/libpurple/protocols/jabber/si.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/si.c	Fri Dec 23 06:58:52 2011 +0000
@@ -393,8 +393,8 @@
 	if (jsx->rxlen < jsx->rxmaxlen)
 		return;
 
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
+	purple_input_remove(purple_xfer_get_watcher(xfer));
+	purple_xfer_set_watcher(xfer, 0);
 	g_free(jsx->rxqueue);
 	jsx->rxqueue = NULL;
 
@@ -462,8 +462,8 @@
 	if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2)
 		return;
 
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
+	purple_input_remove(purple_xfer_get_watcher(xfer));
+	purple_xfer_set_watcher(xfer, 0);
 
 	dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id,
 			jsx->js->user->node, jsx->js->user->domain,
@@ -508,8 +508,8 @@
 	jsx->rxqueue[5+strlen(host)] = 0x00;
 	jsx->rxqueue[6+strlen(host)] = 0x00;
 
-	xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-		jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer);
+	purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
+		jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer));
 	jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source,
 		PURPLE_INPUT_WRITE);
 }
@@ -539,9 +539,9 @@
 
 	/* If we sent a "Success", wait for a response, otherwise give up and cancel */
 	if (jsx->rxqueue[1] == 0x00) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ,
-			jabber_si_xfer_bytestreams_send_read_again_cb, xfer);
+		purple_input_remove(purple_xfer_get_watcher(xfer));
+		purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_READ,
+			jabber_si_xfer_bytestreams_send_read_again_cb, xfer));
 		g_free(jsx->rxqueue);
 		jsx->rxqueue = NULL;
 		jsx->rxlen = 0;
@@ -563,7 +563,7 @@
 
 	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n");
 
-	xfer->fd = source;
+	purple_xfer_set_fd(xfer, source);
 
 	/** Try to read the SOCKS5 header */
 	if(jsx->rxlen < 2) {
@@ -619,10 +619,10 @@
 			jsx->rxqueue = g_malloc(jsx->rxmaxlen);
 			jsx->rxqueue[0] = 0x05;
 			jsx->rxqueue[1] = 0x00;
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
+			purple_input_remove(purple_xfer_get_watcher(xfer));
+			purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
 				jabber_si_xfer_bytestreams_send_read_response_cb,
-				xfer);
+				xfer));
 			jabber_si_xfer_bytestreams_send_read_response_cb(xfer,
 				source, PURPLE_INPUT_WRITE);
 			jsx->rxqueue = NULL;
@@ -637,9 +637,9 @@
 	jsx->rxqueue = g_malloc(jsx->rxmaxlen);
 	jsx->rxqueue[0] = 0x05;
 	jsx->rxqueue[1] = 0xFF;
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-		jabber_si_xfer_bytestreams_send_read_response_cb, xfer);
+	purple_input_remove(purple_xfer_get_watcher(xfer));
+	purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
+		jabber_si_xfer_bytestreams_send_read_response_cb, xfer));
 	jabber_si_xfer_bytestreams_send_read_response_cb(xfer,
 		source, PURPLE_INPUT_WRITE);
 }
@@ -674,7 +674,7 @@
 		return;
 	}
 
-	purple_input_remove(xfer->watcher);
+	purple_input_remove(purple_xfer_get_watcher(xfer));
 	close(source);
 	jsx->local_streamhost_fd = -1;
 
@@ -684,8 +684,8 @@
 	fcntl(acceptfd, F_SETFD, FD_CLOEXEC);
 #endif
 
-	xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ,
-					 jabber_si_xfer_bytestreams_send_read_cb, xfer);
+	purple_xfer_set_watcher(xfer, purple_input_add(acceptfd, PURPLE_INPUT_READ,
+					 jabber_si_xfer_bytestreams_send_read_cb, xfer));
 }
 
 static void
@@ -761,7 +761,7 @@
 			jsx->js->user->domain, jsx->js->user->resource);
 		if (!strcmp(jid, my_jid)) {
 			purple_debug_info("jabber", "Got local SOCKS5 streamhost-used.\n");
-			purple_xfer_start(xfer, xfer->fd, NULL, -1);
+			purple_xfer_start(xfer, purple_xfer_get_fd(xfer), NULL, -1);
 		} else {
 			/* if available, try to revert to IBB... */
 			if (jsx->stream_method & STREAM_METHOD_IBB) {
@@ -785,9 +785,9 @@
 	}
 
 	/* Clean up the local streamhost - it isn't going to be used.*/
-	if (xfer->watcher > 0) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
+	if (purple_xfer_get_watcher(xfer) > 0) {
+		purple_input_remove(purple_xfer_get_watcher(xfer));
+		purple_xfer_set_watcher(xfer, 0);
 	}
 	if (jsx->local_streamhost_fd >= 0) {
 		close(jsx->local_streamhost_fd);
@@ -845,7 +845,7 @@
 
 		jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
 			jsx->js->user->domain, jsx->js->user->resource);
-		xfer->local_port = purple_network_get_port_from_fd(sock);
+		purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock));
 		g_snprintf(port, sizeof(port), "%hu", purple_xfer_get_local_port(xfer));
 
 		public_ip = purple_network_get_my_ip(jsx->js->fd);
@@ -876,8 +876,8 @@
 		g_free(jid);
 
 		/* The listener for the local proxy */
-		xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ,
-				jabber_si_xfer_bytestreams_send_connected_cb, xfer);
+		purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ,
+				jabber_si_xfer_bytestreams_send_connected_cb, xfer));
 	}
 
 	for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) {
@@ -1099,7 +1099,7 @@
 jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess)
 {
 	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-	gsize remaining = purple_xfer_get_bytes_remaining(xfer);
+	goffset remaining = purple_xfer_get_bytes_remaining(xfer);
 
 	if (remaining == 0) {
 		/* close the session */
@@ -1240,7 +1240,7 @@
 	file = xmlnode_new_child(si, "file");
 	xmlnode_set_namespace(file, NS_SI_FILE_TRANSFER);
 	xmlnode_set_attrib(file, "name", purple_xfer_get_filename(xfer));
-	g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
+	g_snprintf(buf, sizeof(buf), "%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer));
 	xmlnode_set_attrib(file, "size", buf);
 	/* maybe later we'll do hash and date attribs */
 
@@ -1304,9 +1304,9 @@
 			jabber_iq_remove_callback_by_id(js, jsx->iq_id);
 		if (jsx->local_streamhost_fd >= 0)
 			close(jsx->local_streamhost_fd);
-		if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xfer->fd >= 0) {
+		if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && purple_xfer_get_fd(xfer) >= 0) {
 			purple_debug_info("jabber", "remove port mapping\n");
-			purple_network_remove_port_mapping(xfer->fd);
+			purple_network_remove_port_mapping(purple_xfer_get_fd(xfer));
 		}
 		if (jsx->connect_timeout > 0)
 			purple_timeout_remove(jsx->connect_timeout);
@@ -1561,7 +1561,7 @@
 
 			purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields,
 					_("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb),
-					jsx->js->gc->account, purple_xfer_get_remote_user(xfer), NULL, xfer);
+					purple_connection_get_account(jsx->js->gc), purple_xfer_get_remote_user(xfer), NULL, xfer);
 
 			g_free(msg);
 		}
@@ -1617,7 +1617,7 @@
 
 	js = purple_connection_get_protocol_data(gc);
 
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
 	if (xfer)
 	{
 		jsx = g_new0(JabberSIXfer, 1);
@@ -1676,8 +1676,7 @@
 	xmlnode *thumbnail;
 #endif
 	const char *stream_id, *filename, *filesize_c, *profile;
-	guint64 filesize_64 = 0;
-	size_t filesize = 0;
+	goffset filesize = 0;
 
 	if(!(profile = xmlnode_get_attrib(si, "profile")) ||
 			strcmp(profile, NS_SI_FILE_TRANSFER))
@@ -1693,17 +1692,7 @@
 		return;
 
 	if((filesize_c = xmlnode_get_attrib(file, "size")))
-		filesize_64 = g_ascii_strtoull(filesize_c, NULL, 10);
-	/* TODO 3.0.0: When the core uses a guint64, this is redundant.
-	 * See #8477.
-	 */
-	if (filesize_64 > G_MAXSIZE) {
-		/* Should this pop up a warning? */
-		purple_debug_warning("jabber", "Unable to transfer file (too large)"
-		                     " -- see #8477 for more details.");
-		return;
-	}
-	filesize = filesize_64;
+		filesize = g_ascii_strtoull(filesize_c, NULL, 10);
 
 	if(!(feature = xmlnode_get_child(si, "feature")))
 		return;
@@ -1754,7 +1743,7 @@
 	jsx->stream_id = g_strdup(stream_id);
 	jsx->iq_id = g_strdup(id);
 
-	xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from);
+	xfer = purple_xfer_new(purple_connection_get_account(js->gc), PURPLE_XFER_RECEIVE, from);
 	g_return_if_fail(xfer != NULL);
 
 	purple_xfer_set_protocol_data(xfer, jsx);
--- a/libpurple/protocols/jabber/usermood.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Fri Dec 23 06:58:52 2011 +0000
@@ -155,12 +155,12 @@
 		   break;
 	}
 	if (newmood != NULL) {
-		purple_prpl_got_user_status(js->gc->account, from, "mood",
+		purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "mood",
 				PURPLE_MOOD_NAME, newmood,
 				PURPLE_MOOD_COMMENT, moodtext,
 				NULL);
 	} else {
-		purple_prpl_got_user_status_deactive(js->gc->account, from, "mood");
+		purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), from, "mood");
 	}
 	g_free(moodtext);
 }
--- a/libpurple/protocols/jabber/usertune.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/jabber/usertune.c	Fri Dec 23 06:58:52 2011 +0000
@@ -92,7 +92,7 @@
 	}
 
 	if (valid) {
-		purple_prpl_got_user_status(js->gc->account, from, "tune",
+		purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "tune",
 				PURPLE_TUNE_ARTIST, tuneinfodata.artist,
 				PURPLE_TUNE_TITLE, tuneinfodata.title,
 				PURPLE_TUNE_ALBUM, tuneinfodata.album,
@@ -100,7 +100,7 @@
 				PURPLE_TUNE_TIME, tuneinfodata.time,
 				PURPLE_TUNE_URL, tuneinfodata.url, NULL);
 	} else {
-		purple_prpl_got_user_status_deactive(js->gc->account, from, "tune");
+		purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), from, "tune");
 	}
 
 	g_free(tuneinfodata.artist);
--- a/libpurple/protocols/msn/httpconn.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/httpconn.c	Fri Dec 23 06:58:52 2011 +0000
@@ -287,7 +287,7 @@
 
 	if (servconn->type == MSN_SERVCONN_NS) {
 		PurpleConnection *gc = purple_account_get_connection(servconn->session->account);
-		gc->last_received = time(NULL);
+		purple_connection_update_last_received(gc);
 	}
 
 	len = read(httpconn->fd, buf, sizeof(buf) - 1);
--- a/libpurple/protocols/msn/msg.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/msg.c	Fri Dec 23 06:58:52 2011 +0000
@@ -688,7 +688,7 @@
 				swboard->flag |= MSN_SB_FLAG_IM;
 			}
 		}
-		else if (!g_str_equal(passport, purple_account_get_username(gc->account)))
+		else if (!g_str_equal(passport, purple_account_get_username(purple_connection_get_account(gc))))
 		{
 			/* Don't im ourselves ... */
 			serv_got_im(gc, passport, body_final, 0, time(NULL));
--- a/libpurple/protocols/msn/msn.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/msn.c	Fri Dec 23 06:58:52 2011 +0000
@@ -881,7 +881,7 @@
 
 	session = purple_connection_get_protocol_data(gc);
 
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
 
 	g_return_val_if_fail(xfer != NULL, NULL);
 
@@ -1354,8 +1354,9 @@
 	session = msn_session_new(account);
 
 	purple_connection_set_protocol_data(gc, session);
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR |
-		PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
+	purple_connection_set_flags(gc, 
+		PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR |
+		PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY);
 
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_START);
 
@@ -1526,7 +1527,7 @@
 			PurpleMessageFlags flags)
 {
 	PurpleAccount *account;
-	PurpleBuddy *buddy = purple_find_buddy(gc->account, who);
+	PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(gc), who);
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
 	MsnMessage *msg;
--- a/libpurple/protocols/msn/notification.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/notification.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1193,7 +1193,7 @@
 	if (id && strcmp(id, "1")) {
 		PurpleConversation *conv
 			= purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-			                                        who, gc->account);
+			                                        who, purple_connection_get_account(gc));
 		if (conv != NULL) {
 			const char *error;
 			if (!strcmp(id, "407"))
--- a/libpurple/protocols/msn/servconn.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/servconn.c	Fri Dec 23 06:58:52 2011 +0000
@@ -423,7 +423,7 @@
 
 	if (servconn->type == MSN_SERVCONN_NS) {
 		PurpleConnection *gc = purple_account_get_connection(servconn->session->account);
-		gc->last_received = time(NULL);
+		purple_connection_update_last_received(gc);
 	}
 
 	len = read(servconn->fd, buf, sizeof(buf) - 1);
--- a/libpurple/protocols/msn/slp.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/slp.c	Fri Dec 23 06:58:52 2011 +0000
@@ -291,7 +291,7 @@
 static gchar *
 gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
 {
-	gsize size = 0;
+	goffset size = 0;
 	MsnFileContext context;
 	gchar *u8 = NULL;
 	gchar *ret;
@@ -322,7 +322,7 @@
 
 	preview = purple_xfer_get_thumbnail(xfer, &preview_len);
 
-	context.length = MSN_FILE_CONTEXT_SIZE;
+	context.length = MSN_FILE_CONTEXT_SIZE_V2;
 	context.version = 2; /* V.3 contains additional unnecessary data */
 	context.file_size = size;
 	if (preview)
@@ -336,15 +336,17 @@
 	}
 	memset(&context.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
 
+#if 0
 	memset(&context.unknown1, 0, sizeof(context.unknown1));
 	context.unknown2 = 0xffffffff;
+#endif
 
 	/* Mind the cast, as in, don't free it after! */
 	context.preview = (char *)preview;
 	context.preview_len = preview_len;
 
 	u8 = msn_file_context_to_wire(&context);
-	ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE + preview_len);
+	ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE_V2 + preview_len);
 
 	g_free(uni);
 	g_free(u8);
--- a/libpurple/protocols/msn/slpcall.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Fri Dec 23 06:58:52 2011 +0000
@@ -512,7 +512,6 @@
 		MsnFileContext *file_context;
 		char *buf;
 		gsize bin_len;
-		guint32 file_size;
 		char *file_name;
 
 		account = slpcall->slplink->session->account;
@@ -529,8 +528,6 @@
 		file_context = msn_file_context_from_wire(buf, bin_len);
 
 		if (file_context != NULL) {
-			file_size = file_context->file_size;
-
 			file_name = g_convert((const gchar *)&file_context->file_name,
 			                      MAX_FILE_NAME_LEN * 2,
 			                      "UTF-8", "UTF-16LE",
@@ -538,7 +535,7 @@
 
 			purple_xfer_set_filename(xfer, file_name ? file_name : "");
 			g_free(file_name);
-			purple_xfer_set_size(xfer, file_size);
+			purple_xfer_set_size(xfer, file_context->file_size);
 			purple_xfer_set_init_fnc(xfer, msn_xfer_init);
 			purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
 			purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
@@ -1145,8 +1142,6 @@
 
 			if (slpcall->cb)
 				slpcall->cb(slpcall, body, body_len);
-
-			slpcall->wasted = TRUE;
 		}
 	}
 	else if (msn_p2p_info_is_ack(slpmsg->p2p_info))
--- a/libpurple/protocols/msn/slpmsg.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/slpmsg.c	Fri Dec 23 06:58:52 2011 +0000
@@ -239,7 +239,7 @@
 
 }
 
-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
+MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, goffset size)
 {
 	MsnSlpMessage *slpmsg;
 
--- a/libpurple/protocols/msn/slpmsg.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/slpmsg.h	Fri Dec 23 06:58:52 2011 +0000
@@ -133,7 +133,7 @@
  *
  * @return A new SlpMessage with the file transfer info.
  */
-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size);
+MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, goffset size);
 
 /**
  * Serialize the MsnSlpMessage in a way it can be used to be transmited
--- a/libpurple/protocols/msn/xfer.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/xfer.c	Fri Dec 23 06:58:52 2011 +0000
@@ -166,7 +166,7 @@
 {
 	gchar *ret, *tmp;
 
-	tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE + context->preview_len + 1);
+	tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE_V2 + context->preview_len + 1);
 
 	msn_push32le(tmp, context->length);
 	msn_push32le(tmp, context->version);
@@ -174,9 +174,15 @@
 	msn_push32le(tmp, context->type);
 	memcpy(tmp, context->file_name, MAX_FILE_NAME_LEN * 2);
 	tmp += MAX_FILE_NAME_LEN * 2;
+#if 0
 	memcpy(tmp, context->unknown1, sizeof(context->unknown1));
 	tmp += sizeof(context->unknown1);
 	msn_push32le(tmp, context->unknown2);
+#else
+	memset(tmp, 0, sizeof(gchar[30]));
+	tmp += sizeof(gchar[30]);
+	msn_push32le(tmp, 0xffffffff);
+#endif
 	if (context->preview) {
 		memcpy(tmp, context->preview, context->preview_len);
 	}
@@ -190,21 +196,30 @@
 {
 	MsnFileContext *context;
 
-	if (!buf || len < MSN_FILE_CONTEXT_SIZE)
+	if (!buf || len < MSN_FILE_CONTEXT_SIZE_V0)
 		return NULL;
 
 	context = g_new(MsnFileContext, 1);
 
 	context->length = msn_pop32le(buf);
 	context->version = msn_pop32le(buf);
-	if (context->version == 2) {
-		/* The length field is broken for this version. No check. */
-		context->length = MSN_FILE_CONTEXT_SIZE;
-	} else if (context->version == 3) {
-		if (context->length != MSN_FILE_CONTEXT_SIZE + 63) {
+	if (context->version == 0) {
+		if (context->length != MSN_FILE_CONTEXT_SIZE_V0) {
 			g_free(context);
 			return NULL;
-		} else if (len < MSN_FILE_CONTEXT_SIZE + 63) {
+		}
+	} else if (context->version == 2) {
+		/* The length field is broken for this version. No check. */
+		context->length = MSN_FILE_CONTEXT_SIZE_V2;
+		if (len < MSN_FILE_CONTEXT_SIZE_V2) {
+			g_free(context);
+			return NULL;
+		}
+	} else if (context->version == 3) {
+		if (context->length != MSN_FILE_CONTEXT_SIZE_V3) {
+			g_free(context);
+			return NULL;
+		} else if (len < MSN_FILE_CONTEXT_SIZE_V3) {
 			g_free(context);
 			return NULL;
 		}
@@ -218,9 +233,15 @@
 	context->type = msn_pop32le(buf);
 	memcpy(context->file_name, buf, MAX_FILE_NAME_LEN * 2);
 	buf += MAX_FILE_NAME_LEN * 2;
-	memcpy(context->unknown1, buf, sizeof(context->unknown1));
-	buf += sizeof(context->unknown1);
-	context->unknown2 = msn_pop32le(buf);
+	if (context->version > 0) {
+#if 0
+		memcpy(context->unknown1, buf, sizeof(context->unknown1));
+		buf += sizeof(context->unknown1);
+		context->unknown2 = msn_pop32le(buf);
+#else
+		buf += sizeof(gchar[30]) + sizeof(guint32);
+#endif
+	}
 
 	if (context->type == 0 && len > context->length) {
 		context->preview_len = len - context->length;
--- a/libpurple/protocols/msn/xfer.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/msn/xfer.h	Fri Dec 23 06:58:52 2011 +0000
@@ -39,13 +39,17 @@
 	guint64   file_size;    /*< Size of file */
 	guint32   type;         /*< Transfer type */
 	gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
+#if 0
 	gchar     unknown1[30]; /*< Used somehow for background sharing */
 	guint32   unknown2;     /*< Possibly for background sharing as well */
+#endif
 	gchar     *preview;     /*< File preview data, 96x96 PNG */
 	gsize     preview_len;
 } MsnFileContext;
 
-#define MSN_FILE_CONTEXT_SIZE (4*4 + 1*8 + 2*MAX_FILE_NAME_LEN + 30)
+#define MSN_FILE_CONTEXT_SIZE_V0 (4*3 + 1*8 + 2*MAX_FILE_NAME_LEN)
+#define MSN_FILE_CONTEXT_SIZE_V2 (MSN_FILE_CONTEXT_SIZE_V0 + 4*1 + 30)
+#define MSN_FILE_CONTEXT_SIZE_V3 (MSN_FILE_CONTEXT_SIZE_V2 + 63)
 
 void msn_xfer_init(PurpleXfer *xfer);
 void msn_xfer_cancel(PurpleXfer *xfer);
--- a/libpurple/protocols/mxit/filexfer.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/filexfer.c	Fri Dec 23 06:58:52 2011 +0000
@@ -124,7 +124,7 @@
 	if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
 		/* we are trying to send a file to MXit */
 
-		if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) {
+		if ( purple_xfer_get_size( xfer ) > ( CP_MAX_PACKET - 1000 ) ) {	/* need to reserve some space for packet headers */
 			/* the file is too big */
 			purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "The file you are trying to send is too large!" ) );
 			purple_xfer_cancel_local( xfer );
@@ -139,7 +139,7 @@
 		 * we have just accepted a file transfer request from MXit.  send a confirmation
 		 * to the MXit server so that can send us the file
 		 */
-		mxit_send_file_accept( mx->session, mx->fileid, purple_xfer_get_size( xfer ), 0 );
+		mxit_send_file_accept( mx->session, mx->fileid, (int) purple_xfer_get_size( xfer ), 0 );
 	}
 }
 
@@ -151,7 +151,7 @@
  */
 static void mxit_xfer_start( PurpleXfer* xfer )
 {
-	size_t			filesize;
+	goffset			filesize;
 	unsigned char*	buffer;
 	int				size;
 	int				wrote;
@@ -427,15 +427,12 @@
 void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen )
 {
 	PurpleXfer*			xfer	= NULL;
-	struct mxitxfer*	mx		= NULL;
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen );
 
 	/* find the file-transfer object */
 	xfer = find_mxit_xfer( session, fileid );
 	if ( xfer ) {
-		mx = purple_xfer_get_protocol_data( xfer );
-
 		/* this is the transfer we have been looking for */
 		purple_xfer_ref( xfer );
 		purple_xfer_start( xfer, -1, NULL, 0 );
--- a/libpurple/protocols/mxit/formcmds.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/formcmds.c	Fri Dec 23 06:58:52 2011 +0000
@@ -25,7 +25,7 @@
 
 
 #include "internal.h"
-#include <glib/gprintf.h>
+#include <glib.h>
 
 #include "purple.h"
 
--- a/libpurple/protocols/mxit/login.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/login.c	Fri Dec 23 06:58:52 2011 +0000
@@ -69,7 +69,12 @@
 
 	/* configure the connection (reference: "libpurple/connection.h") */
 	purple_connection_set_protocol_data( con, session );
-	con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS;
+	purple_connection_set_flags( con,
+			  PURPLE_CONNECTION_NO_BGCOLOR
+			| PURPLE_CONNECTION_NO_URLDESC
+			| PURPLE_CONNECTION_HTML
+			| PURPLE_CONNECTION_SUPPORT_MOODS
+	);
 
 	/* configure the session (reference: "libpurple/account.h") */
 	g_strlcpy( session->server, purple_account_get_string( account, MXIT_CONFIG_SERVER_ADDR, DEFAULT_SERVER ), sizeof( session->server ) );
@@ -171,7 +176,7 @@
 	session->fd = source;
 
 	/* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
-	session->con->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session );
+	session->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session );
 
 	mxit_connected( session );
 }
@@ -562,6 +567,7 @@
 			MXIT_CAPTCHA_WIDTH,
 			time( NULL )
 	);
+	/* FIXME: This should be cancelled somewhere if not needed. */
 	url_data = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_clientinfo2, session );
 
 #ifdef	DEBUG_PROTOCOL
@@ -726,6 +732,7 @@
 
 	/* reference: "libpurple/util.h" */
 	url = g_strdup_printf( "%s/res/?type=challenge&getcountries=true&getlanguage=true&getimage=true&h=%i&w=%i&ts=%li", wapserver, MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
+	/* FIXME: This should be cancelled somewhere if not needed. */
 	url_data = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_clientinfo1, session );
 
 #ifdef	DEBUG_PROTOCOL
@@ -775,9 +782,9 @@
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_reconnect\n" );
 
 	/* remove the input cb function */
-	if ( session->con->inpa ) {
-		purple_input_remove( session->con->inpa );
-		session->con->inpa = 0;
+	if ( session->inpa ) {
+		purple_input_remove( session->inpa );
+		session->inpa = 0;
 	}
 
 	/* close existing connection */
--- a/libpurple/protocols/mxit/markup.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/markup.c	Fri Dec 23 06:58:52 2011 +0000
@@ -628,6 +628,7 @@
 
 	/* reference: "libpurple/util.h" */
 	url = g_strdup_printf( "%s/res/?type=emo&mlh=%i&sc=%s&ts=%li", wapserver, MXIT_EMOTICON_SIZE, id, time( NULL ) );
+	/* FIXME: This should be cancelled somewhere if not needed. */
 	url_data = purple_util_fetch_url( url, TRUE, NULL, TRUE, -1, emoticon_returned, mx );
 	g_free( url );
 }
--- a/libpurple/protocols/mxit/mxit.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/mxit.c	Fri Dec 23 06:58:52 2011 +0000
@@ -176,7 +176,7 @@
 	const char*			who;
 	char*				tmp;
 
-	gc = purple_conversation_get_gc( conv );
+	gc = purple_conversation_get_connection( conv );
 	if ( session->con != gc ) {
 		/* not our conversation */
 		return;
--- a/libpurple/protocols/mxit/mxit.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/mxit.h	Fri Dec 23 06:58:52 2011 +0000
@@ -161,6 +161,7 @@
 	/* libpurple */
 	PurpleAccount*		acc;						/* pointer to the libpurple internal account struct */
 	PurpleConnection*	con;						/* pointer to the libpurple internal connection struct */
+	guint				inpa;						/* the input watcher */
 
 	/* transmit */
 	struct tx_queue		queue;						/* transmit packet queue (FIFO mode) */
--- a/libpurple/protocols/mxit/protocol.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.c	Fri Dec 23 06:58:52 2011 +0000
@@ -718,7 +718,7 @@
 								"%s%c%i%c%s%c%s%c"			/* dateOfBirth\1gender\1location\1capabilities\1 */
 								"%s%c%i%c%s%c%s"			/* dc\1features\1dialingcode\1locale */
 								"%c%i%c%i",					/* \1protocolVer\1lastRosterUpdate */
-								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
+								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_PACKET, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
 								profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM,
 								session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale,
 								CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
@@ -765,7 +765,7 @@
 								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, 1, CP_FLD_TERM,
 								MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM,
 								session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
-								CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
+								CP_MAX_PACKET, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
 	);
 
 	/* include "custom resource" information */
@@ -2819,9 +2819,9 @@
 	}
 
 	/* remove the input cb function */
-	if ( session->con->inpa ) {
-		purple_input_remove( session->con->inpa );
-		session->con->inpa = 0;
+	if ( session->inpa ) {
+		purple_input_remove( session->inpa );
+		session->inpa = 0;
 	}
 
 	/* remove HTTP poll timer */
--- a/libpurple/protocols/mxit/protocol.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.h	Fri Dec 23 06:58:52 2011 +0000
@@ -34,8 +34,7 @@
 #define		CP_PKT_TERM				'\x02'				/* packet terminator */
 
 
-#define		CP_MAX_PACKET			( 1024 * 1024 )		/* maximum client protocol packet size (1 MiB) */
-#define		CP_MAX_FILESIZE			( 150 * 1000 )		/* maximum client protocol file transfer size (150 KB) */
+#define		CP_MAX_PACKET			( 1 * 1000 * 1000 )	/* maximum client protocol packet size (1 MB) */
 #define		MXIT_EMOTICON_SIZE		18					/* icon size for custom emoticons */
 #define		CP_MAX_STATUS_MSG		250					/* maximum status message length (in characters) */
 
@@ -77,6 +76,7 @@
 #define		MXIT_CF_GAMING_UPDATE	0x800000
 #define		MXIT_CF_VOICE			0x1000000
 #define		MXIT_CF_VIDEO			0x2000000
+#define		MXIT_CF_TOUCHSCREEN		0x4000000
 
 /* Client features supported by this implementation */
 #define		MXIT_CP_FEATURES		( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 )
--- a/libpurple/protocols/myspace/myspace.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Fri Dec 23 06:58:52 2011 +0000
@@ -2167,8 +2167,7 @@
 	}
 
 	session->fd = source;
-
-	gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc);
+	session->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc);
 }
 
 /**
@@ -2190,7 +2189,7 @@
 
 	gc = purple_account_get_connection(acct);
 	purple_connection_set_protocol_data(gc, msim_session_new(acct));
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC);
 
 	/*
 	 * Lets wipe out our local list of blocked buddies.  We'll get a
@@ -2263,8 +2262,9 @@
 
 	purple_connection_set_protocol_data(gc, NULL);
 
-	if (session->gc->inpa) {
-		purple_input_remove(session->gc->inpa);
+	if (session->inpa) {
+		purple_input_remove(session->inpa);
+		session->inpa = 0;
 	}
 	if (session->fd >= 0) {
 		close(session->fd);
--- a/libpurple/protocols/myspace/session.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/myspace/session.h	Fri Dec 23 06:58:52 2011 +0000
@@ -38,6 +38,7 @@
 	int privacy_mode;                   /**< This is a bitmask */
 	int offline_message_mode;
 	gint fd;                            /**< File descriptor to/from server */
+	guint inpa;							/**< The input watcher */
 
 	/* TODO: Remove. */
 	GHashTable *user_lookup_cb;         /**< Username -> userid lookup callback */
--- a/libpurple/protocols/myspace/zap.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/myspace/zap.c	Fri Dec 23 06:58:52 2011 +0000
@@ -135,7 +135,7 @@
 	session = purple_connection_get_protocol_data(gc);
 
 	/* Look for this attention type, by the code index given. */
-	types = msim_attention_types(gc->account);
+	types = msim_attention_types(purple_connection_get_account(gc));
 	attn = (PurpleAttentionType *)g_list_nth_data(types, code);
 
 	if (!attn) {
--- a/libpurple/protocols/novell/novell.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/novell/novell.c	Fri Dec 23 06:58:52 2011 +0000
@@ -131,8 +131,8 @@
 				/* Don't attempt to auto-reconnect if our
 				 * password was invalid.
 				 */
-				if (!purple_account_get_remember_password(gc->account))
-					purple_account_set_password(gc->account, NULL);
+				if (!purple_account_get_remember_password(purple_connection_get_account(gc)))
+					purple_account_set_password(purple_connection_get_account(gc), NULL);
 				reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 				break;
 			default:
@@ -741,16 +741,16 @@
 
 		if (allowed) {
 
-			if (!g_slist_find_custom(gc->account->permit,
+			if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 									 display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
-				purple_privacy_permit_add(gc->account, display_id, TRUE);
+				purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE);
 			}
 
 		} else {
 
-			if (!g_slist_find_custom(gc->account->permit,
+			if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 									 display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
-				purple_privacy_deny_add(gc->account, display_id, TRUE);
+				purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE);
 			}
 		}
 
@@ -789,10 +789,10 @@
 
 		if (display_id) {
 
-			if (!g_slist_find_custom(gc->account->deny,
+			if (!g_slist_find_custom(purple_connection_get_account(gc)->deny,
 									 display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
 
-				purple_privacy_deny_add(gc->account, display_id, TRUE);
+				purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE);
 			}
 
 		} else {
@@ -840,11 +840,11 @@
 
 		if (display_id) {
 
-			if (!g_slist_find_custom(gc->account->permit,
+			if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 									 display_id,
 									 (GCompareFunc)purple_utf8_strcasecmp)) {
 
-				purple_privacy_permit_add(gc->account, display_id, TRUE);
+				purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE);
 			}
 
 		} else {
@@ -1177,7 +1177,6 @@
 	const char *dn;
 	const char *name;
 	int idle = 0;
-	gboolean loggedin = TRUE;
 
 	account = purple_buddy_get_account(buddy);
 	name = purple_buddy_get_name(buddy);
@@ -1194,7 +1193,6 @@
 			break;
 		case NM_STATUS_OFFLINE:
 			status_id = NOVELL_STATUS_TYPE_OFFLINE;
-			loggedin = FALSE;
 			break;
 		case NM_STATUS_AWAY_IDLE:
 			status_id = NOVELL_STATUS_TYPE_AWAY;
@@ -1202,7 +1200,6 @@
 			break;
 		default:
 			status_id = NOVELL_STATUS_TYPE_OFFLINE;
-			loggedin = FALSE;
 			break;
 	}
 
@@ -1404,15 +1401,15 @@
 	/* Set the Purple privacy setting */
 	if (user->default_deny) {
 		if (user->allow_list == NULL) {
-			purple_account_set_privacy_type(gc->account, PURPLE_PRIVACY_DENY_ALL);
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_ALL);
 		} else {
-			purple_account_set_privacy_type(gc->account, PURPLE_PRIVACY_ALLOW_USERS);
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_USERS);
 		}
 	} else {
 		if (user->deny_list == NULL) {
-			purple_account_set_privacy_type(gc->account, PURPLE_PRIVACY_ALLOW_ALL);
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_ALL);
 		} else {
-			purple_account_set_privacy_type(gc->account, PURPLE_PRIVACY_DENY_USERS);
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_USERS);
 		}
 	}
 
@@ -1424,9 +1421,9 @@
 		else
 			name =(char *)node->data;
 
-		if (!g_slist_find_custom(gc->account->permit,
+		if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 								 name, (GCompareFunc)purple_utf8_strcasecmp)) {
-			purple_privacy_permit_add(gc->account, name , TRUE);
+			purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE);
 		}
 	}
 
@@ -1437,15 +1434,15 @@
 		else
 			name =(char *)node->data;
 
-		if (!g_slist_find_custom(gc->account->deny,
+		if (!g_slist_find_custom(purple_connection_get_account(gc)->deny,
 								 name, (GCompareFunc)purple_utf8_strcasecmp)) {
-			purple_privacy_deny_add(gc->account, name, TRUE);
+			purple_privacy_deny_add(purple_connection_get_account(gc), name, TRUE);
 		}
 	}
 
 
 	/*  Remove stuff */
-	for (node = gc->account->permit; node; node = node->next) {
+	for (node = purple_connection_get_account(gc)->permit; node; node = node->next) {
 		dn = nm_lookup_dn(user, (char *)node->data);
 		if (dn != NULL &&
 			!g_slist_find_custom(user->allow_list,
@@ -1456,13 +1453,13 @@
 
 	if (rem_list) {
 		for (node = rem_list; node; node = node->next) {
-			purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
+			purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE);
 		}
 		g_slist_free(rem_list);
 		rem_list = NULL;
 	}
 
-	for (node = gc->account->deny; node; node = node->next) {
+	for (node = purple_connection_get_account(gc)->deny; node; node = node->next) {
 		dn = nm_lookup_dn(user, (char *)node->data);
 		if (dn != NULL &&
 			!g_slist_find_custom(user->deny_list,
@@ -1473,7 +1470,7 @@
 
 	if (rem_list) {
 		for (node = rem_list; node; node = node->next) {
-			purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE);
+			purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE);
 		}
 		g_slist_free(rem_list);
 	}
@@ -3091,7 +3088,7 @@
 	/* Remove first -- we will add it back in when we get
 	 * the okay from the server
 	 */
-	purple_privacy_permit_remove(gc->account, who, TRUE);
+	purple_privacy_permit_remove(purple_connection_get_account(gc), who, TRUE);
 
 	if (nm_user_is_privacy_locked(user)) {
 		_show_privacy_locked_error(gc, user);
@@ -3135,7 +3132,7 @@
 	/* Remove first -- we will add it back in when we get
 	 * the okay from the server
 	 */
-	purple_privacy_deny_remove(gc->account, who, TRUE);
+	purple_privacy_deny_remove(purple_connection_get_account(gc), who, TRUE);
 
 	if (nm_user_is_privacy_locked(user)) {
 		_show_privacy_locked_error(gc, user);
@@ -3253,7 +3250,7 @@
 		return;
 	}
 
-	switch (purple_account_get_privacy_type(gc->account)) {
+	switch (purple_account_get_privacy_type(purple_connection_get_account(gc))) {
 
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			rc = nm_send_set_privacy_default(user, FALSE,
@@ -3309,14 +3306,14 @@
 					if (user_record) {
 						name = nm_user_record_get_display_id(user_record);
 
-						if (!g_slist_find_custom(gc->account->permit,
+						if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 												 name, (GCompareFunc)purple_utf8_strcasecmp)) {
-							purple_privacy_permit_add(gc->account, name , TRUE);
+							purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE);
 						}
 					}
 				}
 
-				for (node = gc->account->permit; node; node = node->next) {
+				for (node = purple_connection_get_account(gc)->permit; node; node = node->next) {
 					name = NULL;
 					dn = nm_lookup_dn(user, (char *)node->data);
 					if (dn) {
@@ -3330,7 +3327,7 @@
 															 g_strdup(dn));
 						}
 					} else {
-						purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
+						purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE);
 					}
 				}
 			}
@@ -3351,14 +3348,14 @@
 					if (user_record) {
 						name = nm_user_record_get_display_id(user_record);
 
-						if (!g_slist_find_custom(gc->account->deny,
+						if (!g_slist_find_custom(purple_connection_get_account(gc)->deny,
 												 name, (GCompareFunc)purple_utf8_strcasecmp)) {
-							purple_privacy_deny_add(gc->account, name , TRUE);
+							purple_privacy_deny_add(purple_connection_get_account(gc), name , TRUE);
 						}
 					}
 				}
 
-				for (node = gc->account->deny; node; node = node->next) {
+				for (node = purple_connection_get_account(gc)->deny; node; node = node->next) {
 
 					name = NULL;
 					dn = nm_lookup_dn(user, (char *)node->data);
@@ -3373,7 +3370,7 @@
 															 g_strdup(name));
 						}
 					} else {
-						purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE);
+						purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE);
 					}
 				}
 
--- a/libpurple/protocols/null/nullprpl.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/null/nullprpl.c	Fri Dec 23 06:58:52 2011 +0000
@@ -113,7 +113,7 @@
   PurpleConnection *gc = (PurpleConnection *)(data);
   GcFuncData *gcfdata = (GcFuncData *)userdata;
 
-  if (!strcmp(purple_account_get_protocol_id(gc->account), NULLPRPL_ID))
+  if (!strcmp(purple_account_get_protocol_id(purple_connection_get_account(gc)), NULLPRPL_ID))
     gcfdata->fn(gcfdata->from, gc, gcfdata->userdata);
 }
 
@@ -160,11 +160,11 @@
 
 static void discover_status(PurpleConnection *from, PurpleConnection *to,
                             gpointer userdata) {
-  const char *from_username = purple_account_get_username(from->account);
-  const char *to_username = purple_account_get_username(to->account);
+  const char *from_username = purple_account_get_username(purple_connection_get_account(from));
+  const char *to_username = purple_account_get_username(purple_connection_get_account(to));
 
-  if (purple_find_buddy(from->account, to_username)) {
-    PurpleStatus *status = purple_account_get_active_status(to->account);
+  if (purple_find_buddy(purple_connection_get_account(from), to_username)) {
+    PurpleStatus *status = purple_account_get_active_status(purple_connection_get_account(to));
     const char *status_id = purple_status_get_id(status);
     const char *message = purple_status_get_attr_string(status, "message");
 
@@ -173,7 +173,7 @@
         !strcmp(status_id, NULL_STATUS_OFFLINE)) {
       purple_debug_info("nullprpl", "%s sees that %s is %s: %s\n",
                         from_username, to_username, status_id, message);
-      purple_prpl_got_user_status(from->account, to_username, status_id,
+      purple_prpl_got_user_status(purple_connection_get_account(from), to_username, status_id,
                                   (message) ? "message" : NULL, message, NULL);
     } else {
       purple_debug_error("nullprpl",
@@ -186,7 +186,7 @@
 static void report_status_change(PurpleConnection *from, PurpleConnection *to,
                                  gpointer userdata) {
   purple_debug_info("nullprpl", "notifying %s that %s changed status\n",
-                    purple_account_get_username(to->account), purple_account_get_username(from->account));
+                    purple_account_get_username(purple_connection_get_account(to)), purple_account_get_username(purple_connection_get_account(from)));
   discover_status(to, from, NULL);
 }
 
@@ -265,7 +265,7 @@
     g_free(msg);
 
     if (full) {
-      const char *user_info = purple_account_get_user_info(gc->account);
+      const char *user_info = purple_account_get_user_info(purple_connection_get_account(gc));
       if (user_info)
 		/* TODO: Check whether it's correct to call add_pair_html,
 		         or if we should be using add_pair_plaintext */
@@ -413,7 +413,7 @@
 static int nullprpl_send_im(PurpleConnection *gc, const char *who,
                             const char *message, PurpleMessageFlags flags)
 {
-  const char *from_username = purple_account_get_username(gc->account);
+  const char *from_username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleMessageFlags receive_flags = ((flags & ~PURPLE_MESSAGE_SEND)
                                       | PURPLE_MESSAGE_RECV);
   PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID);
@@ -423,13 +423,13 @@
                     from_username, who, message);
 
   /* is the sender blocked by the recipient's privacy settings? */
-  if (to_acct && !purple_privacy_check(to_acct, purple_account_get_username(gc->account))) {
+  if (to_acct && !purple_privacy_check(to_acct, purple_account_get_username(purple_connection_get_account(gc)))) {
     char *msg = g_strdup_printf(
       _("Your message was blocked by %s's privacy settings."), who);
     purple_debug_info("nullprpl",
                       "discarding; %s is blocked by %s's privacy settings\n",
                       from_username, who);
-    purple_conv_present_error(who, gc->account, msg);
+    purple_conv_present_error(who, purple_connection_get_account(gc), msg);
     g_free(msg);
     return 0;
   }
@@ -461,7 +461,7 @@
 
 static void nullprpl_set_info(PurpleConnection *gc, const char *info) {
   purple_debug_info("nullprpl", "setting %s's user info to %s\n",
-                    purple_account_get_username(gc->account), info);
+                    purple_account_get_username(purple_connection_get_account(gc)), info);
 }
 
 static const char *typing_state_to_string(PurpleTypingState typing) {
@@ -475,10 +475,10 @@
 
 static void notify_typing(PurpleConnection *from, PurpleConnection *to,
                           gpointer typing) {
-  const char *from_username = purple_account_get_username(from->account);
+  const char *from_username = purple_account_get_username(purple_connection_get_account(from));
   const char *action = typing_state_to_string((PurpleTypingState)typing);
   purple_debug_info("nullprpl", "notifying %s that %s %s\n",
-                    purple_account_get_username(to->account), from_username, action);
+                    purple_account_get_username(purple_connection_get_account(to)), from_username, action);
 
   serv_got_typing(to,
                   from_username,
@@ -489,7 +489,7 @@
 
 static unsigned int nullprpl_send_typing(PurpleConnection *gc, const char *name,
                                          PurpleTypingState typing) {
-  purple_debug_info("nullprpl", "%s %s\n", purple_account_get_username(gc->account),
+  purple_debug_info("nullprpl", "%s %s\n", purple_account_get_username(purple_connection_get_account(gc)),
                     typing_state_to_string(typing));
   foreach_nullprpl_gc(notify_typing, gc, (gpointer)typing);
   return 0;
@@ -501,7 +501,7 @@
   PurpleAccount *acct;
 
   purple_debug_info("nullprpl", "Fetching %s's user info for %s\n", username,
-                    purple_account_get_username(gc->account));
+                    purple_account_get_username(purple_connection_get_account(gc)));
 
   if (!get_nullprpl_gc(username)) {
     char *msg = g_strdup_printf(_("%s is not logged in."), username);
@@ -538,26 +538,26 @@
 static void nullprpl_set_idle(PurpleConnection *gc, int idletime) {
   purple_debug_info("nullprpl",
                     "purple reports that %s has been idle for %d seconds\n",
-                    purple_account_get_username(gc->account), idletime);
+                    purple_account_get_username(purple_connection_get_account(gc)), idletime);
 }
 
 static void nullprpl_change_passwd(PurpleConnection *gc, const char *old_pass,
                                    const char *new_pass) {
   purple_debug_info("nullprpl", "%s wants to change their password\n",
-                    purple_account_get_username(gc->account));
+                    purple_account_get_username(purple_connection_get_account(gc)));
 }
 
 static void nullprpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
                                PurpleGroup *group, const char *message)
 {
-  const char *username = purple_account_get_username(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConnection *buddy_gc = get_nullprpl_gc(buddy->name);
 
   purple_debug_info("nullprpl", "adding %s to %s's buddy list\n", buddy->name,
                     username);
 
   if (buddy_gc) {
-    PurpleAccount *buddy_acct = buddy_gc->account;
+    PurpleAccount *buddy_acct = purple_connection_get_account(buddy_gc);
 
     discover_status(gc, buddy_gc, NULL);
 
@@ -594,7 +594,7 @@
                                   PurpleGroup *group)
 {
   purple_debug_info("nullprpl", "removing %s from %s's buddy list\n",
-                    buddy->name, purple_account_get_username(gc->account));
+                    buddy->name, purple_account_get_username(purple_connection_get_account(gc)));
 }
 
 static void nullprpl_remove_buddies(PurpleConnection *gc, GList *buddies,
@@ -620,22 +620,22 @@
  */
 static void nullprpl_add_permit(PurpleConnection *gc, const char *name) {
   purple_debug_info("nullprpl", "%s adds %s to their allowed list\n",
-                    purple_account_get_username(gc->account), name);
+                    purple_account_get_username(purple_connection_get_account(gc)), name);
 }
 
 static void nullprpl_add_deny(PurpleConnection *gc, const char *name) {
   purple_debug_info("nullprpl", "%s adds %s to their blocked list\n",
-                    purple_account_get_username(gc->account), name);
+                    purple_account_get_username(purple_connection_get_account(gc)), name);
 }
 
 static void nullprpl_rem_permit(PurpleConnection *gc, const char *name) {
   purple_debug_info("nullprpl", "%s removes %s from their allowed list\n",
-                    purple_account_get_username(gc->account), name);
+                    purple_account_get_username(purple_connection_get_account(gc)), name);
 }
 
 static void nullprpl_rem_deny(PurpleConnection *gc, const char *name) {
   purple_debug_info("nullprpl", "%s removes %s from their blocked list\n",
-                    purple_account_get_username(gc->account), name);
+                    purple_account_get_username(purple_connection_get_account(gc)), name);
 }
 
 static void nullprpl_set_permit_deny(PurpleConnection *gc) {
@@ -668,7 +668,7 @@
 }
 
 static void nullprpl_join_chat(PurpleConnection *gc, GHashTable *components) {
-  const char *username = purple_account_get_username(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   const char *room = g_hash_table_lookup(components, "room");
   int chat_id = g_str_hash(room);
   purple_debug_info("nullprpl", "%s is joining chat room %s\n", username, room);
@@ -692,7 +692,7 @@
 static void nullprpl_reject_chat(PurpleConnection *gc, GHashTable *components) {
   const char *invited_by = g_hash_table_lookup(components, "invited_by");
   const char *room = g_hash_table_lookup(components, "room");
-  const char *username = purple_account_get_username(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConnection *invited_by_gc = get_nullprpl_gc(invited_by);
   char *message = g_strdup_printf(
     "%s %s %s.",
@@ -719,7 +719,7 @@
 
 static void nullprpl_chat_invite(PurpleConnection *gc, int id,
                                  const char *message, const char *who) {
-  const char *username = purple_account_get_username(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConversation *conv = purple_find_chat(gc, id);
   const char *room = purple_conversation_get_name(conv);
   PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID);
@@ -762,7 +762,7 @@
 static void nullprpl_chat_leave(PurpleConnection *gc, int id) {
   PurpleConversation *conv = purple_find_chat(gc, id);
   purple_debug_info("nullprpl", "%s is leaving chat room %s\n",
-                    purple_account_get_username(gc->account), purple_conversation_get_name(conv));
+                    purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv));
 
   /* tell everyone that we left */
   foreach_gc_in_chat(left_chat_room, gc, id, NULL);
@@ -821,7 +821,7 @@
 
 static void nullprpl_chat_whisper(PurpleConnection *gc, int id, const char *who,
                                   const char *message) {
-  const char *username = purple_account_get_username(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConversation *conv = purple_find_chat(gc, id);
   purple_debug_info("nullprpl",
                     "%s receives whisper from %s in chat room %s: %s\n",
@@ -846,7 +846,7 @@
 
 static int nullprpl_chat_send(PurpleConnection *gc, int id, const char *message,
                               PurpleMessageFlags flags) {
-  const char *username = purple_account_get_username(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConversation *conv = purple_find_chat(gc, id);
 
   if (conv) {
@@ -875,7 +875,7 @@
   PurpleConversation *conv = purple_find_chat(gc, id);
   purple_debug_info("nullprpl",
                     "retrieving %s's info for %s in chat room %s\n", who,
-                    purple_account_get_username(gc->account), purple_conversation_get_name(conv));
+                    purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv));
 
   nullprpl_get_info(gc, who);
 }
@@ -883,25 +883,25 @@
 static void nullprpl_alias_buddy(PurpleConnection *gc, const char *who,
                                  const char *alias) {
  purple_debug_info("nullprpl", "%s sets %s's alias to %s\n",
-                   purple_account_get_username(gc->account), who, alias);
+                   purple_account_get_username(purple_connection_get_account(gc)), who, alias);
 }
 
 static void nullprpl_group_buddy(PurpleConnection *gc, const char *who,
                                  const char *old_group,
                                  const char *new_group) {
   purple_debug_info("nullprpl", "%s has moved %s from group %s to group %s\n",
-                    purple_account_get_username(gc->account), who, old_group, new_group);
+                    purple_account_get_username(purple_connection_get_account(gc)), who, old_group, new_group);
 }
 
 static void nullprpl_rename_group(PurpleConnection *gc, const char *old_name,
                                   PurpleGroup *group, GList *moved_buddies) {
   purple_debug_info("nullprpl", "%s has renamed group %s to %s\n",
-                    purple_account_get_username(gc->account), old_name, group->name);
+                    purple_account_get_username(purple_connection_get_account(gc)), old_name, group->name);
 }
 
 static void nullprpl_convo_closed(PurpleConnection *gc, const char *who) {
   purple_debug_info("nullprpl", "%s's conversation with %s was closed\n",
-                    purple_account_get_username(gc->account), who);
+                    purple_account_get_username(purple_connection_get_account(gc)), who);
 }
 
 /* normalize a username (e.g. remove whitespace, add default domain, etc.)
@@ -915,13 +915,13 @@
 static void nullprpl_set_buddy_icon(PurpleConnection *gc,
                                     PurpleStoredImage *img) {
  purple_debug_info("nullprpl", "setting %s's buddy icon to %s\n",
-                   purple_account_get_username(gc->account),
+                   purple_account_get_username(purple_connection_get_account(gc)),
                    img ? purple_imgstore_get_filename(img) : "(null)");
 }
 
 static void nullprpl_remove_group(PurpleConnection *gc, PurpleGroup *group) {
   purple_debug_info("nullprpl", "%s has removed group %s\n",
-                    purple_account_get_username(gc->account), group->name);
+                    purple_account_get_username(purple_connection_get_account(gc)), group->name);
 }
 
 
@@ -954,7 +954,7 @@
     return;
 
   purple_debug_info("nullprpl", "%s sets topic of chat room '%s' to '%s'\n",
-                    purple_account_get_username(gc->account), purple_conversation_get_name(conv), topic);
+                    purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv), topic);
 
   last_topic = purple_conv_chat_get_topic(chat);
   if ((!topic && !last_topic) ||
@@ -970,8 +970,8 @@
 }
 
 static PurpleRoomlist *nullprpl_roomlist_get_list(PurpleConnection *gc) {
-  const char *username = purple_account_get_username(gc->account);
-  PurpleRoomlist *roomlist = purple_roomlist_new(gc->account);
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
+  PurpleRoomlist *roomlist = purple_roomlist_new(purple_connection_get_account(gc));
   GList *fields = NULL;
   PurpleRoomlistField *field;
   GList *chats;
--- a/libpurple/protocols/oscar/family_feedbag.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Fri Dec 23 06:58:52 2011 +0000
@@ -734,10 +734,37 @@
 }
 
 /**
- * This "cleans" the ssi list.  It does the following:
- * 1) Makes sure all buddies, permits, and denies have names.
- * 2) Makes sure that all buddies are in a group that exist.
- * 3) Deletes any empty groups
+ * Look up the given TLV type in the item's data.  If the value of
+ * the TLV is not a valid UTF-8 string then use purple_utf8_salvage()
+ * to replace invalid bytes with question marks.
+ */
+static void cleanlist_ensure_utf8_data(struct aim_ssi_item *item, guint16 tlvtype)
+{
+	aim_tlv_t *tlv;
+	gchar *value, *salvaged;
+
+	tlv = aim_tlv_gettlv(item->data, tlvtype, 1);
+	if (tlv && tlv->length && !g_utf8_validate((const gchar *)tlv->value, tlv->length, NULL)) {
+		purple_debug_warning("oscar", "cleanlist found invalid UTF-8 "
+				"for 0x%04hx field of 0x%04hx item with name %s.  "
+				"Attempting to repair.\n",
+				tlvtype, item->type, item->name ? item->name : "(null)");
+		value = g_strndup((const gchar *)tlv->value, tlv->length);
+		salvaged = purple_utf8_salvage(value);
+		g_free(value);
+		if (*salvaged)
+			aim_tlvlist_replace_str(&item->data, tlvtype, salvaged);
+		else
+			aim_tlvlist_remove(&item->data, tlvtype);
+		g_free(salvaged);
+	}
+}
+
+/**
+ * This "cleans" the ssi list.  It does things like:
+ * - Makes sure all buddies, permits, and denies have names
+ * - Makes sure all buddies are in a group that exist
+ * - Makes sure strings are valid UTF-8
  *
  * @param od The oscar odion.
  * @return Return 0 if no errors, otherwise return the error number.
@@ -764,27 +791,40 @@
 				aim_ssi_del_from_private_list(od, NULL, cur->type);
 		} else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(&od->ssi.local, cur->gid, 0x0000)))) {
 			char *alias = aim_ssi_getalias(&od->ssi.local, NULL, cur->name);
-			aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE);
+			aim_ssi_addbuddy(od, cur->name, _("Buddies"), NULL, alias, NULL, NULL, FALSE);
 			aim_ssi_delbuddy(od, cur->name, NULL);
 			g_free(alias);
 		}
 		cur = next;
 	}
 
-	/* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */
 	cur = od->ssi.local.data;
 	while (cur) {
 		if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY))
 		{
 			struct aim_ssi_item *cur2, *next2;
+
+			/* Make sure there aren't any duplicate permits or denies, or
+			   duplicate buddies within a group */
 			cur2 = cur->next;
 			while (cur2) {
 				next2 = cur2->next;
-				if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!oscar_util_name_compare(cur->name, cur2->name))) {
+				if (cur->type == cur2->type
+						&& cur->gid == cur2->gid
+						&& cur->name
+						&& cur2->name
+						&& !oscar_util_name_compare(cur->name, cur2->name))
+				{
 					aim_ssi_itemlist_del(&od->ssi.local, cur2);
 				}
 				cur2 = next2;
 			}
+
+			/* Make sure alias is valid UTF-8 */
+			cleanlist_ensure_utf8_data(cur, 0x0131);
+
+			/* Make sure comment is valid UTF-8 */
+			cleanlist_ensure_utf8_data(cur, 0x013c);
 		}
 		cur = cur->next;
 	}
@@ -1674,18 +1714,35 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint16 tmp;
-	char *bn, *msg;
+	char *bn, *msg, *tmpstr;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping auth grant SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping auth grant SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
-	/* Read message (null terminated) */
-	if ((tmp = byte_stream_get16(bs)))
+	/* Read message */
+	tmp = byte_stream_get16(bs);
+	if (tmp) {
 		msg = byte_stream_getstr(bs, tmp);
-	else
+		if (!g_utf8_validate(msg, -1, NULL)) {
+			/* Ugh, msg isn't UTF8.  Let's salvage. */
+			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+					"grant from %s\n", bn);
+			tmpstr = purple_utf8_salvage(msg);
+			g_free(msg);
+			msg = tmpstr;
+		}
+	} else
 		msg = NULL;
 
 	/* Unknown */
@@ -1748,18 +1805,35 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint16 tmp;
-	char *bn, *msg;
+	char *bn, *msg, *tmpstr;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping auth request SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping auth request SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
-	/* Read message (null terminated) */
-	if ((tmp = byte_stream_get16(bs)))
+	/* Read message */
+	tmp = byte_stream_get16(bs);
+	if (tmp) {
 		msg = byte_stream_getstr(bs, tmp);
-	else
+		if (!g_utf8_validate(msg, -1, NULL)) {
+			/* Ugh, msg isn't UTF8.  Let's salvage. */
+			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+					"request from %s\n", bn);
+			tmpstr = purple_utf8_salvage(msg);
+			g_free(msg);
+			msg = tmpstr;
+		}
+	} else
 		msg = NULL;
 
 	/* Unknown */
@@ -1832,21 +1906,38 @@
 	aim_rxcallback_t userfunc;
 	guint16 tmp;
 	guint8 reply;
-	char *bn, *msg;
+	char *bn, *msg, *tmpstr;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping auth reply SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping auth reply SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
 	/* Read reply */
 	reply = byte_stream_get8(bs);
 
-	/* Read message (null terminated) */
-	if ((tmp = byte_stream_get16(bs)))
+	/* Read message */
+	tmp = byte_stream_get16(bs);
+	if (tmp) {
 		msg = byte_stream_getstr(bs, tmp);
-	else
+		if (!g_utf8_validate(msg, -1, NULL)) {
+			/* Ugh, msg isn't UTF8.  Let's salvage. */
+			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+					"reply from %s\n", bn);
+			tmpstr = purple_utf8_salvage(msg);
+			g_free(msg);
+			msg = tmpstr;
+		}
+	} else
 		msg = NULL;
 
 	/* Unknown */
@@ -1872,10 +1963,18 @@
 	char *bn;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, bn);
--- a/libpurple/protocols/oscar/flap_connection.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Fri Dec 23 06:58:52 2011 +0000
@@ -456,7 +456,7 @@
 	 * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then
 	 * we should try to request one instead of disconnecting.
 	 */
-	if (!account->disconnecting && ((od->oscar_connections == NULL)
+	if (!purple_account_is_disconnecting(account) && ((od->oscar_connections == NULL)
 			|| (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE))))
 	{
 		/* No more FLAP connections!  Sign off this PurpleConnection! */
@@ -921,7 +921,7 @@
 						OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
 				break;
 			}
-			conn->od->gc->last_received = time(NULL);
+			purple_connection_update_last_received(conn->od->gc);
 
 			/* If we don't even have a complete FLAP header then do nothing */
 			conn->header_received += read;
--- a/libpurple/protocols/oscar/oft.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/oscar/oft.c	Fri Dec 23 06:58:52 2011 +0000
@@ -508,7 +508,7 @@
 
 	purple_input_remove(conn->watcher_incoming);
 	conn->watcher_incoming = 0;
-	conn->xfer->fd = conn->fd;
+	purple_xfer_set_fd(conn->xfer, conn->fd);
 	conn->fd = -1;
 	conn->disconnect_reason = OSCAR_DISCONNECT_DONE;
 	peer_connection_schedule_destroy(conn, conn->disconnect_reason, NULL);
@@ -602,8 +602,8 @@
 	conn = purple_xfer_get_protocol_data(xfer);
 
 	/* Tell the other person that we've received everything */
-	conn->fd = conn->xfer->fd;
-	conn->xfer->fd = -1;
+	conn->fd = purple_xfer_get_fd(conn->xfer);
+	purple_xfer_set_fd(conn->xfer, -1);
 	peer_oft_send_done(conn);
 
 	conn->disconnect_reason = OSCAR_DISCONNECT_DONE;
@@ -651,7 +651,7 @@
 peer_oft_sendcb_init(PurpleXfer *xfer)
 {
 	PeerConnection *conn;
-	size_t size;
+	goffset size;
 
 	conn = purple_xfer_get_protocol_data(xfer);
 	conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
@@ -721,9 +721,9 @@
 	 */
 	if (purple_xfer_get_bytes_remaining(xfer) <= 0)
 	{
-		purple_input_remove(xfer->watcher);
-		conn->fd = xfer->fd;
-		xfer->fd = -1;
+		purple_input_remove(purple_xfer_get_watcher(xfer));
+		conn->fd = purple_xfer_get_fd(xfer);
+		purple_xfer_set_fd(xfer, -1);
 		conn->watcher_incoming = purple_input_add(conn->fd,
 				PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
 	}
--- a/libpurple/protocols/oscar/oscar.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Dec 23 06:58:52 2011 +0000
@@ -655,6 +655,7 @@
 	GList *sorted_handlers;
 	GList *cur;
 	GString *msg = g_string_new("");
+	PurpleConnectionFlags flags;
 
 	gc = purple_account_get_connection(account);
 	od = oscar_data_new();
@@ -740,17 +741,19 @@
 		return;
 	}
 
-	gc->flags |= PURPLE_CONNECTION_HTML;
+	flags = PURPLE_CONNECTION_HTML;
 	if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) {
 		od->icq = TRUE;
 	} else {
-		gc->flags |= PURPLE_CONNECTION_AUTO_RESP;
+		flags |= PURPLE_CONNECTION_AUTO_RESP;
 	}
 
 	/* Set this flag based on the protocol_id rather than the username,
 	   because that is what's tied to the get_moods prpl callback. */
 	if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq"))
-		gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS;
+		flags |= PURPLE_CONNECTION_SUPPORT_MOODS;
+
+	purple_connection_set_flags(gc, flags);
 
 	od->default_port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT);
 
@@ -1000,7 +1003,7 @@
 	pos->len = len;
 	pos->modname = g_strdup(modname);
 
-	if (purple_proxy_connect(pos->gc, pos->gc->account, "pidgin.im", 80,
+	if (purple_proxy_connect(pos->gc, purple_connection_get_account(pos->gc), "pidgin.im", 80,
 			straight_to_hell, pos) == NULL)
 	{
 		char buf[256];
@@ -1547,7 +1550,7 @@
 
 	purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_OFFLINE, NULL);
 	purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
-	g_hash_table_remove(od->buddyinfo, purple_normalize(gc->account, info->bn));
+	g_hash_table_remove(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), info->bn));
 
 	return 1;
 }
@@ -3176,9 +3179,9 @@
 	else {
 		/* Don't send if this turkey is in our deny list */
 		GSList *list;
-		for (list=gc->account->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next);
+		for (list=purple_connection_get_account(gc)->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next);
 		if (!list) {
-			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(gc->account, name));
+			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), name));
 			if (bi && bi->typingnot) {
 				if (state == PURPLE_TYPING)
 					aim_im_sendmtn(od, 0x0001, name, 0x0002);
@@ -3478,13 +3481,11 @@
 static guint32
 oscar_get_extended_status(PurpleConnection *gc)
 {
-	OscarData *od;
 	PurpleAccount *account;
 	PurpleStatus *status;
 	const gchar *status_id;
 	guint32 data = 0x00000000;
 
-	od = purple_connection_get_protocol_data(gc);
 	account = purple_connection_get_account(gc);
 	status = purple_account_get_active_status(account);
 	status_id = purple_status_get_id(status);
@@ -4032,9 +4033,9 @@
 					gname = groupitem ? groupitem->name : NULL;
 					gname_utf8 = oscar_utf8_try_convert(account, od, gname);
 
-					g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans"));
+					g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies"));
 					if (g == NULL) {
-						g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+						g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies"));
 						purple_blist_add_group(g, NULL);
 					}
 
@@ -4258,13 +4259,13 @@
 		 */
 		b = purple_buddy_new(account, name, alias_utf8);
 
-		if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
-			g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+		if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies")))) {
+			g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies"));
 			purple_blist_add_group(g, NULL);
 		}
 
 		purple_debug_info("oscar",
-				   "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans"));
+				   "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Buddies"));
 		purple_blist_add_buddy(b, NULL, g, NULL);
 
 		/* Mobile users should always be online */
@@ -4616,7 +4617,6 @@
 	PurpleAccount *account = NULL;
 	PurplePresence *presence;
 	PurpleStatus *status;
-	const char *status_id;
 	aim_userinfo_t *userinfo = NULL;
 	const char *name;
 
@@ -4631,7 +4631,6 @@
 
 	presence = purple_buddy_get_presence(b);
 	status = purple_presence_get_active_status(presence);
-	status_id = purple_status_get_id(status);
 
 	if (purple_presence_is_online(presence) == FALSE) {
 		char *gname;
@@ -4690,7 +4689,6 @@
 	OscarData *od;
 	const PurplePresence *presence;
 	const PurpleStatus *status;
-	const char *id;
 	const char *message;
 	gchar *ret = NULL;
 
@@ -4699,7 +4697,6 @@
 	od = purple_connection_get_protocol_data(gc);
 	presence = purple_buddy_get_presence(b);
 	status = purple_presence_get_active_status(presence);
-	id = purple_status_get_id(status);
 
 	if ((od != NULL) && !purple_presence_is_online(presence))
 	{
--- a/libpurple/protocols/oscar/peer.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/oscar/peer.c	Fri Dec 23 06:58:52 2011 +0000
@@ -603,15 +603,11 @@
 peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PeerConnection *conn;
-	OscarData *od;
-	PurpleConnection *gc;
 	struct sockaddr addr;
 	socklen_t addrlen = sizeof(addr);
 	int flags;
 
 	conn = data;
-	od = conn->od;
-	gc = od->gc;
 
 	purple_debug_info("oscar", "Accepting connection on listener socket.\n");
 
--- a/libpurple/protocols/oscar/userinfo.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/oscar/userinfo.c	Fri Dec 23 06:58:52 2011 +0000
@@ -307,8 +307,6 @@
 {
 	OscarData *od;
 	PurpleAccount *account;
-	PurplePresence *presence = NULL;
-	PurpleStatus *status = NULL;
 	PurpleGroup *g = NULL;
 	struct buddyinfo *bi = NULL;
 	char *tmp;
@@ -330,8 +328,6 @@
 		bname = purple_buddy_get_name(b);
 		g = purple_buddy_get_group(b);
 		gname = purple_group_get_name(g);
-		presence = purple_buddy_get_presence(b);
-		status = purple_presence_get_active_status(presence);
 	}
 
 	if (userinfo != NULL)
--- a/libpurple/protocols/sametime/sametime.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Fri Dec 23 06:58:52 2011 +0000
@@ -217,6 +217,7 @@
 
   /** socket fd */
   int socket;
+  guint inpa;  /* input watcher */
   gint outpa;  /* like inpa, but the other way */
 
   /** circular buffer for outgoing data */
@@ -449,9 +450,9 @@
     pd->socket = 0;
   }
 
-  if(gc->inpa) {
-    purple_input_remove(gc->inpa);
-    gc->inpa = 0;
+  if(pd->inpa) {
+    purple_input_remove(pd->inpa);
+    pd->inpa = 0;
   }
 }
 
@@ -1279,7 +1280,7 @@
   struct mwIdBlock who = { 0, 0 };
   struct mwConversation *conv;
 
-  gc = purple_conversation_get_gc(g_conv);
+  gc = purple_conversation_get_connection(g_conv);
   if(pd->gc != gc)
     return; /* not ours */
 
@@ -1760,9 +1761,9 @@
     pd->socket = 0;
   }
 
-  if(pd->gc->inpa) {
-    purple_input_remove(pd->gc->inpa);
-    pd->gc->inpa = 0;
+  if(pd->inpa) {
+    purple_input_remove(pd->inpa);
+    pd->inpa = 0;
   }
 
   if(! ret) {
@@ -1791,7 +1792,6 @@
 static void connect_cb(gpointer data, gint source, const gchar *error_message) {
 
   struct mwPurplePluginData *pd = data;
-  PurpleConnection *gc = pd->gc;
 
   if(source < 0) {
     /* connection failed */
@@ -1819,7 +1819,7 @@
   }
 
   pd->socket = source;
-  gc->inpa = purple_input_add(source, PURPLE_INPUT_READ,
+  pd->inpa = purple_input_add(source, PURPLE_INPUT_READ,
 			    read_cb, pd);
 
   mwSession_start(pd->session);
@@ -2351,7 +2351,7 @@
 
   xfer = mwFileTransfer_getClientData(ft);
   g_return_if_fail(xfer != NULL);
-  g_return_if_fail(xfer->watcher == 0);
+  g_return_if_fail(purple_xfer_get_watcher(xfer) == 0);
 
   if(! mwFileTransfer_getRemaining(ft)) {
     purple_xfer_set_completed(xfer, TRUE);
@@ -2528,10 +2528,10 @@
   gconv = convo_get_gconv(conv);
   if(! gconv) return;
 
-  gc = purple_conversation_get_gc(gconv);
+  gc = purple_conversation_get_connection(gconv);
   if(! gc) return;
 
-  purple_conversation_set_features(gconv, gc->flags);
+  purple_conversation_set_features(gconv, purple_connection_get_flags(gc));
 }
 
 
@@ -3701,7 +3701,7 @@
   pd = mwPurplePluginData_new(gc);
 
   /* while we do support images, the default is to not offer it */
-  gc->flags |= PURPLE_CONNECTION_NO_IMAGES;
+  purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_IMAGES);
 
   user = g_strdup(purple_account_get_username(account));
 
@@ -3794,9 +3794,9 @@
   purple_connection_set_protocol_data(gc, NULL);
 
   /* stop watching the socket */
-  if(gc->inpa) {
-    purple_input_remove(gc->inpa);
-    gc->inpa = 0;
+  if(pd->inpa) {
+    purple_input_remove(pd->inpa);
+    pd->inpa = 0;
   }
 
   /* clean up the rest */
--- a/libpurple/protocols/silc/buddy.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/silc/buddy.c	Fri Dec 23 06:58:52 2011 +0000
@@ -314,7 +314,7 @@
 	a->port = port;
 
 	purple_request_action(client->application, _("Key Agreement Request"), tmp,
-			      hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname,
+			      hostname ? tmp2 : NULL, 1, purple_connection_get_account(gc), client_entry->nickname,
 			      NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),
 			      _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));
 }
@@ -457,7 +457,7 @@
 	                     _("Set IM Password"), NULL, FALSE, TRUE, NULL,
 	                     _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb),
 	                     _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb),
-	                     gc->account, NULL, NULL, p);
+	                     purple_connection_get_account(gc), NULL, NULL, p);
 
 	silc_client_list_free(sg->client, sg->conn, clients);
 }
@@ -686,7 +686,7 @@
 	if (strlen(who) > 2 && who[0] == '*' && who[1] == '@')
 		nick = who + 2;
 
-	b = purple_find_buddy(gc->account, nick);
+	b = purple_find_buddy(purple_connection_get_account(gc), nick);
 	if (b) {
 		/* See if we have this buddy's public key.  If we do use that
 		   to search the details. */
--- a/libpurple/protocols/silc/ft.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/silc/ft.c	Fri Dec 23 06:58:52 2011 +0000
@@ -86,7 +86,7 @@
 		purple_notify_error(gc, _("Secure File Transfer"),
 				    _("Error during file transfer"),
 				    _("Remote disconnected"));
-		xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
+		purple_xfer_set_status(xfer->xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
 		purple_xfer_update_progress(xfer->xfer);
 		silc_client_file_close(client, conn, session_id);
 		return;
@@ -122,7 +122,7 @@
 					  _("Error during file transfer"),
 					  _("File transfer session does not exist"));
 		}
-		xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
+		purple_xfer_set_status(xfer->xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
 		purple_xfer_update_progress(xfer->xfer);
 		silc_client_file_close(client, conn, session_id);
 		return;
@@ -154,7 +154,7 @@
 	if (!xfer)
 		return;
 
-	xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL;
+	purple_xfer_set_status(xfer->xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
 	purple_xfer_update_progress(xfer->xfer);
 	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
 }
--- a/libpurple/protocols/silc/ops.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/silc/ops.c	Fri Dec 23 06:58:52 2011 +0000
@@ -224,7 +224,6 @@
 					    tmp, cflags, time(NULL));
 
 			purple_imgstore_unref_by_id(imgid);
-			cflags = 0;
 			ret = TRUE;
 		}
 		goto out;
@@ -332,10 +331,17 @@
 	}
 
 	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		tmp = g_markup_escape_text((const char *)message, -1);
+		const char *msg = (const char *)message;
+		char *salvaged = NULL;
+		if (!g_utf8_validate((const char *)message, -1, NULL)) {
+			salvaged = purple_utf8_salvage((const char *)message);
+			msg = salvaged;
+		}
+		tmp = g_markup_escape_text(msg, -1);
 		/* Send to Purple */
 		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
 				 sender->nickname, 0, tmp, time(NULL));
+		g_free(salvaged);
 		g_free(tmp);
 	}
 }
--- a/libpurple/protocols/silc/silc.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/silc/silc.c	Fri Dec 23 06:58:52 2011 +0000
@@ -400,7 +400,7 @@
 	}
 
 	/* Perform SILC Key Exchange. */
-	silc_client_key_exchange(sg->client, &params, sg->public_key,
+	silc_client_key_exchange(client, &params, sg->public_key,
 				 sg->private_key, stream, SILC_CONN_SERVER,
 				 silcpurple_connect_cb, gc);
 
@@ -528,7 +528,7 @@
 	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
 	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),
 				(char *)purple_account_get_string(account, "private-key", prd),
-				(gc->password == NULL) ? "" : gc->password,
+				(purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
 				&sg->public_key, &sg->private_key)) {
 		if (!purple_account_get_password(account)) {
 			purple_account_request_password(account, G_CALLBACK(silcpurple_got_password_cb),
@@ -1061,7 +1061,7 @@
 			    fields,
 			    _("OK"), G_CALLBACK(silcpurple_attrs_cb),
 			    _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel),
-				gc->account, NULL, NULL, gc);
+				purple_connection_get_account(gc), NULL, NULL, gc);
 }
 
 static void
@@ -1226,9 +1226,9 @@
 	g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir());
 	g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir());
 	g_snprintf(pkd, sizeof(pkd) - 1, "%s",
-		   purple_account_get_string(gc->account, "public-key", pkd2));
+		   purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd2));
 	g_snprintf(prd, sizeof(prd) - 1, "%s",
-		   purple_account_get_string(gc->account, "private-key", prd2));
+		   purple_account_get_string(purple_connection_get_account(gc), "private-key", prd2));
 
 	fields = purple_request_fields_new();
 
@@ -1269,7 +1269,7 @@
 			      _("Create New SILC Key Pair"), NULL, fields,
 			      _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb),
 			      _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel),
-			      gc->account, NULL, NULL, gc);
+			      purple_connection_get_account(gc), NULL, NULL, gc);
 
 	g_strfreev(u);
 	silc_free(hostname);
@@ -1287,7 +1287,7 @@
 {
 	char prd[256];
 	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir());
-	silc_change_private_key_passphrase(purple_account_get_string(gc->account,
+	silc_change_private_key_passphrase(purple_account_get_string(purple_connection_get_account(gc),
 								     "private-key",
 								     prd), old ? old : "", new ? new : "");
 }
@@ -1548,14 +1548,14 @@
 	PurpleConversation *convo = conv;
 	int id = 0;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
 	if(args && args[0])
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0],
-									gc->account);
+									purple_connection_get_account(gc));
 
 	if (convo != NULL)
 		id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo));
@@ -1577,7 +1577,7 @@
 	char *buf, *tmp, *tmp2;
 	const char *topic;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv));
 
 	if (gc == NULL || id == 0)
@@ -1593,7 +1593,7 @@
 			g_free(tmp2);
 		} else
 			buf = g_strdup(_("No topic is set"));
-		purple_conv_chat_write(PURPLE_CONV_CHAT(conv), purple_account_get_username(gc->account), buf,
+		purple_conv_chat_write(PURPLE_CONV_CHAT(conv), purple_account_get_username(purple_connection_get_account(gc)), buf,
 							 PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
 		g_free(buf);
 
@@ -1623,7 +1623,7 @@
 	if(args[1])
 		g_hash_table_replace(comp, "passphrase", args[1]);
 
-	silcpurple_chat_join(purple_conversation_get_gc(conv), comp);
+	silcpurple_chat_join(purple_conversation_get_connection(conv), comp);
 
 	g_hash_table_destroy(comp);
 	return PURPLE_CMD_RET_OK;
@@ -1633,7 +1633,7 @@
         const char *cmd, char **args, char **error, void *data)
 {
 	PurpleConnection *gc;
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	purple_roomlist_show_with_account(purple_connection_get_account(gc));
 	return PURPLE_CMD_RET_OK;
 }
@@ -1643,7 +1643,7 @@
 {
 	PurpleConnection *gc;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1659,7 +1659,7 @@
 	int ret;
 	PurpleConnection *gc;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1685,7 +1685,7 @@
 		return PURPLE_CMD_RET_FAILED;
 	}
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1713,7 +1713,7 @@
 	SilcPurple sg;
 	char *tmp;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1742,7 +1742,7 @@
 	PurpleConnection *gc;
 	SilcPurple sg;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1767,7 +1767,7 @@
 	char *silccmd, *silcargs, *msg, tmp[256];
 	const char *chname;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL || !args || purple_connection_get_protocol_data(gc) == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1818,7 +1818,7 @@
 	SilcPurple sg;
 	char *silccmd, *silcargs;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1850,7 +1850,7 @@
 	const char *ui_name = NULL, *ui_website = NULL;
 	char *quit_msg;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1887,7 +1887,7 @@
 	PurpleConnection *gc;
 	SilcPurple sg;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
--- a/libpurple/protocols/silc/util.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/silc/util.c	Fri Dec 23 06:58:52 2011 +0000
@@ -198,9 +198,9 @@
 	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
 	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
 	g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(gc->account, "public-key", pkd));
+		   purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd));
 	g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(gc->account, "private-key", prd));
+		   purple_account_get_string(purple_connection_get_account(gc), "private-key", prd));
 
 	if ((g_stat(file_public_key, &st)) == -1) {
 		/* If file doesn't exist */
@@ -210,8 +210,7 @@
 						  SILCPURPLE_DEF_PKCS_LEN,
 						  file_public_key,
 						  file_private_key, NULL,
-						  (gc->password == NULL)
-						  ? "" : gc->password,
+						  (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
 						  NULL, NULL, FALSE)) {
 				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				                             _("Unable to create SILC key pair"));
@@ -253,8 +252,7 @@
 						  SILCPURPLE_DEF_PKCS_LEN,
 						  file_public_key,
 						  file_private_key, NULL,
-						  (gc->password == NULL)
-						  ? "" : gc->password,
+						  (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
 						  NULL, NULL, FALSE)) {
 				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				                             _("Unable to create SILC key pair"));
--- a/libpurple/protocols/silc/wb.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/silc/wb.c	Fri Dec 23 06:58:52 2011 +0000
@@ -105,11 +105,9 @@
 
 PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry)
 {
-	SilcClientConnection conn;
 	PurpleWhiteboard *wb;
 	SilcPurpleWb wbs;
 
-	conn = sg->conn;
 	wb = purple_whiteboard_get_session(sg->account, client_entry->nickname);
 	if (!wb)
 		wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0);
--- a/libpurple/protocols/simple/simple.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/simple/simple.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1121,8 +1121,8 @@
 			if(sip->registerstatus != SIMPLE_REGISTER_RETRY) {
 				purple_debug_info("simple", "REGISTER retries %d\n", sip->registrar.retries);
 				if(sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) {
-					if (!purple_account_get_remember_password(sip->gc->account))
-						purple_account_set_password(sip->gc->account, NULL);
+					if (!purple_account_get_remember_password(purple_connection_get_account(sip->gc)))
+						purple_account_set_password(purple_connection_get_account(sip->gc), NULL);
 					purple_connection_error(sip->gc,
 						PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 						_("Incorrect password"));
@@ -1705,7 +1705,7 @@
 		if(sip->fd == source) sip->fd = -1;
 		return;
 	}
-	gc->last_received = time(NULL);
+	purple_connection_update_last_received(gc);
 	conn->inbufused += len;
 	conn->inbuf[conn->inbufused] = '\0';
 
--- a/libpurple/protocols/yahoo/libymsg.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/yahoo/libymsg.c	Fri Dec 23 06:58:52 2011 +0000
@@ -337,12 +337,12 @@
 			if (!name)
 				break;
 
-			b = purple_find_buddy(gc->account, name);
+			b = purple_find_buddy(purple_connection_get_account(gc), name);
 
 			if (!cksum || (cksum == -1)) {
 				if (f)
 					yahoo_friend_set_buddy_icon_need_request(f, TRUE);
-				purple_buddy_icons_set_for_user(gc->account, name, NULL, 0, NULL);
+				purple_buddy_icons_set_for_user(purple_connection_get_account(gc), name, NULL, 0, NULL);
 				break;
 			}
 
@@ -634,7 +634,6 @@
 static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	GSList *l = pkt->hash;
-	gboolean export = FALSE;
 	gboolean got_serv_list = FALSE;
 	YahooFriend *f = NULL;
 	PurpleAccount *account = purple_connection_get_account(gc);
@@ -712,7 +711,6 @@
 					}
 					b = purple_buddy_new(account, norm_bud, NULL);
 					purple_blist_add_buddy(b, NULL, g, NULL);
-					export = TRUE;
 				}
 
 				yahoo_do_group_check(account, ht, norm_bud, grp);
@@ -2180,12 +2178,12 @@
 							  who, (ignore ? "ignoring" : "unignoring"));
 
 			if (ignore) {
-				b = purple_find_buddy(gc->account, who);
+				b = purple_find_buddy(purple_connection_get_account(gc), who);
 				g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the "
 											   "user is on your buddy list.  Clicking \"Yes\" "
 											   "will remove and ignore the buddy."), who);
 				purple_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0,
-									  gc->account, who, NULL,
+									  purple_connection_get_account(gc), who, NULL,
 									  b,
 									  G_CALLBACK(ignore_buddy),
 									  G_CALLBACK(keep_buddy));
@@ -2214,7 +2212,7 @@
 	char *msg;
 	char *url = NULL;
 	char *fullmsg;
-	PurpleAccount *account = gc->account;
+	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
 
 	while (l) {
@@ -2244,8 +2242,10 @@
 			yd->wm = TRUE;
 			if (yd->fd >= 0)
 				close(yd->fd);
-			if (gc->inpa)
-				purple_input_remove(gc->inpa);
+			if (yd->inpa) {
+				purple_input_remove(yd->inpa);
+				yd->inpa = 0;
+			}
 			url_data = purple_util_fetch_url(WEBMESSENGER_URL, TRUE,
 					"Purple/" VERSION, FALSE, -1, yahoo_login_page_cb, gc);
 			if (url_data != NULL)
@@ -3155,7 +3155,7 @@
 				_("Server closed the connection"));
 		return;
 	}
-	gc->last_received = time(NULL);
+	purple_connection_update_last_received(gc);
 	yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen);
 	memcpy(yd->rxqueue + yd->rxlen, buf, len);
 	yd->rxlen += len;
@@ -3245,10 +3245,10 @@
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, yd->session_id);
 
-	yahoo_packet_hash_str(pkt, 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))));
+	yahoo_packet_hash_str(pkt, 1, purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))));
 	yahoo_packet_send_and_free(pkt, yd);
 
-	gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
+	yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
 }
 
 #ifdef TRY_WEBMESSENGER_LOGIN
@@ -3272,13 +3272,13 @@
 	pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, yd->session_id);
 
 	yahoo_packet_hash(pkt, "sss", 0,
-	                  purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
-	                  1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
+	                  purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))),
+	                  1, purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))),
 	                  6, yd->auth);
 	yahoo_packet_send_and_free(pkt, yd);
 
 	g_free(yd->auth);
-	gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
+	yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
 }
 
 static void yahoo_web_pending(gpointer data, gint source, PurpleInputCondition cond)
@@ -3342,7 +3342,8 @@
 	}
 
 	yd->auth = g_string_free(s, FALSE);
-	purple_input_remove(gc->inpa);
+	purple_input_remove(yd->inpa);
+	yd->inpa = 0;
 	close(source);
 	g_free(yd->rxqueue);
 	yd->rxqueue = NULL;
@@ -3359,13 +3360,10 @@
 
 static void yahoo_got_cookies_send_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
-	PurpleConnection *gc;
-	YahooData *yd;
+	PurpleConnection *gc = data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	int written, remaining;
 
-	gc = data;
-	yd = purple_connection_get_protocol_data(gc);
-
 	remaining = strlen(yd->auth) - yd->auth_written;
 	written = write(source, yd->auth + yd->auth_written, remaining);
 
@@ -3375,9 +3373,10 @@
 		gchar *tmp;
 		g_free(yd->auth);
 		yd->auth = NULL;
-		if (gc->inpa)
-			purple_input_remove(gc->inpa);
-		gc->inpa = 0;
+		if (yd->inpa) {
+			purple_input_remove(yd->inpa);
+			yd->inpa = 0;
+		}
 		tmp = g_strdup_printf(_("Lost connection with %s: %s"),
 				"login.yahoo.com:80", g_strerror(errno));
 		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
@@ -3393,13 +3392,14 @@
 	g_free(yd->auth);
 	yd->auth = NULL;
 	yd->auth_written = 0;
-	purple_input_remove(gc->inpa);
-	gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
+	purple_input_remove(yd->inpa);
+	yd->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
 }
 
 static void yahoo_got_cookies(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleConnection *gc = data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
 		gchar *tmp;
@@ -3410,9 +3410,9 @@
 		return;
 	}
 
-	if (gc->inpa == 0)
+	if (yd->inpa == 0)
 	{
-		gc->inpa = purple_input_add(source, PURPLE_INPUT_WRITE,
+		yd->inpa = purple_input_add(source, PURPLE_INPUT_WRITE,
 			yahoo_got_cookies_send_cb, gc);
 		yahoo_got_cookies_send_cb(gc, source, PURPLE_INPUT_WRITE);
 	}
@@ -3678,7 +3678,7 @@
 	PurpleUtilFetchUrlData *url_data;
 
 	purple_connection_set_protocol_data(gc, yd);
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC);
 
 	purple_connection_update_progress(gc, _("Connecting"), 1, 2);
 
@@ -3725,8 +3725,10 @@
 	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GSList *l;
 
-	if (gc->inpa)
-		purple_input_remove(gc->inpa);
+	if (yd->inpa) {
+		purple_input_remove(yd->inpa);
+		yd->inpa = 0;
+	}
 
 	while (yd->url_datas) {
 		purple_util_fetch_url_cancel(yd->url_datas->data);
@@ -4476,7 +4478,7 @@
 		YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str);
 
 	/* use whole URL if using HTTP Proxy */
-	if ((purple_account_get_proxy_info(gc->account)) && (purple_proxy_info_get_type(purple_account_get_proxy_info(gc->account)) == PURPLE_PROXY_HTTP))
+	if ((purple_account_get_proxy_info(purple_connection_get_account(gc))) && (purple_proxy_info_get_type(purple_account_get_proxy_info(purple_connection_get_account(gc))) == PURPLE_PROXY_HTTP))
 	    use_whole_url = TRUE;
 
 	url_data = purple_util_fetch_url_request(
@@ -4612,7 +4614,7 @@
 	 *
 	 * If they have not set an IMVironment, then use the default.
 	 */
-	wb = purple_whiteboard_get_session(gc->account, who);
+	wb = purple_whiteboard_get_session(purple_connection_get_account(gc), who);
 	if (wb)
 		yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY);
 	else
@@ -5228,7 +5230,7 @@
 	if (!args || !args[0])
 		return PURPLE_CMD_RET_FAILED;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	purple_debug_info("yahoo", "Trying to join %s \n", args[0]);
 
 	comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
@@ -5262,7 +5264,7 @@
 	PurpleConversation *c;
 
 	c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-			username, gc->account);
+			username, purple_connection_get_account(gc));
 
 	g_return_val_if_fail(c != NULL, FALSE);
 
--- a/libpurple/protocols/yahoo/libymsg.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/yahoo/libymsg.h	Fri Dec 23 06:58:52 2011 +0000
@@ -188,6 +188,7 @@
 typedef struct {
 	PurpleConnection *gc;
 	int fd;
+	guint inpa;
 	guchar *rxqueue;
 	int rxlen;
 	PurpleCircBuffer *txbuf;
--- a/libpurple/protocols/yahoo/yahoo_aliases.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_aliases.c	Fri Dec 23 06:58:52 2011 +0000
@@ -331,7 +331,7 @@
 			gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
 			content = g_strdup_printf("<ab k=\"%s\" cc=\"9\">\n"
 						  "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
+						  purple_account_get_username(purple_connection_get_account(gc)),
 						  who, converted_alias_jp);
 			g_free(converted_alias_jp);
 			g_free(alias_jp);
@@ -339,7 +339,7 @@
 			gchar *escaped_alias = g_markup_escape_text(alias, -1);
 			content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"9\">\n"
 						  "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
+						  purple_account_get_username(purple_connection_get_account(gc)),
 						  who, escaped_alias);
 			g_free(escaped_alias);
 		}
@@ -351,7 +351,7 @@
 			gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
 			content = g_strdup_printf("<ab k=\"%s\" cc=\"1\">\n"
 						  "<ct e=\"1\"  yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
+						  purple_account_get_username(purple_connection_get_account(gc)),
 						  who, cb->id, converted_alias_jp);
 			g_free(converted_alias_jp);
 			g_free(alias_jp);
@@ -359,7 +359,7 @@
 			gchar *escaped_alias = g_markup_escape_text(alias, -1);
 			content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"1\">\n"
 						  "<ct e=\"1\"  yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-						  purple_account_get_username(gc->account),
+						  purple_account_get_username(purple_connection_get_account(gc)),
 						  who, cb->id, escaped_alias);
 			g_free(escaped_alias);
 		}
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_doodle.c	Fri Dec 23 06:58:52 2011 +0000
@@ -394,7 +394,7 @@
 	/* Make and send an acknowledge (ready) Doodle packet */
 	pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
 	yahoo_packet_hash_str(pkt, 49,  "IMVIRONMENT");
-	yahoo_packet_hash_str(pkt, 1,    purple_account_get_username(gc->account));
+	yahoo_packet_hash_str(pkt, 1,    purple_account_get_username(purple_connection_get_account(gc)));
 	yahoo_packet_hash_str(pkt, 14,   message);
 	yahoo_packet_hash_int(pkt, 13,   command);
 	yahoo_packet_hash_str(pkt, 5,    to);
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Fri Dec 23 06:58:52 2011 +0000
@@ -169,7 +169,7 @@
 		return;
 	}
 
-	xfer->fd = source;
+	purple_xfer_set_fd(xfer, source);
 
 	/* The first time we get here, assemble the tx buffer */
 	if (xd->txbuflen == 0) {
@@ -250,7 +250,7 @@
 		return;
 	}
 
-	xfer->fd = source;
+	purple_xfer_set_fd(xfer, source);
 
 	/* Assemble the tx buffer */
 	gc = xd->gc;
@@ -260,7 +260,7 @@
 	pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER,
 		YAHOO_STATUS_AVAILABLE, yd->session_id);
 
-	size = g_strdup_printf("%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
+	size = g_strdup_printf("%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer));
 	filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
 	encoded_filename = yahoo_string_encode(gc, filename, NULL);
 
@@ -279,7 +279,7 @@
 	port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
 	header = g_strdup_printf(
 		"POST http://%s:%d/notifyft HTTP/1.0\r\n"
-		"Content-length: %" G_GSIZE_FORMAT "\r\n"
+		"Content-length: %" G_GOFFSET_FORMAT "\r\n"
 		"Host: %s:%d\r\n"
 		"Cookie: Y=%s; T=%s\r\n"
 		"\r\n",
@@ -340,7 +340,7 @@
 			}
 		}
 	} else {
-		xfer->fd = -1;
+		purple_xfer_set_fd(xfer, -1);
 		if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
 		                              yahoo_receivefile_connected, xfer) == NULL) {
 			purple_notify_error(gc, NULL, _("File Transfer Failed"),
@@ -378,7 +378,7 @@
 			302, 268,
 			300, 268,
 			27,  filename,
-			28,  purple_xfer_get_size(xfer),
+			28,  (int)purple_xfer_get_size(xfer),
 			301, 268,
 			303, 268);
 		g_free(filename);
@@ -411,14 +411,14 @@
 	/* We don't need to do anything here, do we? */
 }
 
-static guint calculate_length(const gchar *l, size_t len)
+static goffset calculate_length(const gchar *l, size_t len)
 {
 	int i;
 
 	for (i = 0; i < len; i++) {
 		if (!g_ascii_isdigit(l[i]))
 			continue;
-		return strtol(l + i, NULL, 10);
+		return g_ascii_strtoll(l + i, NULL, 10);
 	}
 	return 0;
 }
@@ -430,14 +430,14 @@
 	gchar *start = NULL;
 	gchar *length;
 	gchar *end;
-	int filelen;
+	goffset filelen;
 	struct yahoo_xfer_data *xd = purple_xfer_get_protocol_data(xfer);
 
 	if (purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE) {
 		return 0;
 	}
 
-	len = read(xfer->fd, buf, sizeof(buf));
+	len = read(purple_xfer_get_fd(xfer), buf, sizeof(buf));
 
 	if (len <= 0) {
 		if ((purple_xfer_get_size(xfer) > 0) &&
@@ -500,7 +500,7 @@
 		return -1;
 	}
 
-	len = write(xfer->fd, buffer, size);
+	len = write(purple_xfer_get_fd(xfer), buffer, size);
 
 	if (len == -1) {
 		if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))
@@ -612,9 +612,10 @@
 {
 	char *tx = NULL;
 	int written;
+	int fd = purple_xfer_get_fd(xfer);
 
 	tx = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\nConnection: close\r\n\r\n";
-	written = write(xfer->fd, tx, strlen(tx));
+	written = write(fd, tx, strlen(tx));
 
 	if (written < 0 && errno == EAGAIN)
 		written = 0;
@@ -622,8 +623,8 @@
 		purple_debug_info("yahoo", "p2p filetransfer: Unable to write HTTP OK");
 
 	/* close connection */
-	close(xfer->fd);
-	xfer->fd = -1;
+	close(fd);
+	purple_xfer_set_fd(xfer, -1);
 }
 
 static void yahoo_xfer_end(PurpleXfer *xfer_old)
@@ -639,7 +640,7 @@
 	   && xfer_data->filename_list) {
 
 		/* Send HTTP OK in case of p2p transfer, when we act as server */
-		if((xfer_data->xfer_url != NULL) && (xfer_old->fd >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE))
+		if((xfer_data->xfer_url != NULL) && (purple_xfer_get_fd(xfer_old) >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE))
 			yahoo_p2p_ft_server_send_OK(xfer_old);
 
 		/* removing top of filename & size list completely */
@@ -656,10 +657,10 @@
 		if(xfer_data->filename_list)
 		{
 			gchar* filename;
-			long filesize;
+			goffset filesize;
 
 			filename = xfer_data->filename_list->data;
-			filesize = atol( xfer_data->size_list->data );
+			filesize = g_ascii_strtoll( xfer_data->size_list->data, NULL, 10 );
 
 			gc = xfer_data->gc;
 			yd = purple_connection_get_protocol_data(gc);
@@ -692,7 +693,7 @@
 			purple_xfer_set_protocol_data(xfer_old, NULL);
 
 			/* Build the file transfer handle. */
-			xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, purple_xfer_get_remote_user(xfer_old));
+			xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, purple_xfer_get_remote_user(xfer_old));
 
 
 			if (xfer) {
@@ -802,7 +803,7 @@
 	struct yahoo_xfer_data *xfer_data;
 	char *service = NULL;
 	char *filename = NULL;
-	unsigned long filesize = 0L;
+	goffset filesize = G_GOFFSET_CONSTANT(0);
 	GSList *l;
 
 	yd = purple_connection_get_protocol_data(gc);
@@ -830,7 +831,7 @@
 			filename = pair->value;
 			break;
 		case 28:
-			filesize = atol(pair->value);
+			filesize = g_ascii_strtoll(pair->value, NULL, 10);
 			break;
 		case 49:
 			service = pair->value;
@@ -879,7 +880,7 @@
 	                xfer_data->host, xfer_data->port, xfer_data->path, url);
 
 	/* Build the file transfer handle. */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, from);
 	if (xfer == NULL) {
 		g_free(xfer_data);
 		g_return_if_reached();
@@ -935,7 +936,7 @@
 	xfer_data->gc = gc;
 
 	/* Build the file transfer handle. */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
 	if (xfer == NULL)
 	{
 		g_free(xfer_data);
@@ -1195,13 +1196,13 @@
 	else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
 	{
 		xd->status_15 = TRANSFER_PHASE;
-		xfer->fd = source;
+		purple_xfer_set_fd(xfer, source);
 		purple_xfer_start(xfer, source, NULL, 0);
 	}
 	else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && (xd->status_15 == ACCEPTED || xd->status_15 == P2P_GET_REQUESTED) )
 	{
 		xd->status_15 = TRANSFER_PHASE;
-		xfer->fd = source;
+		purple_xfer_set_fd(xfer, source);
 		/* Remove Read event */
 		purple_input_remove(xd->input_event);
 		xd->input_event = 0;
@@ -1214,7 +1215,7 @@
 		purple_input_remove(xd->input_event);
 		xd->input_event = 0;
 		close(source);
-		xfer->fd = -1;
+		purple_xfer_set_fd(xfer, -1);
 		/* start local server, listen for connections */
 		purple_network_listen(xd->yahoo_local_p2p_ft_server_port, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer);
 	}
@@ -1265,7 +1266,7 @@
 				initial_buffer = g_strdup_printf("POST /%s HTTP/1.1\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
 						"Host: %s\r\n"
-						"Content-Length: %" G_GSIZE_FORMAT "\r\n"
+						"Content-Length: %" G_GOFFSET_FORMAT "\r\n"
 						"Cache-Control: no-cache\r\n\r\n",
 										xd->path,
 										xd->host,
@@ -1278,7 +1279,7 @@
 						"Cookie:%s\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
 						"Host: %s\r\n"
-						"Content-Length: %" G_GSIZE_FORMAT "\r\n"
+						"Content-Length: %" G_GOFFSET_FORMAT "\r\n"
 						"Cache-Control: no-cache\r\n\r\n",
 										purple_url_encode(xd->xfer_idstring_for_relay),
 										purple_normalize(account, purple_account_get_username(account)),
@@ -1377,7 +1378,7 @@
 
 	purple_input_remove(xd->input_event);
 	xd->status_15 = TRANSFER_PHASE;
-	xfer->fd = source;
+	purple_xfer_set_fd(xfer, source);
 	purple_xfer_start(xfer, source, NULL, 0);
 }
 
@@ -1433,7 +1434,7 @@
 		                            "Server: Y!/1.0\r\n"
 		                            "MIME-version: 1.0\r\n"
 		                            "Last-modified: %s GMT\r\n"
-		                            "Content-length: %" G_GSIZE_FORMAT "\r\n\r\n",
+		                            "Content-length: %" G_GOFFSET_FORMAT "\r\n\r\n",
 		                            time_str, time_str, purple_xfer_get_size(xfer));
 		xd->txbuf = (guchar *)initial_buffer;
 		xd->txbuflen = strlen(initial_buffer);
@@ -1478,7 +1479,7 @@
 	close(xd->yahoo_local_p2p_ft_server_fd);
 
 	/* Add an Input Read event to the file descriptor */
-	xfer->fd = acceptfd;
+	purple_xfer_set_fd(xfer, acceptfd);
 	if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
 		xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_POST_cb, data);
 	else
@@ -1601,7 +1602,7 @@
 	char *filename = NULL;
 	char *xfer_peer_idstring = NULL;
 	char *utf8_filename;
-	unsigned long filesize = 0L;
+	goffset filesize = G_GOFFSET_CONSTANT(0);
 	GSList *l;
 	GSList *filename_list = NULL;
 	GSList *size_list = NULL;
@@ -1718,7 +1719,7 @@
 	filename_list = g_slist_reverse(filename_list);
 	size_list = g_slist_reverse(size_list);
 	filename = filename_list->data;
-	filesize = atol(size_list->data);
+	filesize = g_ascii_strtoll(size_list->data, NULL, 10);
 
 	if(!from) return;
 	xfer_data = g_new0(struct yahoo_xfer_data, 1);
@@ -1730,7 +1731,7 @@
 	xfer_data->size_list = size_list;
 
 	/* Build the file transfer handle. */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, from);
 	if (xfer == NULL)
 	{
 		g_free(xfer_data);
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_picture.c	Fri Dec 23 06:58:52 2011 +0000
@@ -170,7 +170,7 @@
 	}
 
 	if (who) {
-		PurpleBuddy *b = purple_find_buddy(gc->account, who);
+		PurpleBuddy *b = purple_find_buddy(purple_connection_get_account(gc), who);
 		const char *locksum = NULL;
 
 		/* FIXME: Cleanup this strtol() stuff if possible. */
@@ -251,7 +251,7 @@
 			yahoo_send_picture_request(gc, who);
 		else if ((avatar == 0) || (avatar == 1)) {
 			YahooFriend *f;
-			purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL);
+			purple_buddy_icons_set_for_user(purple_connection_get_account(gc), who, NULL, 0, NULL);
 			if ((f = yahoo_friend_find(gc, who)))
 				yahoo_friend_set_buddy_icon_need_request(f, TRUE);
 			purple_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who);
@@ -536,7 +536,7 @@
 void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
 	YahooData *yd = purple_connection_get_protocol_data(gc);
-	PurpleAccount *account = gc->account;
+	PurpleAccount *account = purple_connection_get_account(gc);
 
 	if (img == NULL) {
 		g_free(yd->picture_url);
--- a/libpurple/protocols/zephyr/ZRetSubs.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/zephyr/ZRetSubs.c	Fri Dec 23 06:58:52 2011 +0000
@@ -132,6 +132,11 @@
 
 		__subscriptions_num = __subscriptions_num / 3;
 
+		if (!__subscriptions_num) {
+			ZFreeNotice(&retnotice);
+			continue;
+		}
+
 		__subscriptions_list = (ZSubscription_t *)
 			malloc((unsigned)(__subscriptions_num*
 					  sizeof(ZSubscription_t)));
--- a/libpurple/protocols/zephyr/zephyr.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Fri Dec 23 06:58:52 2011 +0000
@@ -777,9 +777,9 @@
 			if (ZParseLocations(&notice, NULL, &nlocs, &user) != ZERR_NONE)
 				return;
 
-			if ((b = purple_find_buddy(gc->account, user)) == NULL) {
+			if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) {
 				char* stripped_user = zephyr_strip_local_realm(zephyr,user);
-				b = purple_find_buddy(gc->account,stripped_user);
+				b = purple_find_buddy(purple_connection_get_account(gc),stripped_user);
 				g_free(stripped_user);
 			}
 
@@ -815,9 +815,9 @@
 				purple_notify_user_info_destroy(user_info);
 			} else {
 				if (nlocs>0)
-					purple_prpl_got_user_status(gc->account, b ? bname : user, "available", NULL);
+					purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL);
 				else
-					purple_prpl_got_user_status(gc->account, b ? bname : user, "offline", NULL);
+					purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL);
 			}
 
 			g_free(user);
@@ -900,7 +900,7 @@
 			}
 
 			gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-														 zt2->name, gc->account);
+														 zt2->name, purple_connection_get_account(gc));
 			gcc = purple_conversation_get_chat_data(gconv1);
 #ifndef INET_ADDRSTRLEN
 #define INET_ADDRSTRLEN 16
@@ -1156,9 +1156,9 @@
 				gchar *locval;
 				user = tree_child(find_node(newparsetree,"user"),2)->contents;
 
-				if ((b = purple_find_buddy(gc->account, user)) == NULL) {
+				if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) {
 					gchar *stripped_user = zephyr_strip_local_realm(zephyr,user);
-					b = purple_find_buddy(gc->account, stripped_user);
+					b = purple_find_buddy(purple_connection_get_account(gc), stripped_user);
 					g_free(stripped_user);
 				}
 				locations = find_node(newparsetree,"locations");
@@ -1200,9 +1200,9 @@
 					purple_notify_user_info_destroy(user_info);
 				} else {
 					if (nlocs>0)
-						purple_prpl_got_user_status(gc->account, b ? bname : user, "available", NULL);
+						purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL);
 					else
-						purple_prpl_got_user_status(gc->account, b ? bname : user, "offline", NULL);
+						purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL);
 				}
 			}
 			else if (!g_ascii_strncasecmp(spewtype,"subscribed",10)) {
@@ -1521,11 +1521,11 @@
 		while (fgets(buff, BUFSIZ, fd)) {
 			strip_comments(buff);
 			if (buff[0]) {
-				if (!(b = purple_find_buddy(gc->account, buff))) {
+				if (!(b = purple_find_buddy(purple_connection_get_account(gc), buff))) {
 					char *stripped_user = zephyr_strip_local_realm(zephyr,buff);
 					purple_debug_info("zephyr","stripped_user %s\n",stripped_user);
-					if (!(b = purple_find_buddy(gc->account,stripped_user))){
-						b = purple_buddy_new(gc->account, stripped_user, NULL);
+					if (!(b = purple_find_buddy(purple_connection_get_account(gc),stripped_user))){
+						b = purple_buddy_new(purple_connection_get_account(gc), stripped_user, NULL);
 						purple_blist_add_buddy(b, NULL, g, NULL);
 					}
 					g_free(stripped_user);
@@ -1564,14 +1564,14 @@
 	gchar *exposure;
 
 	gc = purple_account_get_connection(account);
-	read_anyone = purple_account_get_bool(gc->account,"read_anyone",TRUE);
-	read_zsubs = purple_account_get_bool(gc->account,"read_zsubs",TRUE);
-	exposure = (gchar *)purple_account_get_string(gc->account, "exposure_level", EXPOSE_REALMVIS);
+	read_anyone = purple_account_get_bool(purple_connection_get_account(gc),"read_anyone",TRUE);
+	read_zsubs = purple_account_get_bool(purple_connection_get_account(gc),"read_zsubs",TRUE);
+	exposure = (gchar *)purple_account_get_string(purple_connection_get_account(gc), "exposure_level", EXPOSE_REALMVIS);
 
 #ifdef WIN32
 	username = purple_account_get_username(account);
 #endif
-	gc->flags |= PURPLE_CONNECTION_AUTO_RESP | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_AUTO_RESP | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC);
 	zephyr = g_new0(zephyr_account, 1);
 	purple_connection_set_protocol_data(gc, zephyr);
 
@@ -1580,13 +1580,13 @@
 	/* Make sure that the exposure (visibility) is set to a sane value */
 	zephyr->exposure=g_strdup(normalize_zephyr_exposure(exposure));
 
-	if (purple_account_get_bool(gc->account,"use_tzc",0)) {
+	if (purple_account_get_bool(purple_connection_get_account(gc),"use_tzc",0)) {
 		zephyr->connection_type = PURPLE_ZEPHYR_TZC;
 	} else {
 		zephyr->connection_type = PURPLE_ZEPHYR_KRB4;
 	}
 
-	zephyr->encoding = (char *)purple_account_get_string(gc->account, "encoding", ZEPHYR_FALLBACK_CHARSET);
+	zephyr->encoding = (char *)purple_account_get_string(purple_connection_get_account(gc), "encoding", ZEPHYR_FALLBACK_CHARSET);
 	purple_connection_update_progress(gc, _("Connecting"), 0, 8);
 
 	/* XXX z_call_s should actually try to report the com_err determined error */
@@ -1607,7 +1607,7 @@
 		if (pid == 0) {
 			unsigned int i=0;
 			gboolean found_ps = FALSE;
-			gchar ** tzc_cmd_array = g_strsplit(purple_account_get_string(gc->account,"tzc_command","/usr/bin/tzc -e %s")," ",0);
+			gchar ** tzc_cmd_array = g_strsplit(purple_account_get_string(purple_connection_get_account(gc),"tzc_command","/usr/bin/tzc -e %s")," ",0);
 			if (close(1) == -1) {
 				exit(-1);
 			}
@@ -1779,7 +1779,7 @@
 						if ((realm = strchr(username,'@')))
 							zephyr->realm = g_strdup_printf("%s",realm+1);
 						else {
-							realm = (gchar *)purple_account_get_string(gc->account,"realm","");
+							realm = (gchar *)purple_account_get_string(purple_connection_get_account(gc),"realm","");
 							if (!*realm) {
 								realm = "local-realm";
 							}
@@ -1816,7 +1816,7 @@
 		z_call_s(ZOpenPort(&(zephyr->port)), "Couldn't open port");
 		z_call_s(ZSetLocation((char *)zephyr->exposure), "Couldn't set location");
 
-		realm = (gchar *)purple_account_get_string(gc->account,"realm","");
+		realm = (gchar *)purple_account_get_string(purple_connection_get_account(gc),"realm","");
 		if (!*realm) {
 			realm = ZGetRealm();
 		}
@@ -1972,10 +1972,10 @@
 	}
 	g_list_free(zephyr->pending_zloc_names);
 
-	if (purple_account_get_bool(gc->account, "write_anyone", FALSE))
+	if (purple_account_get_bool(purple_connection_get_account(gc), "write_anyone", FALSE))
 		write_anyone(zephyr);
 
-	if (purple_account_get_bool(gc->account, "write_zsubs", FALSE))
+	if (purple_account_get_bool(purple_connection_get_account(gc), "write_zsubs", FALSE))
 		write_zsubs(zephyr);
 
 	s = zephyr->subscrips;
@@ -2047,7 +2047,7 @@
 	sig = zephyr_get_signature();
 
 	gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, zt->name,
-												 gc->account);
+												 purple_connection_get_account(gc));
 	gcc = purple_conversation_get_chat_data(gconv1);
 
 	if (!(inst = (char *)purple_conv_chat_get_topic(gcc)))
@@ -2576,7 +2576,7 @@
 	if (!zt)
 		return;
 	gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, zt->name,
-												gc->account);
+												purple_connection_get_account(gc));
 	gcc = purple_conversation_get_chat_data(gconv);
 
 	topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic);
@@ -2591,7 +2591,7 @@
 				      const char *cmd, char **args, char **error, void *data)
 {
 	char *recipient;
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);;
 	if (!g_ascii_strcasecmp(args[0],"*"))
 		return PURPLE_CMD_RET_FAILED;  /* "*" is not a valid argument */
@@ -2610,7 +2610,7 @@
 static PurpleCmdRet zephyr_purple_cmd_zlocate(PurpleConversation *conv,
 					  const char *cmd, char **args, char **error, void *data)
 {
-	zephyr_zloc(purple_conversation_get_gc(conv),args[0]);
+	zephyr_zloc(purple_conversation_get_connection(conv),args[0]);
 	return PURPLE_CMD_RET_OK;
 }
 
@@ -2623,7 +2623,7 @@
 
 	PurpleConvChat *gcc = purple_conversation_get_chat_data(conv);
 	const char* instance = args[0];
-	zephyr_chat_set_topic(purple_conversation_get_gc(conv),purple_conv_chat_get_id(gcc),instance);
+	zephyr_chat_set_topic(purple_conversation_get_connection(conv),purple_conv_chat_get_id(gcc),instance);
 	return PURPLE_CMD_RET_OK;
 }
 
@@ -2635,7 +2635,7 @@
 	g_hash_table_insert(triple,"class",args[0]);
 	g_hash_table_insert(triple,"instance",args[1]);
 	g_hash_table_insert(triple,"recipient",args[2]);
-	zephyr_join_chat(purple_conversation_get_gc(conv),triple);
+	zephyr_join_chat(purple_conversation_get_connection(conv),triple);
 	return PURPLE_CMD_RET_OK;
 }
 
@@ -2643,7 +2643,7 @@
 				     const char *cmd, char **args, char **error, void *data)
 {
 	/* args = instance, message */
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if ( zephyr_send_message(zephyr,"message",args[0],"",args[1],zephyr_get_signature(),""))
 		return PURPLE_CMD_RET_OK;
@@ -2655,7 +2655,7 @@
 				      const char *cmd, char **args, char **error, void *data)
 {
 	/* args = class, instance, message */
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if ( zephyr_send_message(zephyr,args[0],args[1],"",args[2],zephyr_get_signature(),""))
 		return PURPLE_CMD_RET_OK;
@@ -2667,7 +2667,7 @@
 				       const char *cmd, char **args, char **error, void *data)
 {
 	/* args = class, instance, recipient, message */
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if ( zephyr_send_message(zephyr,args[0],args[1],args[2],args[3],zephyr_get_signature(),""))
 		return PURPLE_CMD_RET_OK;
@@ -2679,7 +2679,7 @@
 				      const char *cmd, char **args, char **error, void *data)
 {
 	/* args = instance, recipient, message */
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if ( zephyr_send_message(zephyr,"message",args[0],args[1],args[2],zephyr_get_signature(),""))
 		return PURPLE_CMD_RET_OK;
@@ -2691,7 +2691,7 @@
 				     const char *cmd, char **args, char **error, void *data)
 {
 	/* args = class, message */
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if ( zephyr_send_message(zephyr,args[0],"PERSONAL","",args[1],zephyr_get_signature(),""))
 		return PURPLE_CMD_RET_OK;
--- a/libpurple/proxy.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/proxy.c	Fri Dec 23 06:58:52 2011 +0000
@@ -2024,7 +2024,6 @@
 		return;
 	}
 
-	i = 0;
 	buf[0] = 0x05;		/* SOCKS version 5 */
 
 	if (purple_proxy_info_get_username(connect_data->gpi) != NULL) {
--- a/libpurple/prpl.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/prpl.c	Fri Dec 23 06:58:52 2011 +0000
@@ -446,13 +446,13 @@
 	g_return_if_fail(gc != NULL);
 	g_return_if_fail(who != NULL);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(gc->account));
+	prpl = purple_find_prpl(purple_account_get_protocol_id(purple_connection_get_account(gc)));
 	send_attention = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention;
 	g_return_if_fail(send_attention != NULL);
 
 	mtime = time(NULL);
 
-	attn = purple_get_attention_type_from_code(gc->account, type_code);
+	attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code);
 
 	if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL)
 		alias = purple_buddy_get_contact_alias(buddy);
@@ -473,7 +473,7 @@
 	if (!send_attention(gc, who, type_code))
 		return;
 
-	conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, gc->account, who);
+	conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, purple_connection_get_account(gc), who);
 	purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, description, flags, mtime);
 	purple_prpl_attention(conv, who, type_code, PURPLE_MESSAGE_SEND, time(NULL));
 
@@ -492,7 +492,7 @@
 
 	mtime = time(NULL);
 
-	attn = purple_get_attention_type_from_code(gc->account, type_code);
+	attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code);
 
 	/* PURPLE_MESSAGE_NOTIFY is for attention messages. */
 	flags = PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_RECV;
--- a/libpurple/purple-3.pc.in	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/purple-3.pc.in	Fri Dec 23 06:58:52 2011 +0000
@@ -1,7 +1,7 @@
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
-includedir=@includedir@
+includedir=@includedir@/libpurple
 datarootdir=@datarootdir@
 datadir=@datadir@
 sysconfdir=@sysconfdir@
--- a/libpurple/server.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/server.c	Fri Dec 23 06:58:52 2011 +0000
@@ -149,7 +149,7 @@
 	 * this only reset lar->sent if we're away AND idle?
 	 */
 	auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply");
-	if((gc->flags & PURPLE_CONNECTION_AUTO_RESP) &&
+	if((purple_connection_get_flags(gc) & PURPLE_CONNECTION_AUTO_RESP) &&
 			!purple_presence_is_available(presence) &&
 			!purple_strequal(auto_reply_pref, "never")) {
 
@@ -570,7 +570,7 @@
 	 * We should update the conversation window buttons and menu,
 	 * if it exists.
 	 */
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, gc->account);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, purple_connection_get_account(gc));
 
 	/*
 	 * Make copies of the message and the sender in case plugins want
@@ -581,7 +581,7 @@
 
 	plugin_return = GPOINTER_TO_INT(
 		purple_signal_emit_return_1(purple_conversations_get_handle(),
-								  "receiving-im-msg", gc->account,
+								  "receiving-im-msg", purple_connection_get_account(gc),
 								  &angel, &buffy, conv, &flags));
 
 	if (!buffy || !angel || plugin_return) {
@@ -593,12 +593,12 @@
 	name = angel;
 	message = buffy;
 
-	purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", gc->account,
+	purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", purple_connection_get_account(gc),
 					 name, message, conv, flags);
 
 	/* search for conversation again in case it was created by received-im-msg handler */
 	if (conv == NULL)
-		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account);
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc));
 
 	if (conv == NULL)
 		conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
@@ -615,7 +615,7 @@
 	 *  - or we're not idle and the 'only auto respond if idle' pref
 	 *    is set
 	 */
-	if (gc->flags & PURPLE_CONNECTION_AUTO_RESP)
+	if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_AUTO_RESP)
 	{
 		PurplePresence *presence;
 		PurpleStatus *status;
@@ -688,7 +688,7 @@
 	PurpleConversation *conv;
 	PurpleConvIm *im = NULL;
 
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc));
 	if (conv != NULL) {
 		im = PURPLE_CONV_IM(conv);
 
@@ -698,15 +698,15 @@
 		{
 			case PURPLE_TYPING:
 				purple_signal_emit(purple_conversations_get_handle(),
-								   "buddy-typing", gc->account, name);
+								   "buddy-typing", purple_connection_get_account(gc), name);
 				break;
 			case PURPLE_TYPED:
 				purple_signal_emit(purple_conversations_get_handle(),
-								   "buddy-typed", gc->account, name);
+								   "buddy-typed", purple_connection_get_account(gc), name);
 				break;
 			case PURPLE_NOT_TYPING:
 				purple_signal_emit(purple_conversations_get_handle(),
-								   "buddy-typing-stopped", gc->account, name);
+								   "buddy-typing-stopped", purple_connection_get_account(gc), name);
 				break;
 		}
 	}
@@ -720,7 +720,7 @@
 	PurpleConversation *conv;
 	PurpleConvIm *im;
 
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc));
 	if (conv != NULL)
 	{
 		im = PURPLE_CONV_IM(conv);
@@ -734,7 +734,7 @@
 	else
 	{
 		purple_signal_emit(purple_conversations_get_handle(),
-						 "buddy-typing-stopped", gc->account, name);
+						 "buddy-typing-stopped", purple_connection_get_account(gc), name);
 	}
 }
 
@@ -925,7 +925,7 @@
 
 	plugin_return = GPOINTER_TO_INT(
 		purple_signal_emit_return_1(purple_conversations_get_handle(),
-								  "receiving-chat-msg", g->account,
+								  "receiving-chat-msg", purple_connection_get_account(g),
 								  &angel, &buffy, conv, &flags));
 
 	if (!buffy || !angel || plugin_return) {
@@ -937,7 +937,7 @@
 	who = angel;
 	message = buffy;
 
-	purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", g->account,
+	purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", purple_connection_get_account(g),
 					 who, message, conv, flags);
 
 	purple_conv_chat_write(chat, who, message, flags, mtime);
--- a/libpurple/util.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/util.c	Fri Dec 23 06:58:52 2011 +0000
@@ -3331,9 +3331,9 @@
 }
 
 char *
-purple_str_size_to_units(size_t size)
+purple_str_size_to_units(goffset size)
 {
-	static const char * const size_str[] = { "bytes", "KiB", "MiB", "GiB" };
+	static const char * const size_str[] = { "bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" };
 	float size_mag;
 	int size_index = 0;
 
@@ -3346,7 +3346,7 @@
 	else {
 		size_mag = (float)size;
 
-		while ((size_index < 3) && (size_mag > 1024)) {
+		while ((size_index < G_N_ELEMENTS(size_str) - 1) && (size_mag > 1024)) {
 			size_mag /= 1024;
 			size_index++;
 		}
@@ -4637,7 +4637,7 @@
  * This function is copied from g_strerror() but changed to use
  * gai_strerror().
  */
-G_CONST_RETURN gchar *
+const gchar *
 purple_gai_strerror(gint errnum)
 {
 	static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
--- a/libpurple/util.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/util.h	Fri Dec 23 06:58:52 2011 +0000
@@ -1091,7 +1091,7 @@
  *
  * @return The string in units form. This must be freed.
  */
-char *purple_str_size_to_units(size_t size);
+char *purple_str_size_to_units(goffset size);
 
 /**
  * Converts seconds into a human-readable form.
@@ -1344,7 +1344,7 @@
  *
  * @return The UTF-8 error message.
  */
-G_CONST_RETURN gchar *purple_gai_strerror(gint errnum);
+const gchar *purple_gai_strerror(gint errnum);
 
 /**
  * Compares two UTF-8 strings case-insensitively.  This comparison is
--- a/libpurple/whiteboard.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/whiteboard.c	Fri Dec 23 06:58:52 2011 +0000
@@ -25,6 +25,23 @@
 #include "whiteboard.h"
 #include "prpl.h"
 
+/**
+ * A PurpleWhiteboard
+ */
+struct _PurpleWhiteboard
+{
+	int state;                       /**< State of whiteboard session */
+
+	PurpleAccount *account;            /**< Account associated with this session */
+	char *who;                       /**< Name of the remote user */
+
+	void *ui_data;                   /**< Graphical user-interface data */
+	void *proto_data;                /**< Protocol specific data */
+	PurpleWhiteboardPrplOps *prpl_ops; /**< Protocol-plugin operations */
+
+	GList *draw_list;                /**< List of drawing elements/deltas to send */
+};
+
 /******************************************************************************
  * Globals
  *****************************************************************************/
--- a/libpurple/whiteboard.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/whiteboard.h	Fri Dec 23 06:58:52 2011 +0000
@@ -26,6 +26,9 @@
 #ifndef _PURPLE_WHITEBOARD_H_
 #define _PURPLE_WHITEBOARD_H_
 
+/** @copydoc _PurpleWhiteboard */
+typedef struct _PurpleWhiteboard PurpleWhiteboard;
+
 /**
  * Whiteboard PRPL Operations
  */
@@ -33,22 +36,6 @@
 
 #include "account.h"
 
-/**
- * A PurpleWhiteboard
- */
-typedef struct _PurpleWhiteboard
-{
-	int state;                       /**< State of whiteboard session */
-
-	PurpleAccount *account;            /**< Account associated with this session */
-	char *who;                       /**< Name of the remote user */
-
-	void *ui_data;                   /**< Graphical user-interface data */
-	void *proto_data;                /**< Protocol specific data */
-	PurpleWhiteboardPrplOps *prpl_ops; /**< Protocol-plugin operations */
-
-	GList *draw_list;                /**< List of drawing elements/deltas to send */
-} PurpleWhiteboard;
 
 /**
  * The PurpleWhiteboard UI Operations
--- a/libpurple/win32/libc_interface.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/win32/libc_interface.c	Fri Dec 23 06:58:52 2011 +0000
@@ -300,6 +300,50 @@
   return (const char *) dst;
 }
 
+int
+wpurple_inet_pton(int af, const char *src, void *dst)
+{
+	/* struct sockaddr can't accomodate struct sockaddr_in6. */
+	union {
+		struct sockaddr_in6 sin6;
+		struct sockaddr_in sin;
+	} sa;
+	size_t srcsize;
+	
+	switch(af)
+	{
+		case AF_INET:
+			sa.sin.sin_family = AF_INET;
+			srcsize = sizeof (sa.sin);
+		break;
+		case AF_INET6:
+			sa.sin6.sin6_family = AF_INET6;
+			srcsize = sizeof (sa.sin6);
+		break;
+		default:
+			errno = WSAEPFNOSUPPORT;
+			return -1;
+	}
+	
+	if (WSAStringToAddress(src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
+	{
+		errno = WSAGetLastError();
+		return -1;
+	}
+	
+	switch(af)
+	{
+		case AF_INET:
+			memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
+		break;
+		case AF_INET6:
+			memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
+		break;
+	}
+	
+	return 1;
+}
+
 
 /* netdb.h */
 struct hostent* wpurple_gethostbyname(const char *name) {
--- a/libpurple/win32/libc_interface.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/win32/libc_interface.h	Fri Dec 23 06:58:52 2011 +0000
@@ -89,6 +89,9 @@
 #define inet_ntop( af, src, dst, cnt ) \
 wpurple_inet_ntop( af, src, dst, cnt )
 
+#define inet_pton( af, src, dst ) \
+wpurple_inet_pton( af, src, dst )
+
 /* netdb.h */
 #define gethostbyname( name ) \
 wpurple_gethostbyname( name )
--- a/libpurple/win32/libc_internal.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/libpurple/win32/libc_internal.h	Fri Dec 23 06:58:52 2011 +0000
@@ -48,6 +48,7 @@
 int wpurple_inet_aton(const char *name, struct in_addr *addr);
 const char *
 wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt);
+int wpurple_inet_pton(int af, const char *src, void *dst);
 
 /* netdb.h */
 struct hostent* wpurple_gethostbyname(const char *name);
--- a/pidgin/Makefile.am	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/Makefile.am	Fri Dec 23 06:58:52 2011 +0000
@@ -34,7 +34,7 @@
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = pidgin-3.pc
 
-SUBDIRS = pixmaps plugins
+SUBDIRS = pixmaps plugins themes
 
 bin_PROGRAMS = pidgin
 
@@ -156,6 +156,7 @@
 pidgin_LDADD = \
 	@LIBOBJS@ \
 	$(GLIB_LIBS) \
+	$(GCR_LIBS) \
 	$(DBUS_LIBS) \
 	$(GSTREAMER_LIBS) \
 	$(XSS_LIBS) \
@@ -181,6 +182,7 @@
 	-I$(top_builddir) \
 	-I$(top_srcdir) \
 	$(GLIB_CFLAGS) \
+	$(GCR_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
--- a/pidgin/gtkblist.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkblist.c	Fri Dec 23 06:58:52 2011 +0000
@@ -351,13 +351,13 @@
 
 static void gtk_blist_menu_autojoin_cb(GtkWidget *w, PurpleChat *chat)
 {
-	purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin",
+	purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin",
 			gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
 }
 
 static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat)
 {
-	purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent",
+	purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent",
 			gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
 }
 
@@ -924,7 +924,7 @@
 	gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), GTK_RESPONSE_OK, sensitive);
 
 	gc = purple_account_get_connection(data->rq_data.account);
-	prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL;
+	prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
 	sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL);
 
 	gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive);
@@ -948,7 +948,7 @@
 	if (gc == NULL)
 		return FALSE;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	return (prpl_info->chat_info != NULL);
 }
@@ -1038,6 +1038,7 @@
 rebuild_chat_entries(PidginChatData *data, const char *default_chat_name)
 {
 	PurpleConnection *gc;
+	PurplePluginProtocolInfo *prpl_info;
 	GList *list = NULL, *tmp;
 	GHashTable *defaults = NULL;
 	struct proto_chat_entry *pce;
@@ -1046,17 +1047,18 @@
 	g_return_if_fail(data->rq_data.account != NULL);
 
 	gc = purple_account_get_connection(data->rq_data.account);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL);
 
 	g_list_free(data->entries);
 	data->entries = NULL;
 
-	if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL)
-		list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc);
-
-	if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL)
-		defaults = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, default_chat_name);
+	if (prpl_info->chat_info != NULL)
+		list = prpl_info->chat_info(gc);
+
+	if (prpl_info->chat_info_defaults != NULL)
+		defaults = prpl_info->chat_info_defaults(gc, default_chat_name);
 
 	for (tmp = list; tmp; tmp = tmp->next)
 	{
@@ -1419,7 +1421,7 @@
                                       PurpleBlistNode *node)
 {
 	GList *l, *ll;
-	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	if(!prpl_info || !prpl_info->blist_node_menu)
 		return;
@@ -1527,7 +1529,7 @@
 
 	if (prpl_info && prpl_info->send_file) {
 		if (!prpl_info->can_receive_file ||
-			prpl_info->can_receive_file(purple_account_get_connection(buddy->account), buddy->name))
+			prpl_info->can_receive_file(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)))
 		{
 			pidgin_new_item_from_stock(menu, _("_Send File..."),
 									 PIDGIN_STOCK_TOOLBAR_SEND_FILE,
@@ -1555,11 +1557,11 @@
 				NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
 	}
 
-	pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(buddy->account), node);
+	pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(purple_buddy_get_account(buddy)), node);
 	pidgin_append_blist_node_extended_menu(menu, node);
 
 	if (!contact_expanded && contact != NULL)
-		pidgin_append_blist_node_move_to_menu(menu, (PurpleBlistNode *)contact);
+		pidgin_append_blist_node_move_to_menu(menu, PURPLE_BLIST_NODE(contact));
 
 	if (node->parent && node->parent->child->next &&
               !sub && !contact_expanded) {
@@ -1608,7 +1610,7 @@
 			return FALSE;
 		}
 		if(buddy)
-			pidgin_retrieve_user_info(purple_account_get_connection(buddy->account), buddy->name);
+			pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy));
 	} else {
 		switch (event->keyval) {
 			case GDK_F2:
@@ -1761,7 +1763,7 @@
 	pidgin_new_item_from_stock(menu, _("View _Log"), NULL,
 			G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL);
 
-	pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(c->account), node);
+	pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(purple_chat_get_account(c)), node);
 	pidgin_append_blist_node_extended_menu(menu, node);
 
 	pidgin_separator(menu);
@@ -1811,7 +1813,7 @@
 static GtkWidget *
 create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b)
 {
-	struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkWidget *menu;
 	GtkWidget *menuitem;
 	gboolean show_offline = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies");
@@ -1846,13 +1848,13 @@
 
 				if(buddy == b)
 					continue;
-				if(!purple_account_get_connection(buddy->account))
+				if(!purple_account_get_connection(purple_buddy_get_account(buddy)))
 					continue;
 				if(!show_offline && !PURPLE_BUDDY_IS_ONLINE(buddy))
 					continue;
 
-				menuitem = gtk_image_menu_item_new_with_label(buddy->name);
-				buf = pidgin_create_prpl_icon(buddy->account,PIDGIN_PRPL_ICON_SMALL);
+				menuitem = gtk_image_menu_item_new_with_label(purple_buddy_get_name(buddy));
+				buf = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL);
 				image = gtk_image_new_from_pixbuf(buf);
 				g_object_unref(G_OBJECT(buf));
 				gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
@@ -1879,12 +1881,10 @@
 								 guint button,
 								 guint32 time)
 {
-	struct _pidgin_blist_node *gtknode;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkWidget *menu = NULL;
 	gboolean handled = FALSE;
 
-	gtknode = (struct _pidgin_blist_node *)node->ui_data;
-
 	/* Create a menu based on the thing we right-clicked on */
 	if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
 		PurpleGroup *g = (PurpleGroup *)node;
@@ -1946,7 +1946,7 @@
 		return FALSE;
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
 	gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1);
-	gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	gtknode = purple_blist_node_get_ui_data(node);
 
 	/* Right click draws a context menu */
 	if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) {
@@ -1970,12 +1970,12 @@
 		else
 			b = (PurpleBuddy *)node;
 
-		prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
+		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
 		if (prpl != NULL)
 			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 		if (prpl && prpl_info->get_info)
-			pidgin_retrieve_user_info(purple_account_get_connection(b->account), b->name);
+			pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(b)), purple_buddy_get_name(b));
 		handled = TRUE;
 	}
 
@@ -2125,7 +2125,7 @@
 		for (l = list; l != NULL; l = l->next)
 		{
 			purple_blist_request_add_buddy(account, l->data,
-										 (group ? group->name : NULL),
+										 (group ? purple_group_get_name(group) : NULL),
 										 alias);
 		}
 	}
@@ -2306,7 +2306,7 @@
 			buddy = (PurpleBuddy *)node;
 		}
 
-		gc = purple_account_get_connection(buddy->account);
+		gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
 		if (gc == NULL)
 		{
@@ -2315,7 +2315,7 @@
 		}
 
 		protocol =
-			PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(buddy->account,
+			PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->list_icon(purple_buddy_get_account(buddy),
 														   buddy);
 
 		str = g_string_new(NULL);
@@ -2325,13 +2325,13 @@
 			"X-IM-Protocol: %s\r\n"
 			"X-IM-Username: %s\r\n",
 			protocol,
-			buddy->name);
-
-		if (buddy->alias != NULL)
+			purple_buddy_get_name(buddy));
+
+		if (purple_buddy_get_local_buddy_alias(buddy) != NULL)
 		{
 			g_string_append_printf(str,
 				"X-IM-Alias: %s\r\n",
-				buddy->alias);
+				purple_buddy_get_local_buddy_alias(buddy));
 		}
 
 		g_string_append(str, "\r\n");
@@ -2370,7 +2370,7 @@
 					&iter, path);
 			gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel),
 					&iter, NODE_COLUMN, &node, -1);
-			gtknode = node->ui_data;
+			gtknode = purple_blist_node_get_ui_data(node);
 
 			if (PURPLE_BLIST_NODE_IS_CONTACT(n)) {
 				PurpleContact *c = (PurpleContact*)n;
@@ -2547,7 +2547,7 @@
 			else
 			{
 				purple_blist_request_add_buddy(account, username,
-											 (group ? group->name : NULL),
+											 (group ? purple_group_get_name(group) : NULL),
 											 alias);
 			}
 		}
@@ -2614,7 +2614,7 @@
 
 				if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 					PurpleBuddy *b = PURPLE_BLIST_NODE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node));
-					pidgin_dnd_file_manage(sd, b->account, b->name);
+					pidgin_dnd_file_manage(sd, purple_buddy_get_account(b), purple_buddy_get_name(b));
 					gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 				} else {
 					gtk_drag_finish(dc, FALSE, FALSE, t);
@@ -2688,7 +2688,7 @@
 	}
 
 	if(account && purple_account_get_connection(account)) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_account_get_connection(account)->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
 	}
 
 #if 0
@@ -2701,7 +2701,7 @@
 	 * a contact then this is a group or some other type of node and we
 	 * want to use that directly. */
 	if (contact) {
-		custom_img = purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact);
+		custom_img = purple_buddy_icons_node_find_custom_icon(PURPLE_BLIST_NODE(contact));
 	} else {
 		custom_img = purple_buddy_icons_node_find_custom_icon(node);
 	}
@@ -2714,7 +2714,7 @@
 	if (data == NULL) {
 		if (buddy) {
 			/* Not sure I like this...*/
-			if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name)))
+			if (!(icon = purple_buddy_icons_find(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))))
 				return NULL;
 			data = purple_buddy_icon_get_data(icon, &len);
 		}
@@ -2884,9 +2884,9 @@
 	char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL;
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		account = ((PurpleBuddy*)(node))->account;
+		account = purple_buddy_get_account((PurpleBuddy*)(node));
 	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
-		account = ((PurpleChat*)(node))->account;
+		account = purple_chat_get_account((PurpleChat*)(node));
 	}
 
 	td->padding = TOOLTIP_BORDER;
@@ -3197,7 +3197,7 @@
 		return FALSE;
 	}
 
-	gtknode = node->ui_data;
+	gtknode = purple_blist_node_get_ui_data(node);
 
 	if (!gtknode->contact_expanded) {
 		GtkTreeIter i;
@@ -3226,13 +3226,13 @@
 	if(!buddy)
 		return FALSE;
 
-	gtknode = ((PurpleBlistNode*)buddy)->ui_data;
-
-	return (purple_account_is_connected(buddy->account) &&
-			(purple_presence_is_online(buddy->presence) ||
+	gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
+
+	return (purple_account_is_connected(purple_buddy_get_account(buddy)) &&
+			(purple_presence_is_online(purple_buddy_get_presence(buddy)) ||
 			 (gtknode && gtknode->recent_signonoff) ||
 			 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies") ||
-			 purple_blist_node_get_bool((PurpleBlistNode*)buddy, "show_offline")));
+			 purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy), "show_offline")));
 }
 
 void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget)
@@ -3407,7 +3407,7 @@
 			const char *text;
 			PurpleAccount *account = purple_connection_get_account(gc);
 
-			if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) {
+			if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) {
 				PurpleRequestField *text_field;
 				text_field = purple_request_fields_get_field(fields, "text");
 				text = purple_request_field_string_get_value(text_field);
@@ -3423,7 +3423,7 @@
 				PurpleAccount *account = (PurpleAccount *) accounts->data;
 				PurpleConnection *gc = purple_account_get_connection(account);
 
-				if (gc && gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) {
+				if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) {
 					update_status_with_mood(account, mood, NULL);
 				}
 			}
@@ -3458,9 +3458,9 @@
 		if (purple_account_is_connected(account)) {
 			PurpleConnection *gc = purple_account_get_connection(account);
 
-			if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) {
+			if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS) {
 				PurplePluginProtocolInfo *prpl_info =
-					PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+					PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 				PurpleMood *mood = NULL;
 
 				/* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't
@@ -3518,7 +3518,7 @@
 		PurpleAccount *account = (PurpleAccount *) accounts->data;
 
 		if (purple_account_is_connected(account) &&
-		    (purple_account_get_connection(account)->flags &
+		    (purple_connection_get_flags(purple_account_get_connection(account)) &
 		     PURPLE_CONNECTION_SUPPORT_MOODS)) {
 			PurplePresence *presence = purple_account_get_presence(account);
 			PurpleStatus *status = purple_presence_get_status(presence, "mood");
@@ -3553,8 +3553,8 @@
 		PurplePresence *presence = purple_account_get_presence(account);
 		PurpleStatus *status = purple_presence_get_status(presence, "mood");
 		gc = purple_account_get_connection(account);
-		g_return_if_fail(gc->prpl != NULL);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 		current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
 	} else {
 		current_mood = get_global_mood_status();
@@ -3593,7 +3593,7 @@
 	purple_request_fields_add_group(fields, g);
 
 	/* if the connection allows setting a mood message */
-	if (gc && (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) {
+	if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) {
 		g = purple_request_field_group_new(NULL);
 		f = purple_request_field_string_new("text",
 		    _("Message (optional)"), NULL, FALSE);
@@ -3758,16 +3758,16 @@
 		struct proto_chat_entry *pce;
 		char *name, *value;
 		PurpleConversation *conv;
-		PidginBlistNode *bnode = node->ui_data;
+		PidginBlistNode *bnode = purple_blist_node_get_ui_data(node);
 
 		chat = (PurpleChat *)node;
-		prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
+		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_chat_get_account(chat)));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 		connections = purple_connections_get_all();
 		if (connections && connections->next)
 		{
-			tmp = g_markup_escape_text(purple_account_get_username(chat->account), -1);
+			tmp = g_markup_escape_text(purple_account_get_username(purple_chat_get_account(chat)), -1);
 			g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
 			g_free(tmp);
 		}
@@ -3777,12 +3777,12 @@
 		} else {
 			char *chat_name;
 			if (prpl_info && prpl_info->get_chat_name)
-				chat_name = prpl_info->get_chat_name(chat->components);
+				chat_name = prpl_info->get_chat_name(purple_chat_get_components(chat));
 			else
 				chat_name = g_strdup(purple_chat_get_name(chat));
 
 			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chat_name,
-					chat->account);
+					purple_chat_get_account(chat));
 			g_free(chat_name);
 		}
 
@@ -3799,7 +3799,7 @@
 		}
 
 		if (prpl_info && prpl_info->chat_info != NULL)
-			cur = prpl_info->chat_info(purple_account_get_connection(chat->account));
+			cur = prpl_info->chat_info(purple_account_get_connection(purple_chat_get_account(chat)));
 		else
 			cur = NULL;
 
@@ -3808,13 +3808,13 @@
 			pce = cur->data;
 
 			if (!pce->secret && (!pce->required &&
-				g_hash_table_lookup(chat->components, pce->identifier) == NULL))
+				g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier) == NULL))
 			{
 				tmp = purple_text_strip_mnemonic(pce->label);
 				name = g_markup_escape_text(tmp, -1);
 				g_free(tmp);
 				value = g_markup_escape_text(g_hash_table_lookup(
-										chat->components, pce->identifier), -1);
+										purple_chat_get_components(chat), pce->identifier), -1);
 				g_string_append_printf(str, "\n<b>%s</b> %s",
 							name ? name : "",
 							value ? value : "");
@@ -3850,7 +3850,7 @@
 			c = purple_buddy_get_contact(b);
 		}
 
-		prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
+		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 		presence = purple_buddy_get_presence(b);
@@ -3867,12 +3867,12 @@
 		/* Alias */
 		/* If there's not a contact alias, the node is being displayed with
 		 * this alias, so there's no point in showing it in the tooltip. */
-		if (full && c && b->alias != NULL && b->alias[0] != '\0' &&
+		if (full && c && purple_buddy_get_local_buddy_alias(b) != NULL && purple_buddy_get_local_buddy_alias(b)[0] != '\0' &&
 		    (c->alias != NULL && c->alias[0] != '\0') &&
-		    strcmp(c->alias, b->alias) != 0)
+		    strcmp(c->alias, purple_buddy_get_local_buddy_alias(b)) != 0)
 		{
 			purple_notify_user_info_add_pair_plaintext(user_info,
-					_("Buddy Alias"), b->alias);
+					_("Buddy Alias"), purple_buddy_get_local_buddy_alias(b));
 		}
 
 		/* Nickname/Server Alias */
@@ -3880,10 +3880,10 @@
 		 * alias, but many people on MSN set long nicknames, which
 		 * get ellipsized, so the only way to see the whole thing is
 		 * to look at the tooltip. */
-		if (full && b->server_alias != NULL && b->server_alias[0] != '\0')
+		if (full && purple_buddy_get_server_alias(b))
 		{
 			purple_notify_user_info_add_pair_plaintext(user_info,
-					_("Nickname"), b->server_alias);
+					_("Nickname"), purple_buddy_get_server_alias(b));
 		}
 
 		/* Logged In */
@@ -3918,7 +3918,7 @@
 		/* Last Seen */
 		if (full && c && !PURPLE_BUDDY_IS_ONLINE(b))
 		{
-			struct _pidgin_blist_node *gtknode = ((PurpleBlistNode *)c)->ui_data;
+			struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(c));
 			PurpleBlistNode *bnode;
 			int lastseen = 0;
 
@@ -3958,7 +3958,7 @@
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Offline"));
 		}
 
-		if (purple_account_is_connected(b->account) &&
+		if (purple_account_is_connected(purple_buddy_get_account(b)) &&
 				prpl_info && prpl_info->tooltip_text)
 		{
 			/* Additional text from the PRPL */
@@ -3966,11 +3966,11 @@
 		}
 
 		/* These are Easter Eggs.  Patches to remove them will be rejected. */
-		if (!g_ascii_strcasecmp(b->name, "robflynn"))
+		if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "robflynn"))
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Description"), _("Spooky"));
-		if (!g_ascii_strcasecmp(b->name, "seanegn"))
+		if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "seanegn"))
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Awesome"));
-		if (!g_ascii_strcasecmp(b->name, "chipx86"))
+		if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "chipx86"))
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Rockin'"));
 
 		tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n");
@@ -4047,7 +4047,7 @@
 pidgin_blist_get_emblem(PurpleBlistNode *node)
 {
 	PurpleBuddy *buddy = NULL;
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	PurplePlugin *prpl;
 	PurplePluginProtocolInfo *prpl_info;
 	const char *name = NULL;
@@ -4070,10 +4070,10 @@
 			return _pidgin_blist_get_cached_emblem(path);
 		}
 
-		if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) {
+		if (((struct _pidgin_blist_node*)purple_blist_node_get_ui_data(node->parent))->contact_expanded) {
 			if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"))
 				return NULL;
-			return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
+			return pidgin_create_prpl_icon(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PRPL_ICON_SMALL);
 		}
 	} else {
 		return NULL;
@@ -4081,7 +4081,7 @@
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 
-	if (!purple_privacy_check(buddy->account, purple_buddy_get_name(buddy))) {
+	if (!purple_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) {
 		path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL);
 		return _pidgin_blist_get_cached_emblem(path);
 	}
@@ -4117,7 +4117,7 @@
 		return _pidgin_blist_get_cached_emblem(path);
 	}
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account));
+	prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(buddy)));
 	if (!prpl)
 		return NULL;
 
@@ -4154,7 +4154,7 @@
 {
 	GdkPixbuf *ret;
 	const char *icon = NULL;
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	struct _pidgin_blist_node *gtkbuddynode = NULL;
 	PurpleBuddy *buddy = NULL;
 	PurpleChat *chat = NULL;
@@ -4165,11 +4165,11 @@
 		if(!gtknode->contact_expanded) {
 			buddy = purple_contact_get_priority_buddy((PurpleContact*)node);
 			if (buddy != NULL)
-				gtkbuddynode = ((PurpleBlistNode*)buddy)->ui_data;
+				gtkbuddynode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 		}
 	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		buddy = (PurpleBuddy*)node;
-		gtkbuddynode = node->ui_data;
+		gtkbuddynode = purple_blist_node_get_ui_data(node);
 	} else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
 		chat = (PurpleChat*)node;
 	} else {
@@ -4181,9 +4181,9 @@
 		PurplePlugin *prpl;
 
 		if(buddy)
-			account = buddy->account;
+			account = purple_buddy_get_account(buddy);
 		else
-			account = chat->account;
+			account = purple_chat_get_account(chat);
 
 		prpl = purple_find_prpl(purple_account_get_protocol_id(account));
 		if(!prpl)
@@ -4198,7 +4198,7 @@
 		if(conv != NULL) {
 			PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
 			if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) {
-				PidginBlistNode *ui = buddy->node.ui_data;
+				PidginBlistNode *ui = purple_blist_node_get_ui_data(&(buddy->node));
 				if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE))
 					return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview),
 							PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView");
@@ -4282,7 +4282,7 @@
 	PidginBlistTheme *theme;
 
 	if (conv != NULL) {
-		PidginBlistNode *ui = b->node.ui_data;
+		PidginBlistNode *ui = purple_blist_node_get_ui_data(&(b->node));
 		if (ui) {
 			if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)
 				hidden_conv = TRUE;
@@ -4316,12 +4316,12 @@
 	if (!aliased || biglist) {
 
 		/* Status Info */
-		prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
+		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
 
 		if (prpl != NULL)
 			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-		if (prpl_info && prpl_info->status_text && purple_account_get_connection(b->account)) {
+		if (prpl_info && prpl_info->status_text && purple_account_get_connection(purple_buddy_get_account(b))) {
 			char *tmp = prpl_info->status_text(b);
 			const char *end;
 
@@ -4516,7 +4516,7 @@
 
 				if (buddy &&
 						purple_presence_is_idle(purple_buddy_get_presence(buddy)))
-					pidgin_blist_update_contact(list, (PurpleBlistNode*)buddy);
+					pidgin_blist_update_contact(list, PURPLE_BLIST_NODE(buddy));
 			}
 		}
 	}
@@ -4527,7 +4527,7 @@
 
 static void pidgin_blist_hide_node(PurpleBuddyList *list, PurpleBlistNode *node, gboolean update)
 {
-	struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkTreeIter iter;
 
 	if (!gtknode || !gtknode->row || !gtkblist)
@@ -4696,7 +4696,7 @@
 	if(account != NULL && purple_conversation_get_name(conv) != NULL) {
 		PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
 		if(buddy != NULL)
-			pidgin_blist_update_buddy(NULL, (PurpleBlistNode *)buddy, TRUE);
+			pidgin_blist_update_buddy(NULL, PURPLE_BLIST_NODE(buddy), TRUE);
 	}
 
 	if (gtkblist->menutrayicon) {
@@ -4776,7 +4776,7 @@
 written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message,
 		PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node)
 {
-	PidginBlistNode *ui = node->ui_data;
+	PidginBlistNode *ui = purple_blist_node_get_ui_data(node);
 	if (ui->conv.conv != conv || !pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) ||
 			!(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)))
 		return;
@@ -4792,7 +4792,7 @@
 static void
 displayed_msg_update_ui_cb(PidginConversation *gtkconv, PurpleBlistNode *node)
 {
-	PidginBlistNode *ui = node->ui_data;
+	PidginBlistNode *ui = purple_blist_node_get_ui_data(node);
 	if (ui->conv.conv != gtkconv->active_conv)
 		return;
 	ui->conv.flags &= ~(PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE |
@@ -4811,7 +4811,7 @@
 				GSList *buddies = purple_find_buddies(account, purple_conversation_get_name(conv));
 				while (buddies) {
 					PurpleBlistNode *buddy = buddies->data;
-					struct _pidgin_blist_node *ui = buddy->ui_data;
+					struct _pidgin_blist_node *ui = purple_blist_node_get_ui_data(buddy);
 					buddies = g_slist_delete_link(buddies, buddies);
 					if (!ui)
 						continue;
@@ -4833,7 +4833,7 @@
 				struct _pidgin_blist_node *ui;
 				if (!chat)
 					break;
-				ui = chat->node.ui_data;
+				ui = purple_blist_node_get_ui_data(&(chat->node));
 				if (!ui)
 					break;
 				ui->conv.conv = conv;
@@ -4868,7 +4868,7 @@
 
 static void pidgin_blist_new_node(PurpleBlistNode *node)
 {
-	node->ui_data = g_new0(struct _pidgin_blist_node, 1);
+	purple_blist_node_set_ui_data(node, g_new0(struct _pidgin_blist_node, 1));
 }
 
 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node)
@@ -4881,7 +4881,7 @@
 
 	g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE);
 
-	return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded;
+	return ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node))->contact_expanded;
 }
 
 enum {
@@ -4931,7 +4931,7 @@
 		struct _pidgin_blist_node *gtknode;
 		GtkTreePath *path;
 
-		gtknode = node->ui_data;
+		gtknode = purple_blist_node_get_ui_data(node);
 		if (gtknode && gtknode->row)
 		{
 			path = gtk_tree_row_reference_get_path(gtknode->row);
@@ -6253,7 +6253,7 @@
 }
 
 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter) {
-	struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkTreePath *path;
 
 	if (!gtknode) {
@@ -6282,7 +6282,7 @@
 
 static void pidgin_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node)
 {
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 
 	purple_request_close_with_handle(node);
 
@@ -6304,9 +6304,9 @@
 		if(gtknode->recent_signonoff_timer > 0)
 			purple_timeout_remove(gtknode->recent_signonoff_timer);
 
-		purple_signals_disconnect_by_handle(node->ui_data);
-		g_free(node->ui_data);
-		node->ui_data = NULL;
+		purple_signals_disconnect_by_handle(gtknode);
+		g_free(gtknode);
+		purple_blist_node_set_ui_data(node, NULL);
 	}
 }
 
@@ -6350,8 +6350,8 @@
 
 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter)
 {
-	GtkTreeIter parent_iter, cur, *curptr = NULL;
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	GtkTreeIter parent_iter = {0, NULL, NULL, NULL}, cur, *curptr = NULL;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkTreePath *newpath;
 
 	if(!iter)
@@ -6373,7 +6373,7 @@
 		gtk_tree_row_reference_free(gtknode->row);
 	} else {
 		pidgin_blist_new_node(node);
-		gtknode = (struct _pidgin_blist_node *)node->ui_data;
+		gtknode = purple_blist_node_get_ui_data(node);
 	}
 
 	newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel),
@@ -6391,7 +6391,7 @@
 
 	if(node->parent) {
 		GtkTreePath *expand = NULL;
-		struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data;
+		struct _pidgin_blist_node *gtkparentnode = purple_blist_node_get_ui_data(node->parent);
 
 		if(PURPLE_BLIST_NODE_IS_GROUP(node->parent)) {
 			if(!purple_blist_node_get_bool(node->parent, "collapsed"))
@@ -6413,12 +6413,12 @@
 {
 	PurpleBlistNode *gnode, *cnode, *bnode;
 
-	gnode = (PurpleBlistNode *)group;
+	gnode = PURPLE_BLIST_NODE(group);
 	for(cnode = gnode->child; cnode; cnode = cnode->next) {
 		if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) {
 			for(bnode = cnode->child; bnode; bnode = bnode->next) {
 				PurpleBuddy *buddy = (PurpleBuddy *)bnode;
-				if (purple_account_is_connected(buddy->account) &&
+				if (purple_account_is_connected(purple_buddy_get_account(buddy)) &&
 					purple_blist_node_get_bool(bnode, "show_offline"))
 					return TRUE;
 			}
@@ -6558,7 +6558,7 @@
 	text_color = selected ? NULL : theme_font_get_color_default(pair, NULL);
 	text_font = theme_font_get_face_default(pair, "");
 
-	esc = g_markup_escape_text(group->name, -1);
+	esc = g_markup_escape_text(purple_group_get_name(group), -1);
 	if (text_color) {
 		mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s%s%s</span>",
 		                       text_color, text_font,
@@ -6585,7 +6585,7 @@
 	GdkColor *color = NULL;
 	char *mark;
 	char *idle = NULL;
-	gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded;
+	gboolean expanded = ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node->parent))->contact_expanded;
 	gboolean selected = (gtkblist->selected_node == node);
 	gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
 	PidginBlistTheme *theme;
@@ -6593,12 +6593,12 @@
 	if (editing_blist)
 		return;
 
-	status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy,
+	status = pidgin_blist_get_status_icon(PURPLE_BLIST_NODE(buddy),
 						biglist ? PIDGIN_STATUS_ICON_LARGE : PIDGIN_STATUS_ICON_SMALL);
 
 	/* Speed it up if we don't want buddy icons. */
 	if(biglist)
-		avatar = pidgin_blist_get_buddy_icon((PurpleBlistNode *)buddy, TRUE, TRUE);
+		avatar = pidgin_blist_get_buddy_icon(PURPLE_BLIST_NODE(buddy), TRUE, TRUE);
 	else
 		avatar = NULL;
 
@@ -6609,7 +6609,7 @@
 		do_alphashift(avatar, 77);
 	}
 
-	emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy);
+	emblem = pidgin_blist_get_emblem(PURPLE_BLIST_NODE(buddy));
 	mark = pidgin_blist_get_name_markup(buddy, selected, TRUE);
 
 	theme = pidgin_blist_get_theme();
@@ -6650,7 +6650,7 @@
 		}
 	}
 
-	prpl_icon = pidgin_create_prpl_icon(buddy->account, PIDGIN_PRPL_ICON_SMALL);
+	prpl_icon = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL);
 
 	if (theme != NULL)
 		color = pidgin_blist_theme_get_contact_color(theme);
@@ -6721,7 +6721,7 @@
 		if(!insert_node(list, cnode, &iter))
 			return;
 
-		gtknode = (struct _pidgin_blist_node *)cnode->ui_data;
+		gtknode = purple_blist_node_get_ui_data(cnode);
 
 		if(gtknode->contact_expanded) {
 			GdkPixbuf *status;
@@ -6798,7 +6798,7 @@
 	/* First things first, update the contact */
 	pidgin_blist_update_contact(list, node);
 
-	gtkparentnode = (struct _pidgin_blist_node *)node->parent->ui_data;
+	gtkparentnode = purple_blist_node_get_ui_data(node->parent);
 
 	if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy))
 	{
@@ -6829,7 +6829,7 @@
 
 	chat = (PurpleChat*)node;
 
-	if(purple_account_is_connected(chat->account)) {
+	if(purple_account_is_connected(purple_chat_get_account(chat))) {
 		GtkTreeIter iter;
 		GdkPixbuf *status, *avatar, *emblem, *prpl_icon;
 		const gchar *color, *font;
@@ -6848,7 +6848,7 @@
 		if (!insert_node(list, node, &iter))
 			return;
 
-		ui = node->ui_data;
+		ui = purple_blist_node_get_ui_data(node);
 		conv = ui->conv.conv;
 		if (conv && pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv))) {
 			hidden = (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE);
@@ -6893,7 +6893,7 @@
 		g_free(mark);
 		mark = tmp;
 
-		prpl_icon = pidgin_create_prpl_icon(chat->account, PIDGIN_PRPL_ICON_SMALL);
+		prpl_icon = pidgin_create_prpl_icon(purple_chat_get_account(chat), PIDGIN_PRPL_ICON_SMALL);
 
 		if (theme != NULL)
 			bgcolor = pidgin_blist_theme_get_contact_color(theme);
@@ -6934,10 +6934,10 @@
 	if(!gtkblist || !gtkblist->treeview || !node)
 		return;
 
-	if (node->ui_data == NULL)
+	if (purple_blist_node_get_ui_data(node) == NULL)
 		pidgin_blist_new_node(node);
 
-	switch(node->type) {
+	switch (purple_blist_node_get_type(node)) {
 		case PURPLE_BLIST_GROUP_NODE:
 			pidgin_blist_update_group(list, node);
 			break;
@@ -7031,7 +7031,6 @@
 groups_tree(void)
 {
 	static GList *list = NULL;
-	char *tmp2;
 	PurpleGroup *g;
 	PurpleBlistNode *gnode;
 
@@ -7051,8 +7050,7 @@
 			if (PURPLE_BLIST_NODE_IS_GROUP(gnode))
 			{
 				g    = (PurpleGroup *)gnode;
-				tmp2 = g->name;
-				list  = g_list_append(list, tmp2);
+				list  = g_list_append(list, (char *) purple_group_get_name(g));
 			}
 		}
 	}
@@ -7139,7 +7137,7 @@
 
 		/* Offer to merge people with the same alias. */
 		if (whoalias != NULL && g != NULL)
-			gtk_blist_auto_personize((PurpleBlistNode *)g, whoalias);
+			gtk_blist_auto_personize(PURPLE_BLIST_NODE(g), whoalias);
 
 		/*
 		 * XXX
@@ -7287,10 +7285,10 @@
 		purple_blist_add_chat(chat, group, NULL);
 
 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin)))
-			purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", TRUE);
+			purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin", TRUE);
 
 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent)))
-			purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", TRUE);
+			purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent", TRUE);
 	}
 
 	gtk_widget_destroy(data->chat_data.rq_data.window);
@@ -7327,11 +7325,13 @@
 	GList *l;
 	PurpleConnection *gc;
 	GtkBox *vbox;
+	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	if (account != NULL) {
 		gc = purple_account_get_connection(account);
-
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat == NULL) {
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+
+		if (prpl_info->join_chat == NULL) {
 			purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL);
 			return;
 		}
@@ -7339,8 +7339,9 @@
 		/* Find an account with chat capabilities */
 		for (l = purple_connections_get_all(); l != NULL; l = l->next) {
 			gc = (PurpleConnection *)l->data;
-
-			if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat != NULL) {
+			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+
+			if (prpl_info->join_chat != NULL) {
 				account = purple_connection_get_account(gc);
 				break;
 			}
@@ -7384,7 +7385,7 @@
 	if (name != NULL)
 		gtk_widget_grab_focus(data->alias_entry);
 
-	data->group_combo = pidgin_text_combo_box_entry_new(group ? group->name : NULL, groups_tree());
+	data->group_combo = pidgin_text_combo_box_entry_new(group ? purple_group_get_name(group) : NULL, groups_tree());
 	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"),
 	                          data->chat_data.rq_data.sg, data->group_combo,
 	                          TRUE, NULL);
@@ -7541,11 +7542,11 @@
 
 			chat = (PurpleChat *)cnode;
 
-			if(chat->account != account)
+			if(purple_chat_get_account(chat) != account)
 				continue;
 
-			if (purple_blist_node_get_bool((PurpleBlistNode*)chat, "gtk-autojoin"))
-				serv_join_chat(gc, chat->components);
+			if (purple_blist_node_get_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin"))
+				serv_join_chat(gc, purple_chat_get_components(chat));
 		}
 	}
 
@@ -7562,25 +7563,25 @@
 
 static gboolean buddy_signonoff_timeout_cb(PurpleBuddy *buddy)
 {
-	struct _pidgin_blist_node *gtknode = ((PurpleBlistNode*)buddy)->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 
 	gtknode->recent_signonoff = FALSE;
 	gtknode->recent_signonoff_timer = 0;
 
-	pidgin_blist_update(NULL, (PurpleBlistNode*)buddy);
+	pidgin_blist_update(NULL, PURPLE_BLIST_NODE(buddy));
 
 	return FALSE;
 }
 
 static void buddy_signonoff_cb(PurpleBuddy *buddy)
 {
-	struct _pidgin_blist_node *gtknode;
-
-	if(!((PurpleBlistNode*)buddy)->ui_data) {
-		pidgin_blist_new_node((PurpleBlistNode*)buddy);
-	}
-
-	gtknode = ((PurpleBlistNode*)buddy)->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
+
+	if(!gtknode) {
+		pidgin_blist_new_node(PURPLE_BLIST_NODE(buddy));
+	}
+
+	gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 
 	gtknode->recent_signonoff = TRUE;
 
@@ -7947,7 +7948,7 @@
 		PurpleBuddy *buddy;
 		for (n = node->child; n; n = n->next) {
 			buddy = (PurpleBuddy*)n;
-			activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, buddy->name, buddy->account);
+			activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
 		}
 		buddy_name = purple_contact_get_alias((PurpleContact*)node);
 	} else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
@@ -7983,7 +7984,7 @@
 		if(PURPLE_BLIST_NODE_IS_CONTACT(n)) {
 			for (n2 = n->child; n2; n2 = n2->next) {
                         	buddy = (PurpleBuddy*)n2;
-				this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, buddy->name, buddy->account);
+				this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
 			}
 			this_buddy_name = purple_contact_get_alias((PurpleContact*)n);
 		} else {
@@ -8159,7 +8160,7 @@
 			g_string_append(accounts_ui, "<separator/>");
 
 			gc = purple_account_get_connection(account);
-			plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
+			plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? purple_connection_get_prpl(gc) : NULL;
 			if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
 				build_plugin_actions(accounts_action_group, accounts_ui, base, plugin, gc);
 			} else {
--- a/pidgin/gtkcertmgr.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkcertmgr.c	Fri Dec 23 06:58:52 2011 +0000
@@ -40,6 +40,12 @@
 
 #include "gtkcertmgr.h"
 
+#ifdef ENABLE_GCR
+#define GCR_API_SUBJECT_TO_CHANGE
+#include <gcr/gcr.h>
+#include <gcr/gcr-simple-certificate.h>
+#endif
+
 /*****************************************************************************
  * X.509 tls_peers management interface                                      *
  *****************************************************************************/
@@ -310,6 +316,13 @@
 	GtkTreeModel *model;
 	gchar *id;
 	PurpleCertificate *crt;
+#ifdef ENABLE_GCR
+	GByteArray *der;
+	GcrCertificate *gcrt;
+	char *title;
+	GtkWidget *dialog;
+	GcrCertificateBasicsWidget *cert_widget;
+#endif
 
 	/* See if things are selected */
 	if (!gtk_tree_selection_get_selected(select, &model, &iter)) {
@@ -325,11 +338,38 @@
 	crt = purple_certificate_pool_retrieve(tpm_dat->tls_peers, id);
 	g_return_if_fail(crt);
 
+#ifdef ENABLE_GCR
+	der = purple_certificate_get_der_data(crt);
+	g_return_if_fail(der);
+
+	gcrt = gcr_simple_certificate_new(der->data, der->len);
+	g_return_if_fail(gcrt);
+
+	/* Fire the notification */
+	title = g_strdup_printf(_("Certificate Information for %s"), id);
+	dialog = gtk_dialog_new_with_buttons(title,
+	                                     NULL,
+	                                     0,
+	                                     GTK_STOCK_OK,
+	                                     GTK_RESPONSE_ACCEPT,
+	                                     NULL);
+	cert_widget = gcr_certificate_basics_widget_new(gcrt);
+	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
+	                   GTK_WIDGET(cert_widget), TRUE, TRUE, 0);
+	g_signal_connect_swapped(dialog, "response",
+	                         G_CALLBACK(gtk_widget_destroy),
+	                         dialog);
+	gtk_widget_show_all(dialog);
+
+	g_byte_array_free(der, TRUE);
+	g_object_unref(G_OBJECT(gcrt));
+#else
 	/* Fire the notification */
 	purple_certificate_display_x509(crt);
 
 	g_free(id);
 	purple_certificate_destroy(crt);
+#endif
 }
 
 static void
--- a/pidgin/gtkconv-theme.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkconv-theme.c	Fri Dec 23 06:58:52 2011 +0000
@@ -111,6 +111,23 @@
 	return val;
 }
 
+/* The template path can either come from the theme, or can
+ * be stock Template.html that comes with Pidgin */
+static char *
+get_template_path(const char *dir)
+{
+	char *file;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Template.html", NULL);
+
+	if (!g_file_test(file, G_FILE_TEST_EXISTS)) {
+		g_free(file);
+		file = g_build_filename(DATADIR, "pidgin", "theme", "conversation", "Template.html", NULL);
+	}
+
+	return file;
+}
+
 static const char *
 get_template_html(PidginConvThemePrivate *priv, const char *dir)
 {
@@ -119,14 +136,7 @@
 	if (priv->template_html)
 		return priv->template_html;
 
-	/* The template path can either come from the theme, or can
-	 * be stock Template.html that comes with the plugin */
-	file = g_build_filename(dir, "Contents", "Resources", "Template.html", NULL);
-
-	if (!g_file_test(file, G_FILE_TEST_EXISTS)) {
-		g_free(file);
-		file = g_build_filename(DATADIR, "pidgin", "webkit", "Template.html", NULL);
-	}
+	file = get_template_path(dir);
 
 	if (!g_file_get_contents(file, &priv->template_html, NULL, NULL)) {
 		purple_debug_error("webkit", "Could not locate a Template.html (%s)\n", file);
@@ -371,6 +381,7 @@
 	if (!g_file_get_contents(file, &priv->outgoing_next_context_html, NULL, NULL)) {
 		priv->outgoing_next_context_html = g_strdup(get_outgoing_context_html(priv, dir));
 	}
+	g_free(file);
 
 	return priv->outgoing_next_context_html;
 }
@@ -708,19 +719,12 @@
 pidgin_conversation_theme_get_template_path(PidginConvTheme *theme)
 {
 	const char *dir;
-	char *filename;
 
 	g_return_val_if_fail(theme != NULL, NULL);
 
 	dir = purple_theme_get_dir(PURPLE_THEME(theme));
-	filename = g_build_filename(dir, "Contents", "Resources", "Template.html", NULL);
 
-	if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
-		g_free(filename);
-		filename = g_build_filename(DATADIR, "pidgin", "webkit", "Template.html", NULL);
-	}
-
-	return filename;
+	return get_template_path(dir);
 }
 
 char *
--- a/pidgin/gtkconv.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkconv.c	Fri Dec 23 06:58:52 2011 +0000
@@ -571,8 +571,8 @@
 					PurplePluginProtocolInfo *prpl_info = NULL;
 					PurpleConnection *gc;
 
-					if ((gc = purple_conversation_get_gc(conv)))
-						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+					if ((gc = purple_conversation_get_connection(conv)))
+						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 					if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
 						char *spaceslash;
@@ -730,7 +730,7 @@
 	PurpleConversation *conv = gtkconv->active_conv;
 	PurpleConnection *gc;
 
-	if ((gc = purple_conversation_get_gc(conv))) {
+	if ((gc = purple_conversation_get_connection(conv))) {
 		pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)));
 	}
 }
@@ -742,7 +742,7 @@
 	PurpleConversation *conv = gtkconv->active_conv;
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		pidgin_retrieve_user_info(purple_conversation_get_gc(conv),
+		pidgin_retrieve_user_info(purple_conversation_get_connection(conv),
 					  purple_conversation_get_name(conv));
 		gtk_widget_grab_focus(gtkconv->entry);
 	} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
@@ -830,7 +830,7 @@
 		if (!g_ascii_strcasecmp(buddy, ""))
 			return;
 
-		serv_chat_invite(purple_conversation_get_gc(conv),
+		serv_chat_invite(purple_conversation_get_connection(conv),
 						 purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
 						 message, buddy);
 	}
@@ -865,7 +865,7 @@
 		else
 			return;
 
-		if (strcmp(convprotocol, purple_account_get_protocol_id(buddy->account)))
+		if (strcmp(convprotocol, purple_account_get_protocol_id(purple_buddy_get_account(buddy))))
 		{
 			purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL,
 							  _("That buddy is not on the same protocol as this "
@@ -1225,7 +1225,7 @@
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		serv_send_file(purple_conversation_get_gc(conv), purple_conversation_get_name(conv), NULL);
+		serv_send_file(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), NULL);
 	}
 
 }
@@ -1237,8 +1237,13 @@
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		purple_prpl_send_attention(purple_conversation_get_gc(conv),
-			purple_conversation_get_name(conv), 0);
+		int index;
+		if (widget == win->menu.get_attention)
+			index = 0;
+		else
+			index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "index"));
+		purple_prpl_send_attention(purple_conversation_get_connection(conv),
+			purple_conversation_get_name(conv), index);
 	}
 }
 
@@ -1521,7 +1526,7 @@
 	gc = purple_account_get_connection(account);
 	g_return_if_fail(gc != NULL);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	if (prpl_info && prpl_info->get_cb_real_name)
 		real_who = prpl_info->get_cb_real_name(gc,
@@ -1572,12 +1577,12 @@
 	PurplePluginProtocolInfo *prpl_info;
 	PurpleConversation *conv = gtkconv->active_conv;
 	const char *who = g_object_get_data(G_OBJECT(w), "user_data");
-	PurpleConnection *gc  = purple_conversation_get_gc(conv);
+	PurpleConnection *gc  = purple_conversation_get_connection(conv);
 	gchar *real_who = NULL;
 
 	g_return_if_fail(gc != NULL);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	if (prpl_info && prpl_info->get_cb_real_name)
 		real_who = prpl_info->get_cb_real_name(gc,
@@ -1658,7 +1663,7 @@
 	PurpleBuddy *buddy = NULL;
 
 	if (gc != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	/*
 	 * If a menu already exists, destroy it before creating a new one,
@@ -2447,7 +2452,7 @@
 		/* We deleted all the text, so turn off typing. */
 		purple_conv_im_stop_send_typed_timeout(im);
 
-		serv_send_typing(purple_conversation_get_gc(conv),
+		serv_send_typing(purple_conversation_get_connection(conv),
 						 purple_conversation_get_name(conv),
 						 PURPLE_NOT_TYPING);
 	}
@@ -3390,6 +3395,60 @@
 }
 
 static void
+regenerate_attention_items(PidginWindow *win)
+{
+	GtkWidget *menu;
+	PurpleConversation *conv;
+	PurpleConnection *pc;
+	PurplePlugin *prpl = NULL;
+	PurplePluginProtocolInfo *prpl_info = NULL;
+	GList *list;
+
+	conv = pidgin_conv_window_get_active_conversation(win);
+	if (!conv)
+		return;
+
+	/* Remove the previous entries */
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.get_attention), NULL);
+
+	pc = purple_conversation_get_connection(conv);
+	if (pc != NULL)
+		prpl = purple_connection_get_prpl(pc);
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_attention_types)) {
+		list = prpl_info->get_attention_types(purple_connection_get_account(pc));
+
+		/* Multiple attention types */
+		if (list && list->next) {
+			int index = 0;
+
+			menu = gtk_menu_new();
+			while (list) {
+				PurpleAttentionType *type;
+				GtkWidget *menuitem;
+
+				type = list->data;
+
+				menuitem = gtk_menu_item_new_with_label(purple_attention_type_get_name(type));
+				g_object_set_data(G_OBJECT(menuitem), "index", GINT_TO_POINTER(index));
+				g_signal_connect(G_OBJECT(menuitem), "activate",
+				                 G_CALLBACK(menu_get_attention_cb),
+				                 win);
+				gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+				index++;
+				list = g_list_delete_link(list, list);
+			}
+
+			gtk_menu_item_set_submenu(GTK_MENU_ITEM(win->menu.get_attention), menu);
+			gtk_widget_show_all(menu);
+		}
+	}
+}
+
+static void
 regenerate_options_items(PidginWindow *win)
 {
 	GtkWidget *menu;
@@ -3482,6 +3541,7 @@
 	regenerate_media_items(win);
 	regenerate_options_items(win);
 	regenerate_plugins_items(win);
+	regenerate_attention_items(win);
 
 	/* The following are to make sure the 'More' submenu is not regenerated every time
 	 * the focus shifts from 'Conversations' to some other menu and back. */
@@ -3679,7 +3739,7 @@
 				  time(NULL) > purple_conv_im_get_type_again(im)))
 	{
 		unsigned int timeout;
-		timeout = serv_send_typing(purple_conversation_get_gc(conv),
+		timeout = serv_send_typing(purple_conversation_get_connection(conv),
 								   purple_conversation_get_name(conv),
 								   PURPLE_TYPING);
 		purple_conv_im_set_type_again(im, timeout);
@@ -4100,9 +4160,9 @@
 	chat    = PURPLE_CONV_CHAT(conv);
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	gtkchat = gtkconv->u.chat;
-	gc      = purple_conversation_get_gc(conv);
-
-	if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)))
+	gc      = purple_conversation_get_connection(conv);
+
+	if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
 		return;
 
 	tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
@@ -4410,9 +4470,9 @@
 	char *new_topic;
 	const char *current_topic;
 
-	gc      = purple_conversation_get_gc(conv);
-
-	if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)))
+	gc      = purple_conversation_get_connection(conv);
+
+	if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
 		return;
 
 	if(prpl_info->set_chat_topic == NULL)
@@ -4502,7 +4562,7 @@
 	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
 		return;
 
-	normalized_name = g_strdup(purple_normalize(account, buddy->name));
+	normalized_name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy)));
 
 	do {
 		char *name;
@@ -4553,10 +4613,10 @@
 	g_return_if_fail(node != NULL);
 	g_return_if_fail(conv != NULL);
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 	g_return_if_fail(gc != NULL);
-	g_return_if_fail(gc->prpl != NULL);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)
 		return;
@@ -4576,7 +4636,7 @@
 	else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
 		update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info);
 	else if (PURPLE_BLIST_NODE_IS_CHAT(node) &&
-			purple_conversation_get_account(conv) == ((PurpleChat*)node)->account)
+			purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node))
 	{
 		if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0)
 			pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE);
@@ -4605,7 +4665,7 @@
 	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
 		return;
 
-	normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), buddy->name));
+	normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_buddy_get_name(buddy)));
 
 	do {
 		char *name;
@@ -4763,8 +4823,8 @@
 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
 {
 	PurpleConversation *conv = gtkconv->active_conv;
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
-	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
+	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	if (prpl_info->options & OPT_PROTO_CHAT_TOPIC)
 	{
 		GtkWidget *hbox, *label;
@@ -4813,7 +4873,7 @@
 
 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_account_get_connection(account)->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
 	node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who));
 	if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME))
 		pidgin_blist_draw_tooltip(node, gtkconv->infopane);
@@ -5074,7 +5134,11 @@
 			replace = purple_utf8_strftime(format ? format : "%X", NULL);
 			g_free(format);
 
+		} else if (g_str_has_prefix(cur, "%dateOpened%")) {
+			replace = purple_date_format_short(NULL);
+
 		} else {
+			cur++;
 			continue;
 		}
 
@@ -5407,7 +5471,7 @@
 	PurpleConversation *c;
 	PurpleAccount *convaccount = purple_conversation_get_account(conv);
 	PurpleConnection *gc = purple_account_get_connection(convaccount);
-	PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL;
+	PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
 
 	if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
 	{
@@ -5541,7 +5605,7 @@
 	for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) {
 		PurpleBuddy *b = PURPLE_BUDDY(bn);
 		PurpleConversation *conv;
-		if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) {
+		if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), purple_buddy_get_account(b)))) {
 			if (PIDGIN_CONVERSATION(conv))
 				return PIDGIN_CONVERSATION(conv);
 		}
@@ -5632,7 +5696,6 @@
 	GtkWidget *pane = NULL;
 	GtkWidget *tab_cont;
 	PurpleBlistNode *convnode;
-	PurpleValue *value;
 
 	if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
 		purple_conversation_set_ui_data(conv, gtkconv);
@@ -5719,11 +5782,9 @@
 	if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
 		gtkconv->make_sound = TRUE;
 
-	if (convnode != NULL &&
-	    (value = g_hash_table_lookup(convnode->settings, "enable-logging")) &&
-	    purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN)
-	{
-		purple_conversation_set_logging(conv, purple_value_get_boolean(value));
+	if (convnode != NULL) {
+		gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging");
+		purple_conversation_set_logging(conv, logging);
 	}
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"))
@@ -5959,7 +6020,7 @@
 						&start, &end)) {
 				GtkWidget *menu = NULL;
 				PurpleConnection *gc =
-					purple_conversation_get_gc(conv);
+					purple_conversation_get_connection(conv);
 
 
 				menu = create_chat_menu(conv, buddyname, gc);
@@ -6112,6 +6173,9 @@
 			replace = purple_utf8_strftime(format ? format : "%X", NULL);
 			g_free(format);
 
+		} else if (g_str_has_prefix(cur, "%shortTime%")) {
+			replace = purple_utf8_strftime("%H:%M", NULL);
+
 		} else if (g_str_has_prefix(cur, "%userIconPath%")) {
 			if (flags & PURPLE_MESSAGE_SEND) {
 				if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) {
@@ -6141,6 +6205,9 @@
 		} else if (g_str_has_prefix(cur, "%service%")) {
 			replace = purple_account_get_protocol_name(purple_conversation_get_account(conv));
 
+		} else if (g_str_has_prefix(cur, "%messageDirection%")) {
+			replace = purple_markup_is_rtl(message) ? "rtl" : "ltr";
+
 		} else {
 			cur++;
 			continue;
@@ -6597,7 +6664,15 @@
 	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
 		return;
 
+	if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
+		g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
+	if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE)))
+		g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
+
 	old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
+	if (!old_cbuddy)
+		return;
+
 	if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
 		GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy);
 
@@ -6606,14 +6681,6 @@
 		purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL);
 	}
 
-	if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
-		g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
-	if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE)))
-		g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
-
-	if (!old_cbuddy)
-		return;
-
 	g_return_if_fail(new_alias != NULL);
 
 	new_cbuddy = purple_conv_chat_cb_find(chat, new_name);
@@ -6902,11 +6969,11 @@
 	PurpleAccount *account;
 
 	win     = pidgin_conv_get_window(gtkconv);
-	gc      = purple_conversation_get_gc(conv);
+	gc      = purple_conversation_get_connection(conv);
 	account = purple_conversation_get_account(conv);
 
 	if (gc != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	if (win->menu.send_to != NULL)
 		update_send_to_selection(win);
@@ -7125,6 +7192,7 @@
 	{
 		gray_stuff_out(PIDGIN_CONVERSATION(conv));
 		generate_send_to_items(win);
+		regenerate_plugins_items(win);
 	}
 
 	if (fields & PIDGIN_CONV_TAB_ICON)
@@ -7442,7 +7510,7 @@
 	if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
 		return;
 
-	if (purple_conversation_get_gc(conv) == NULL)
+	if (purple_conversation_get_connection(conv) == NULL)
 		return;
 
 	buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
@@ -7948,7 +8016,7 @@
 	{
 		PurpleBuddy *buddy = (PurpleBuddy*)node;
 		PurpleConversation *conv;
-		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account);
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
 		if (conv)
 			return PIDGIN_CONVERSATION(conv);
 	}
@@ -7974,15 +8042,17 @@
 
 		if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
 				purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
-				purple_conversation_get_account(conv) == gc->account &&
+				purple_conversation_get_account(conv) == purple_connection_get_account(gc) &&
 				purple_conversation_get_data(conv, "want-to-rejoin")) {
 			GHashTable *comps = NULL;
 			PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
 			if (chat == NULL) {
-				if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL)
-					comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, purple_conversation_get_name(conv));
+				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+				
+				if (prpl_info->chat_info_defaults != NULL)
+					comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv));
 			} else {
-				comps = chat->components;
+				comps = purple_chat_get_components(chat);
 			}
 			serv_join_chat(gc, comps);
 			if (chat == NULL && comps != NULL)
@@ -8049,7 +8119,7 @@
 {
 	PurpleConversation *conv;
 
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
 	if (conv)
 		pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON);
 }
@@ -8059,7 +8129,7 @@
 {
 	PurpleConversation *conv;
 
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
 	if (conv)
 		pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON);
 }
@@ -8124,7 +8194,7 @@
 message_compare(gconstpointer p1, gconstpointer p2)
 {
 	const PurpleConvMessage *m1 = p1, *m2 = p2;
-	return (m1->when > m2->when);
+	return (purple_conversation_message_get_timestamp(m1) > purple_conversation_message_get_timestamp(m2));
 }
 
 /* Adds some message history to the gtkconv. This happens in a idle-callback. */
@@ -8140,11 +8210,17 @@
 	gtkconv->attach.timer = 0;
 	while (gtkconv->attach.current && count < 100) {  /* XXX: 100 is a random value here */
 		PurpleConvMessage *msg = gtkconv->attach.current->data;
-		if (!im && when && when < msg->when) {
+		if (!im && when && when < purple_conversation_message_get_timestamp(msg)) {
 			gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
 			g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
 		}
-		pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when);
+		pidgin_conv_write_conv(
+				purple_conversation_message_get_conv(msg),
+				purple_conversation_message_get_sender(msg),
+				purple_conversation_message_get_alias(msg),
+				purple_conversation_message_get_message(msg),
+				purple_conversation_message_get_flags(msg),
+				purple_conversation_message_get_timestamp(msg));
 		if (im) {
 			gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current);
 		} else {
@@ -8167,14 +8243,20 @@
 			GList *history = purple_conversation_get_message_history(conv);
 			for (; history; history = history->next) {
 				PurpleConvMessage *msg = history->data;
-				if (msg->when > when)
+				if (purple_conversation_message_get_timestamp(msg) > when)
 					msgs = g_list_prepend(msgs, msg);
 			}
 		}
 		msgs = g_list_sort(msgs, message_compare);
 		for (; msgs; msgs = g_list_delete_link(msgs, msgs)) {
 			PurpleConvMessage *msg = msgs->data;
-			pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when);
+			pidgin_conv_write_conv(
+					purple_conversation_message_get_conv(msg),
+					purple_conversation_message_get_sender(msg),
+					purple_conversation_message_get_alias(msg),
+					purple_conversation_message_get_message(msg),
+					purple_conversation_message_get_flags(msg),
+					purple_conversation_message_get_timestamp(msg));
 		}
 		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
 		g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
@@ -8252,7 +8334,7 @@
 				g_return_val_if_reached(TRUE);
 		}
 		g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time",
-				GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when));
+				GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConvMessage*)(list->data))));
 		gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv);
 	} else {
 		purple_signal_emit(pidgin_conversations_get_handle(),
@@ -9474,9 +9556,9 @@
 		PurpleConnection *gc;
 		PurplePluginProtocolInfo *prpl_info = NULL;
 
-		gc = purple_conversation_get_gc(conv);
+		gc = purple_conversation_get_connection(conv);
 		if (gc != NULL)
-			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 		if (prpl_info && prpl_info->set_chat_topic == NULL)
 			/* This protocol doesn't support setting the chat room topic */
 			return FALSE;
--- a/pidgin/gtkdialogs.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkdialogs.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1133,10 +1133,10 @@
 
 	g_return_if_fail(buddy != NULL);
 
-	secondary = g_strdup_printf(_("Enter an alias for %s."), buddy->name);
+	secondary = g_strdup_printf(_("Enter an alias for %s."), purple_buddy_get_name(buddy));
 
 	purple_request_input(NULL, _("Alias Buddy"), NULL,
-					   secondary, buddy->alias, FALSE, FALSE, NULL,
+					   secondary, purple_buddy_get_local_buddy_alias(buddy), FALSE, FALSE, NULL,
 					   _("Alias"), G_CALLBACK(pidgin_dialogs_alias_buddy_cb),
 					   _("Cancel"), NULL,
 					   purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL,
@@ -1161,7 +1161,7 @@
 					   chat->alias, FALSE, FALSE, NULL,
 					   _("Alias"), G_CALLBACK(pidgin_dialogs_alias_chat_cb),
 					   _("Cancel"), NULL,
-					   chat->account, NULL, NULL,
+					   purple_chat_get_account(chat), NULL, NULL,
 					   chat);
 }
 
@@ -1175,8 +1175,8 @@
 	group = (PurpleGroup*)cnode->parent;
 	for (bnode = cnode->child; bnode; bnode = bnode->next) {
 		PurpleBuddy *buddy = (PurpleBuddy*)bnode;
-		if (purple_account_is_connected(buddy->account))
-			purple_account_remove_buddy(buddy->account, buddy, group);
+		if (purple_account_is_connected(purple_buddy_get_account(buddy)))
+			purple_account_remove_buddy(purple_buddy_get_account(buddy), buddy, group);
 	}
 	purple_blist_remove_contact(contact);
 }
@@ -1201,8 +1201,8 @@
 						"want to continue?",
 						"You are about to remove the contact containing %s "
 						"and %d other buddies from your buddy list.  Do you "
-						"want to continue?", contact->totalsize - 1),
-					buddy->name, contact->totalsize - 1);
+						"want to continue?", purple_contact_get_contact_size(contact, TRUE) - 1),
+					purple_buddy_get_name(buddy), purple_contact_get_contact_size(contact, TRUE) - 1);
 
 		purple_request_action(contact, NULL, _("Remove Contact"), text, 0,
 				NULL, purple_contact_get_alias(contact), NULL,
@@ -1239,7 +1239,7 @@
 
 	text = g_strdup_printf(
 				_("You are about to merge the group called %s into the group "
-				"called %s. Do you want to continue?"), source->name, new_name);
+				"called %s. Do you want to continue?"), purple_group_get_name(source), new_name);
 
 	ggp = g_new(struct _PidginGroupMergeObject, 1);
 	ggp->parent = source;
@@ -1270,8 +1270,8 @@
 				if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) {
 					buddy = (PurpleBuddy*)bnode;
 					bnode = bnode->next;
-					if (purple_account_is_connected(buddy->account)) {
-						purple_account_remove_buddy(buddy->account, buddy, group);
+					if (purple_account_is_connected(purple_buddy_get_account(buddy))) {
+						purple_account_remove_buddy(purple_buddy_get_account(buddy), buddy, group);
 						purple_blist_remove_buddy(buddy);
 					}
 				} else {
@@ -1281,7 +1281,7 @@
 		} else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) {
 			PurpleChat *chat = (PurpleChat *)cnode;
 			cnode = cnode->next;
-			if (purple_account_is_connected(chat->account))
+			if (purple_account_is_connected(purple_chat_get_account(chat)))
 				purple_blist_remove_chat(chat);
 		} else {
 			cnode = cnode->next;
@@ -1299,7 +1299,7 @@
 	g_return_if_fail(group != NULL);
 
 	text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list.  Do you want to continue?"),
-						   group->name);
+						   purple_group_get_name(group));
 
 	purple_request_action(group, NULL, _("Remove Group"), text, 0,
 						NULL, NULL, NULL,
@@ -1319,10 +1319,10 @@
 	PurpleAccount *account;
 
 	group = purple_buddy_get_group(buddy);
-	name = g_strdup(buddy->name); /* b->name is a crasher after remove_buddy */
-	account = buddy->account;
+	name = g_strdup(purple_buddy_get_name(buddy)); /* purple_buddy_get_name() is a crasher after remove_buddy */
+	account = purple_buddy_get_account(buddy);
 
-	purple_debug_info("blist", "Removing '%s' from buddy list.\n", buddy->name);
+	purple_debug_info("blist", "Removing '%s' from buddy list.\n", purple_buddy_get_name(buddy));
 	/* TODO - Should remove from blist first... then call purple_account_remove_buddy()? */
 	purple_account_remove_buddy(account, buddy, group);
 	purple_blist_remove_buddy(buddy);
@@ -1338,7 +1338,7 @@
 	g_return_if_fail(buddy != NULL);
 
 	text = g_strdup_printf(_("You are about to remove %s from your buddy list.  Do you want to continue?"),
-						   buddy->name);
+						   purple_buddy_get_name(buddy));
 
 	purple_request_action(buddy, NULL, _("Remove Buddy"), text, 0,
 						purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL,
@@ -1368,7 +1368,7 @@
 			name ? name : "");
 
 	purple_request_action(chat, NULL, _("Remove Chat"), text, 0,
-						chat->account, NULL, NULL,
+						purple_chat_get_account(chat), NULL, NULL,
 						chat, 2,
 						_("_Remove Chat"), G_CALLBACK(pidgin_dialogs_remove_chat_cb),
 						_("Cancel"), NULL);
--- a/pidgin/gtkdocklet.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkdocklet.c	Fri Dec 23 06:58:52 2011 +0000
@@ -272,7 +272,7 @@
 
 	while(c != NULL) {
 		PurpleConnection *gc = c->data;
-		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 		if (prpl_info != NULL && prpl_info->chat_info != NULL)
 			return TRUE;
 		c = c->next;
@@ -309,7 +309,7 @@
 docklet_signed_on_cb(PurpleConnection *gc)
 {
 	if (!enable_join_chat) {
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL)
+		if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL)
 			enable_join_chat = TRUE;
 	}
 	docklet_update_status();
@@ -319,7 +319,7 @@
 docklet_signed_off_cb(PurpleConnection *gc)
 {
 	if (enable_join_chat) {
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL)
+		if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL)
 			enable_join_chat = online_account_supports_chat();
 	}
 	docklet_update_status();
--- a/pidgin/gtkft.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkft.c	Fri Dec 23 06:58:52 2011 +0000
@@ -247,7 +247,7 @@
 
 	get_xfer_info_strings(xfer, &kbsec, &time_elapsed, &time_remaining);
 
-	status = g_strdup_printf("%d%% (%" G_GSIZE_FORMAT " of %" G_GSIZE_FORMAT " bytes)",
+	status = g_strdup_printf("%d%% (%" G_GOFFSET_FORMAT " of %" G_GOFFSET_FORMAT " bytes)",
 							 (int)(purple_xfer_get_progress(xfer)*100),
 							 purple_xfer_get_bytes_sent(xfer),
 							 purple_xfer_get_size(xfer));
--- a/pidgin/gtkimhtml.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkimhtml.c	Fri Dec 23 06:58:52 2011 +0000
@@ -93,6 +93,36 @@
 	GtkTextMark *mark;
 };
 
+struct _GtkIMHtmlScalable {
+	void (*scale)(struct _GtkIMHtmlScalable *, int, int);
+	void (*add_to)(struct _GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *);
+	void (*free)(struct _GtkIMHtmlScalable *);
+};
+
+struct _GtkIMHtmlHr {
+	GtkIMHtmlScalable scalable;
+	GtkWidget *sep;
+};
+
+struct _GtkIMHtmlImage {
+	GtkIMHtmlScalable scalable;
+	GtkImage *image; /**< Contains the scaled version of this pixbuf. */
+	GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */
+	GtkTextMark *mark;
+	gchar *filename;
+	int width;
+	int height;
+	int id;
+	GtkWidget *filesel;
+};
+
+struct _GtkIMHtmlAnimation {
+	GtkIMHtmlImage imhtmlimage;
+	GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */
+	GdkPixbufAnimationIter *iter;
+	guint timer;
+};
+
 struct _GtkIMHtmlLink
 {
 	GtkIMHtml *imhtml;
@@ -100,6 +130,12 @@
 	GtkTextTag *tag;
 };
 
+struct _GtkSmileyTree {
+	GString *values;
+	GtkSmileyTree **children;
+	GtkIMHtmlSmiley *image;
+};
+
 typedef struct {
 	char *name;
 	int length;
--- a/pidgin/gtkimhtml.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkimhtml.h	Fri Dec 23 06:58:52 2011 +0000
@@ -148,12 +148,6 @@
 	GList *protocols; /* List of GtkIMHtmlProtocol's */
 };
 
-struct _GtkSmileyTree {
-	GString *values;
-	GtkSmileyTree **children;
-	GtkIMHtmlSmiley *image;
-};
-
 struct _GtkIMHtmlSmiley {
 	gchar *smile;
 	gchar *file;
@@ -167,36 +161,6 @@
 	gsize datasize;
 };
 
-struct _GtkIMHtmlScalable {
-	void (*scale)(struct _GtkIMHtmlScalable *, int, int);
-	void (*add_to)(struct _GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *);
-	void (*free)(struct _GtkIMHtmlScalable *);
-};
-
-struct _GtkIMHtmlImage {
-	GtkIMHtmlScalable scalable;
-	GtkImage *image; /**< Contains the scaled version of this pixbuf. */
-	GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */
-	GtkTextMark *mark;
-	gchar *filename;
-	int width;
-	int height;
-	int id;
-	GtkWidget *filesel;
-};
-
-struct _GtkIMHtmlAnimation {
-	GtkIMHtmlImage imhtmlimage;
-	GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */
-	GdkPixbufAnimationIter *iter;
-	guint timer;
-};
-
-struct _GtkIMHtmlHr {
-	GtkIMHtmlScalable scalable;
-	GtkWidget *sep;
-};
-
 typedef enum {
 	GTK_IMHTML_NO_COLOURS          = 1 << 0,
 	GTK_IMHTML_NO_FONTS            = 1 << 1,
--- a/pidgin/gtkimhtmltoolbar.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Fri Dec 23 06:58:52 2011 +0000
@@ -917,7 +917,7 @@
 	PurpleConversation *conv =
 		g_object_get_data(G_OBJECT(toolbar), "active_conv");
 	const gchar *who = purple_conversation_get_name(conv);
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 
 	toggle_button_set_active_block(GTK_TOGGLE_BUTTON(attention), FALSE, toolbar);
 	purple_prpl_send_attention(gc, who, 0);
@@ -1254,6 +1254,7 @@
 		{PIDGIN_STOCK_TOOLBAR_INSERT_LINK, insert_link_cb, &toolbar->link, _("Insert Link")},
 		{"", NULL, NULL, NULL},
 		{PIDGIN_STOCK_TOOLBAR_SMILEY, insert_smiley_cb, &toolbar->smiley, _("Insert Smiley")},
+		{PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, send_attention_cb, &toolbar->attention, _("Send Attention")},
 		{NULL, NULL, NULL, NULL}
 	};
 	int iter;
@@ -1276,18 +1277,6 @@
 			button = gtk_vseparator_new();
 		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
 	}
-	/* create the attention button (this is a bit hacky to not break ABI) */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION);
-	g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(gtk_imhtmltoolbar_popup_menu), toolbar);
-	g_signal_connect(G_OBJECT(button), "clicked",
-		G_CALLBACK(send_attention_cb), toolbar);
-	g_object_set_data(G_OBJECT(toolbar), "attention", button);
-#if GTK_CHECK_VERSION(2,12,0)
-	gtk_widget_set_tooltip_text(button, _("Send Attention"));
-#else
-	gtk_tooltips_set_tip(toolbar->tooltips, button, _("Send Attention"), NULL);
-#endif
-	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
 
 	gtk_box_pack_start(GTK_BOX(toolbar), hbox, FALSE, FALSE, 0);
 	g_object_set_data(G_OBJECT(toolbar), "wide-view", hbox);
@@ -1350,7 +1339,6 @@
 	GtkWidget *insert_menu;
 	GtkWidget *menuitem;
 	GtkWidget *sep;
-	GObject *wide_attention_button;
 	int i;
 	struct {
 		const char *label;
@@ -1503,8 +1491,6 @@
 	gtk_widget_show_all(sep);
 
 	/* Attention */
-	wide_attention_button = g_object_get_data(G_OBJECT(toolbar), "attention");
-
 	attention_button = gtk_button_new();
 	gtk_button_set_relief(GTK_BUTTON(attention_button), GTK_RELIEF_NONE);
 	bbox = gtk_hbox_new(FALSE, 3);
@@ -1516,16 +1502,16 @@
 	gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(box), attention_button, FALSE, FALSE, 0);
 	g_signal_connect_swapped(G_OBJECT(attention_button), "clicked",
-		G_CALLBACK(gtk_button_clicked), wide_attention_button);
+		G_CALLBACK(gtk_button_clicked), toolbar->attention);
 	gtk_widget_show_all(attention_button);
 
-	g_signal_connect(wide_attention_button, "notify::sensitive",
+	g_signal_connect(G_OBJECT(toolbar->attention), "notify::sensitive",
 			G_CALLBACK(button_sensitiveness_changed), attention_button);
-	g_signal_connect(wide_attention_button, "notify::visible",
+	g_signal_connect(G_OBJECT(toolbar->attention), "notify::visible",
 			G_CALLBACK(button_visibility_changed), attention_button);
 
 	/* set attention button to be greyed out until we get a conversation */
-	gtk_widget_set_sensitive(GTK_WIDGET(wide_attention_button), FALSE);
+	gtk_widget_set_sensitive(toolbar->attention, FALSE);
 
 	gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0);
 	g_object_set_data(G_OBJECT(hbox), "lean-view", box);
@@ -1606,16 +1592,14 @@
 void gtk_imhtmltoolbar_switch_active_conversation(GtkIMHtmlToolbar *toolbar,
 	PurpleConversation *conv)
 {
-	PurpleConnection *gc = purple_conversation_get_gc(conv);
+	PurpleConnection *gc = purple_conversation_get_connection(conv);
 	PurplePlugin *prpl = purple_connection_get_prpl(gc);
-	GtkWidget *attention =
-		g_object_get_data(G_OBJECT(toolbar), "attention");
 
 	g_object_set_data(G_OBJECT(toolbar), "active_conv", conv);
 
 	/* gray out attention button on protocols that don't support it
 	 for the time being it is always disabled for chats */
-	gtk_widget_set_sensitive(attention,
+	gtk_widget_set_sensitive(toolbar->attention,
 		conv && prpl && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM &&
 		PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL);
 }
--- a/pidgin/gtkimhtmltoolbar.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkimhtmltoolbar.h	Fri Dec 23 06:58:52 2011 +0000
@@ -69,6 +69,7 @@
 	GtkWidget *image;
 	GtkWidget *link;
 	GtkWidget *smiley;
+	GtkWidget *attention;
 
 	GtkWidget *font_dialog;
 	GtkWidget *fgcolor_dialog;
--- a/pidgin/gtkmedia.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkmedia.c	Fri Dec 23 06:58:52 2011 +0000
@@ -40,6 +40,8 @@
 
 #ifdef _WIN32
 #include <gdk/gdkwin32.h>
+#elif defined(GDK_WINDOWING_QUARTZ)
+#include <gdk/gdkquartz.h>
 #endif
 
 #include <gst/interfaces/xoverlay.h>
@@ -290,14 +292,14 @@
 	GtkWidget *menu;
 
 	action_group = gtk_action_group_new("MediaActions");
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(action_group,
+	                                        PACKAGE);
+#endif
 	gtk_action_group_add_actions(action_group,
 	                             menu_entries,
 	                             G_N_ELEMENTS(menu_entries),
 	                             GTK_WINDOW(window));
-#ifdef ENABLE_NLS
-	gtk_action_group_set_translation_domain(action_group,
-	                                        PACKAGE);
-#endif
 
 	window->priv->ui = gtk_ui_manager_new();
 	gtk_ui_manager_insert_action_group(window->priv->ui, action_group, 0);
@@ -455,7 +457,7 @@
 		progress = pidgin_media_get_widget(gtkmedia, session_id, participant);
 
 	if (progress)
-		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level * 5);
+		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level);
 }
 
 
@@ -560,6 +562,8 @@
 		window_id = GDK_WINDOW_HWND(window);
 #elif defined(HAVE_X11)
 		window_id = GDK_WINDOW_XWINDOW(window);
+#elif defined(GDK_WINDOWING_QUARTZ)
+		window_id = (gulong) gdk_quartz_window_get_nsview(window);
 #else
 #		error "Unsupported windowing system"
 #endif
@@ -789,7 +793,7 @@
 
 		/* Hold button */
 		gtkmedia->priv->hold =
-				gtk_toggle_button_new_with_mnemonic("_Hold");
+				gtk_toggle_button_new_with_mnemonic(_("_Hold"));
 		gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->hold,
 				FALSE, FALSE, 0);
 		gtk_widget_show(gtkmedia->priv->hold);
@@ -878,7 +882,7 @@
 
 	if (type & PURPLE_MEDIA_SEND_AUDIO) {
 		gtkmedia->priv->mute =
-				gtk_toggle_button_new_with_mnemonic("_Mute");
+				gtk_toggle_button_new_with_mnemonic(_("_Mute"));
 		gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->mute,
 				FALSE, FALSE, 0);
 		gtk_widget_show(gtkmedia->priv->mute);
@@ -969,7 +973,7 @@
 		pidgin_media_set_state(gtkmedia, PIDGIN_MEDIA_ACCEPTED);
 		pidgin_media_emit_message(gtkmedia, _("Call in progress."));
 		gtk_statusbar_push(GTK_STATUSBAR(gtkmedia->priv->statusbar),
-				0, _("Call in progress."));
+				0, _("Call in progress"));
 		gtk_widget_show(GTK_WIDGET(gtkmedia));
 	}
 }
@@ -1082,6 +1086,10 @@
 		src = gst_element_factory_make("dshowvideosrc", NULL);
 	if (src == NULL)
 		src = gst_element_factory_make("autovideosrc", NULL);
+#elif defined(__APPLE__)
+	src = gst_element_factory_make("osxvideosrc", NULL);
+	if (src == NULL)
+		src = gst_element_factory_make("autovideosrc", NULL);
 #else
 	src = gst_element_factory_make("gconfvideosrc", NULL);
 	if (src == NULL)
@@ -1136,6 +1144,8 @@
 		src = gst_element_factory_make("osssrc", NULL);
 	if (src == NULL)
 		src = gst_element_factory_make("dshowaudiosrc", NULL);
+	if (src == NULL)
+		src = gst_element_factory_make("osxaudiosrc", NULL);
 	if (src == NULL) {
 		purple_debug_error("gtkmedia", "Unable to find a suitable "
 				"element for the default audio source.\n");
--- a/pidgin/gtknotify.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtknotify.c	Fri Dec 23 06:58:52 2011 +0000
@@ -691,6 +691,8 @@
 	PurpleAccount *account;
 	PidginNotifyMailData *data = NULL, *data2;
 	gboolean new_data = FALSE;
+	GtkTreeSelection *sel;
+	GtkTreeIter iter;
 
 	/* Don't bother updating if there aren't new emails and we don't have any displayed currently */
 	if (count == 0 && mail_dialog == NULL)
@@ -777,6 +779,13 @@
 		}
 	}
 
+	/* Select first item if nothing selected */
+	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(mail_dialog->treeview));
+	if ((gtk_tree_selection_count_selected_rows(sel) < 1)
+		&& gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mail_dialog->treemodel), &iter)) {
+		gtk_tree_selection_select_iter(sel, &iter);
+	}
+
 #if GTK_CHECK_VERSION(2,18,0)
 	if (!gtk_widget_get_visible(mail_dialog->dialog)) {
 #else
@@ -1027,7 +1036,7 @@
 		renderer = gtk_cell_renderer_text_new();
 
 		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1,
-				column->title, renderer, "text", i, NULL);
+				purple_notify_searchresult_column_get_title(column), renderer, "text", i, NULL);
 
 		if (!purple_notify_searchresult_column_is_visible(column))
 			gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), i), FALSE);
@@ -1041,7 +1050,7 @@
 		switch (b->type) {
 			case PURPLE_NOTIFY_BUTTON_LABELED:
 				if(b->label) {
-					button = gtk_button_new_with_label(b->label);
+					button = gtk_dialog_add_button(GTK_DIALOG(window), b->label, GTK_RESPONSE_NONE);
 				} else {
 					purple_debug_warning("gtknotify", "Missing button label\n");
 				}
@@ -1086,7 +1095,7 @@
 	g_signal_connect_swapped(G_OBJECT(close_button), "clicked",
 	                         G_CALLBACK(searchresults_close_cb), data);
 
-	data->account = gc->account;
+	data->account = purple_connection_get_account(gc);
 	data->model = model;
 	data->treeview = treeview;
 	data->window = window;
@@ -1542,11 +1551,13 @@
 		gtk_tree_view_set_search_column(GTK_TREE_VIEW(spec_dialog->treeview), PIDGIN_MAIL_TEXT);
 		gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(spec_dialog->treeview),
 			             pidgin_tree_view_search_equal_func, NULL, NULL);
+		sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(spec_dialog->treeview));
+		gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
 
 		g_signal_connect(G_OBJECT(dialog), "response",
 						 G_CALLBACK(email_response_cb), spec_dialog);
-		g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(spec_dialog->treeview))),
-						 "changed", G_CALLBACK(selection_changed_cb), spec_dialog);
+		g_signal_connect(G_OBJECT(sel), "changed",
+		                 G_CALLBACK(selection_changed_cb), spec_dialog);
 		g_signal_connect(G_OBJECT(spec_dialog->treeview), "row-activated", G_CALLBACK(email_row_activated_cb), NULL);
 
 		column = gtk_tree_view_column_new();
--- a/pidgin/gtkpounce.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkpounce.c	Fri Dec 23 06:58:52 2011 +0000
@@ -427,9 +427,9 @@
 
 		dialog = (PidginPounceDialog *)data;
 
-		gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), buddy->name);
-		dialog->account = buddy->account;
-		pidgin_account_option_menu_set_selected(dialog->account_menu, buddy->account);
+		gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), purple_buddy_get_name(buddy));
+		dialog->account = purple_buddy_get_account(buddy);
+		pidgin_account_option_menu_set_selected(dialog->account_menu, purple_buddy_get_account(buddy));
 
 		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
@@ -476,7 +476,7 @@
 {
 	PurpleAccount *account = pidgin_account_option_menu_get_selected(dialog->account_menu);
 	gtk_imhtml_setup_entry(GTK_IMHTML(dialog->send_msg_entry),
-			(account && purple_account_get_connection(account)) ? purple_account_get_connection(account)->flags : PURPLE_CONNECTION_HTML);
+			(account && purple_account_get_connection(account)) ? purple_connection_get_flags(purple_account_get_connection(account)) : PURPLE_CONNECTION_HTML);
 }
 
 void
@@ -1423,7 +1423,6 @@
 	if (purple_pounce_action_is_enabled(pounce, "popup-notify"))
 	{
 		char *tmp;
-		const char *name_shown;
 		const char *reason;
 		reason = purple_pounce_action_get_attribute(pounce, "popup-notify",
 														  "reason");
@@ -1456,14 +1455,6 @@
 				   _("Unknown.... Please report this!")
 				   );
 
-		/*
-		 * Ok here is where I change the second argument, title, from
-		 * NULL to the account alias if we have it or the account
-		 * name if that's all we have
-		 */
-		if ((name_shown = purple_account_get_alias(account)) == NULL)
-			name_shown = purple_account_get_username(account);
-
 		pidgin_notify_pounce_add(account, pounce, alias, tmp, reason,
 				purple_date_format_full(NULL));
 
--- a/pidgin/gtkprefs.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkprefs.c	Fri Dec 23 06:58:52 2011 +0000
@@ -2225,6 +2225,14 @@
 		path = g_find_program_in_path("gnome-network-properties");
 		if (path == NULL)
 			path = g_find_program_in_path("gnome-network-preferences");
+		if (path == NULL) {
+			path = g_find_program_in_path("gnome-control-center");
+			if (path != NULL) {
+				char *tmp = g_strdup_printf("%s network", path);
+				g_free(path);
+				path = tmp;
+			}
+		}
 
 		if (path == NULL) {
 			label = gtk_label_new(NULL);
@@ -3081,7 +3089,6 @@
 	purple_prefs_rename("/purple/conversations/placement",
 					  PIDGIN_PREFS_ROOT "/conversations/placement");
 
-	purple_prefs_rename(PIDGIN_PREFS_ROOT "/debug/timestamps", "/purple/debug/timestamps");
 	purple_prefs_rename(PIDGIN_PREFS_ROOT "/conversations/im/raise_on_events", "/plugins/gtk/X11/notify/method_raise");
 
 	purple_prefs_rename_boolean_toggle(PIDGIN_PREFS_ROOT "/conversations/ignore_colors",
@@ -3127,6 +3134,7 @@
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ignore_fonts");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ignore_font_sizes");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/passthrough_unknown_commands");
+	purple_prefs_remove(PIDGIN_PREFS_ROOT "/debug/timestamps");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/idle");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/logging/individual_logs");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/sound/signon");
--- a/pidgin/gtkroomlist.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkroomlist.c	Fri Dec 23 06:58:52 2011 +0000
@@ -233,7 +233,7 @@
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	if(gc != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	if(prpl_info != NULL && prpl_info->roomlist_room_serialize)
 		name = prpl_info->roomlist_room_serialize(info->room);
@@ -502,7 +502,7 @@
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	if (conn && PURPLE_CONNECTION_IS_CONNECTED(conn))
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(conn));
 
 	return (prpl_info && prpl_info->roomlist_get_list != NULL);
 }
--- a/pidgin/gtkutils.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkutils.c	Fri Dec 23 06:58:52 2011 +0000
@@ -1023,7 +1023,7 @@
 		return;
 	}
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(conn));
 	if (prpl_info != NULL && prpl_info->get_cb_real_name)
 		who = prpl_info->get_cb_real_name(conn, chat, name);
 	if (prpl_info == NULL || prpl_info->get_cb_info == NULL) {
@@ -1149,7 +1149,7 @@
 					gc = (PurpleConnection *)l->data;
 					account = purple_connection_get_account(gc);
 
-					prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+					prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 				}
 
 				protoname = prpl_info->list_icon(account, NULL);
@@ -1191,7 +1191,7 @@
 						gc = (PurpleConnection *)l->data;
 						account = purple_connection_get_account(gc);
 
-						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 					}
 
 					protoname = prpl_info->list_icon(account, NULL);
@@ -1603,7 +1603,7 @@
 			data->account = account;
 
 			if (gc)
-				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 			if (prpl_info && prpl_info->options & OPT_PROTO_IM_IMAGE)
 				im = TRUE;
@@ -2088,8 +2088,8 @@
 					add_buddyname_autocomplete_entry(data->store,
 														((PurpleContact *)cnode)->alias,
 														purple_buddy_get_contact_alias(entry.entry.buddy),
-														entry.entry.buddy->account,
-														entry.entry.buddy->name
+														purple_buddy_get_account(entry.entry.buddy),
+														purple_buddy_get_name(entry.entry.buddy)
 													 );
 				}
 			}
@@ -2181,7 +2181,7 @@
 	gboolean all = GPOINTER_TO_INT(all_accounts);
 
 	if (completion_entry->is_buddy) {
-		return all || purple_account_is_connected(completion_entry->entry.buddy->account);
+		return all || purple_account_is_connected(purple_buddy_get_account(completion_entry->entry.buddy));
 	} else {
 		return all || (completion_entry->entry.logged_buddy->account != NULL && purple_account_is_connected(completion_entry->entry.logged_buddy->account));
 	}
@@ -2487,9 +2487,9 @@
 					   the image. */
 					purple_debug_info("buddyicon", "Converted image from "
 							"%dx%d to %dx%d, format=%s, quality=%u, "
-							"filesize=%zu\n", orig_width, orig_height,
-							new_width, new_height, prpl_formats[i], quality,
-							length);
+							"filesize=%" G_GSIZE_FORMAT "\n",
+							orig_width, orig_height, new_width, new_height,
+							prpl_formats[i], quality, length);
 					if (len)
 						*len = length;
 					g_strfreev(prpl_formats);
@@ -3080,7 +3080,7 @@
 
 	if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) {
 		purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() "
-				"failed with size=%zu: %s\n", count,
+				"failed with size=%" G_GSIZE_FORMAT ": %s\n", count,
 				error ? error->message : "(no error message)");
 		if (error)
 			g_error_free(error);
@@ -3090,7 +3090,7 @@
 
 	if (!gdk_pixbuf_loader_close(loader, &error) || error) {
 		purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() "
-				"failed for image of size %zu: %s\n", count,
+				"failed for image of size %" G_GSIZE_FORMAT ": %s\n", count,
 				error ? error->message : "(no error message)");
 		if (error)
 			g_error_free(error);
@@ -3104,7 +3104,7 @@
 		pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader));
 	if (!pixbuf) {
 		purple_debug_warning("gtkutils", "%s() returned NULL for image "
-				"of size %zu\n",
+				"of size %" G_GSIZE_FORMAT "\n",
 				animated ? "gdk_pixbuf_loader_get_animation"
 					: "gdk_pixbuf_loader_get_pixbuf", count);
 		g_object_unref(G_OBJECT(loader));
--- a/pidgin/gtkwebview.h	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/gtkwebview.h	Fri Dec 23 06:58:52 2011 +0000
@@ -64,22 +64,22 @@
 /**
  * Returns the GType for a GtkWebView widget
  *
- * @return the GType for GtkWebView widget
+ * @return The GType for GtkWebView widget
  */
 GType gtk_webview_get_type(void);
 
 /**
  * Create a new GtkWebView object
  *
- * @return a GtkWidget corresponding to the GtkWebView object
+ * @return A GtkWidget corresponding to the GtkWebView object
  */
 GtkWidget *gtk_webview_new(void);
 
 /**
  * Set the vertical adjustment for the GtkWebView.
  *
- * @param webview  The GtkWebView.
- * @param vadj     The GtkAdjustment that control the webview.
+ * @param webview  The GtkWebView object
+ * @param vadj     The GtkAdjustment that control the webview
  */
 void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj);
 
@@ -109,7 +109,7 @@
  *
  * @param webview The GtkWebView object
  *
- * @return gboolean indicating whether the webview is empty.
+ * @return gboolean indicating whether the webview is empty
  */
 gboolean gtk_webview_is_empty(GtkWebView *webview);
 
@@ -120,8 +120,8 @@
  * conditions when calling JS functions immediately after opening the
  * page.
  *
- * @param webview the GtkWebView object
- * @param script   the script to execute
+ * @param webview The GtkWebView object
+ * @param script  The script to execute
  */
 void gtk_webview_safe_execute_script(GtkWebView *webview, const char *script);
 
@@ -131,15 +131,15 @@
  *
  * @param str The string to escape and quote
  *
- * @return the quoted string.
+ * @return The quoted string
  */
 char *gtk_webview_quote_js_string(const char *str);
 
 /**
  * Scrolls the Webview to the end of its contents.
  *
- * @param webview The GtkWebView.
- * @param smooth   A boolean indicating if smooth scrolling should be used.
+ * @param webview The GtkWebView object
+ * @param smooth  A boolean indicating if smooth scrolling should be used
  */
 void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth);
 
--- a/pidgin/pidgin-3.pc.in	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/pidgin-3.pc.in	Fri Dec 23 06:58:52 2011 +0000
@@ -1,7 +1,7 @@
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
-includedir=@includedir@
+includedir=@includedir@/pidgin
 datarootdir=@datarootdir@
 datadir=@datadir@
 sysconfdir=@sysconfdir@
--- a/pidgin/plugins/Makefile.am	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/plugins/Makefile.am	Fri Dec 23 06:58:52 2011 +0000
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = adiumthemes cap disco gestures gevolution musicmessaging perl ticker
+DIST_SUBDIRS = cap disco gestures gevolution musicmessaging perl ticker
 
 if BUILD_GEVOLUTION
 GEVOLUTION_DIR = gevolution
@@ -27,8 +27,7 @@
 	$(MUSICMESSAGING_DIR) \
 	$(PERL_DIR) \
 	disco \
-	ticker \
-	adiumthemes
+	ticker
 
 plugindir = $(libdir)/pidgin
 
--- a/pidgin/plugins/adiumthemes/Makefile.am	Sun Oct 09 07:10:36 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-
-adiumtemplatedir = $(datadir)/pidgin/webkit
-adiumtemplate_DATA = Template.html
-
-adiumdir = $(libdir)/pidgin
-
-adium_la_LDFLAGS = -module -avoid-version
-
-EXTRA_DIST = $(webkittemplate_DATA)
-
-if PLUGINS
-
-adium_LTLIBRARIES = adium.la
-
-adium_la_SOURCES = webkit.c \
-	message-style.h \
-	message-style.c
-
-endif
-
-adium_la_LIBADD = $(GTK_LIBS) $(WEBKIT_LIBS)
-
-AM_CPPFLAGS = \
-	-DDATADIR=\"$(datadir)\" \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	-I$(top_srcdir)/pidgin \
-	$(DEBUG_CFLAGS) \
-	$(GTK_CFLAGS) \
-	$(WEBKIT_CFLAGS)
--- a/pidgin/plugins/adiumthemes/Template.html	Sun Oct 09 07:10:36 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
-	<base href="%@">
-	<script type="text/ecmascript" defer="defer">
-	
-		//Appending new content to the message view
-		function appendMessage(html) {
-			shouldScroll = nearBottom();
-		
-			//Remove any existing insertion point
-			insert = document.getElementById("insert");
-			if(insert) insert.parentNode.removeChild(insert);
-
-			//Append the new message to the bottom of our chat block
-			chat = document.getElementById("Chat");
-			range = document.createRange();
-			range.selectNode(chat);
-			documentFragment = range.createContextualFragment(html);
-			chat.appendChild(documentFragment);
-			
-			alignChat(shouldScroll);
-		}
-		function appendMessageNoScroll(html) {
-			//Remove any existing insertion point
-			insert = document.getElementById("insert");
-			if(insert) insert.parentNode.removeChild(insert);
-
-			//Append the new message to the bottom of our chat block
-			chat = document.getElementById("Chat");
-			range = document.createRange();
-			range.selectNode(chat);
-			documentFragment = range.createContextualFragment(html);
-			chat.appendChild(documentFragment);
-		}
-		function appendNextMessage(html){
-			shouldScroll = nearBottom();
-
-			//Locate the insertion point
-			insert = document.getElementById("insert");
-		
-			//make new node
-			range = document.createRange();
-			range.selectNode(insert.parentNode);
-			newNode = range.createContextualFragment(html);
-
-			//swap
-			insert.parentNode.replaceChild(newNode,insert);
-			
-			alignChat(shouldScroll);
-		}
-		function appendNextMessageNoScroll(html){
-			//Locate the insertion point
-			insert = document.getElementById("insert");
-		
-			//make new node
-			range = document.createRange();
-			range.selectNode(insert.parentNode);
-			newNode = range.createContextualFragment(html);
-
-			//swap
-			insert.parentNode.replaceChild(newNode,insert);
-		}
-		
-		//Auto-scroll to bottom.  Use nearBottom to determine if a scrollToBottom is desired.
-		function nearBottom() {
-			return ( document.body.scrollTop >= ( document.body.offsetHeight - ( window.innerHeight * 1.2 ) ) );
-		}
-		function scrollToBottom() {
-			document.body.scrollTop = document.body.offsetHeight;
-		}
-
-		//Dynamically exchange the active stylesheet
-		function setStylesheet( id, url ) {
-			code = "<style id=\"" + id + "\" type=\"text/css\" media=\"screen,print\">";
-			if( url.length ) code += "@import url( \"" + url + "\" );";
-			code += "</style>";
-			range = document.createRange();
-			head = document.getElementsByTagName( "head" ).item(0);
-			range.selectNode( head );
-			documentFragment = range.createContextualFragment( code );
-			head.removeChild( document.getElementById( id ) );
-			head.appendChild( documentFragment );
-		}
-		
-		//Swap an image with its alt-tag text on click, or expand/unexpand an attached image
-		document.onclick = imageCheck;
-		function imageCheck() {		
-			node = event.target;
-			if(node.tagName == 'IMG' && !client.zoomImage(node) && node.alt) {
-				a = document.createElement('a');
-				a.setAttribute('onclick', 'imageSwap(this)');
-				a.setAttribute('src', node.getAttribute('src'));
-				a.className = node.className;
-				text = document.createTextNode(node.alt);
-				a.appendChild(text);
-				node.parentNode.replaceChild(a, node);
-			}
-		}
-
-		function imageSwap(node) {
-			shouldScroll = nearBottom();
-
-			//Swap the image/text
-			img = document.createElement('img');
-			img.setAttribute('src', node.getAttribute('src'));
-			img.setAttribute('alt', node.firstChild.nodeValue);
-			img.className = node.className;
-			node.parentNode.replaceChild(img, node);
-			
-			alignChat(shouldScroll);
-		}
-		
-		//Align our chat to the bottom of the window.  If true is passed, view will also be scrolled down
-		function alignChat(shouldScroll) {
-			var windowHeight = window.innerHeight;
-			
-			if (windowHeight > 0) {
-				var contentElement = document.getElementById('Chat');
-				var contentHeight = contentElement.offsetHeight;
-				if (windowHeight - contentHeight > 0) {
-					contentElement.style.position = 'relative';
-					contentElement.style.top = (windowHeight - contentHeight) + 'px';
-				} else {
-					contentElement.style.position = 'static';
-				}
-			}
-			
-			if (shouldScroll) scrollToBottom();
-		}
-		
-		function windowDidResize(){
-			alignChat(true/*nearBottom()*/); //nearBottom buggy with inactive tabs
-		}
-		
-		window.onresize = windowDidResize;
-	</script>
-	
-	<style type="text/css">
-		.actionMessageUserName:before { content:"*"; }
-		.actionMessageBody:after { content:"*"; }
-		*{ word-wrap:break-word; }
-		img.scaledToFitImage { height:auto; width:100%; }
-	</style>
-	
-	<!-- This style is shared by all variants. !-->
-	<style id="baseStyle" type="text/css" media="screen,print">	
-		%@
-	</style>
-	
-	<!-- Although we call this mainStyle for legacy reasons, it's actually the variant style !-->
-	<style id="mainStyle" type="text/css" media="screen,print">	
-		@import url( "%@" );
-	</style>
-
-</head>
-<body onload="alignChat(true);" style="==bodyBackground==">
-%@
-<div id="Chat">
-</div>
-%@
-</body>
-</html>
--- a/pidgin/plugins/adiumthemes/message-style.c	Sun Oct 09 07:10:36 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,429 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#include "message-style.h"
-
-#include <string.h>
-
-#include <glib.h>
-
-#include <debug.h>
-#include <util.h>
-
-static void
-glist_free_all_string(GList *list)
-{
-	for (; list; list = g_list_delete_link(list, list))
-		g_free(list->data);
-}
-
-static PidginMessageStyle *
-pidgin_message_style_new(const char *styledir)
-{
-	PidginMessageStyle *ret = g_new0(PidginMessageStyle, 1);
-
-	ret->ref_counter = 1;
-	ret->style_dir = g_strdup(styledir);
-
-	return ret;
-}
-
-void
-pidgin_message_style_unref(PidginMessageStyle *style)
-{
-	if (!style)
-		return;
-	g_assert (style->ref_counter > 0);
-
-	style->ref_counter--;
-	if (style->ref_counter)
-		return;
-
-	g_free(style->cf_bundle_name);
-	g_free(style->cf_bundle_identifier);
-	g_free(style->cf_bundle_get_info_string);
-	g_free(style->default_font_family);
-	g_free(style->default_background_color);
-	g_free(style->image_mask);
-	g_free(style->default_variant);
-
-	g_free(style->style_dir);
-	g_free(style->template_path);
-
-	g_free(style->template_html);
-	g_free(style->incoming_content_html);
-	g_free(style->outgoing_content_html);
-	g_free(style->outgoing_next_content_html);
-	g_free(style->status_html);
-	g_free(style->basestyle_css);
-
-	g_free(style);
-}
-
-void
-pidgin_message_style_save_state(const PidginMessageStyle *style)
-{
-	char *prefname = g_strdup_printf("/plugins/gtk/adiumthemes/%s", style->cf_bundle_identifier);
-	char *variant = g_strdup_printf("%s/variant", prefname);
-
-	purple_debug_info("webkit", "saving state with variant %s\n", style->variant);
-	purple_prefs_add_none(prefname);
-	purple_prefs_add_string(variant, "");
-	purple_prefs_set_string(variant, style->variant);
-
-	g_free(prefname);
-	g_free(variant);
-}
-
-static void
-pidgin_message_style_load_state(PidginMessageStyle *style)
-{
-	char *prefname = g_strdup_printf("/plugins/gtk/adiumthemes/%s", style->cf_bundle_identifier);
-	char *variant = g_strdup_printf("%s/variant", prefname);
-
-	const char* value = purple_prefs_get_string(variant);
-	gboolean changed = !style->variant || !g_str_equal(style->variant, value);
-
-	g_free(style->variant);
-	style->variant = g_strdup(value);
-
-	if (changed)
-		pidgin_message_style_read_info_plist(style, style->variant);
-
-	g_free(prefname);
-	g_free(variant);
-}
-
-
-static gboolean
-parse_info_plist_key_value(xmlnode* key, gpointer destination, const char* expected)
-{
-	xmlnode *val = key->next;
-
-	for (; val && val->type != XMLNODE_TYPE_TAG; val = val->next)
-		;
-	if (!val)
-		return FALSE;
-
-	if (expected == NULL || g_str_equal(expected, "string")) {
-		char **dest = (char **)destination;
-		if (!g_str_equal(val->name, "string"))
-			return FALSE;
-		if (*dest)
-			g_free(*dest);
-		*dest = xmlnode_get_data_unescaped(val);
-	} else if (g_str_equal(expected, "integer")) {
-		int *dest = (int *)destination;
-		char *value = xmlnode_get_data_unescaped(val);
-
-		if (!g_str_equal(val->name, "integer"))
-			return FALSE;
-		*dest = atoi(value);
-		g_free(value);
-	} else if (g_str_equal(expected, "boolean")) {
-		gboolean *dest = (gboolean *)destination;
-		if (g_str_equal(val->name, "true"))
-			*dest = TRUE;
-		else if (g_str_equal(val->name, "false"))
-			*dest = FALSE;
-		else
-			return FALSE;
-	} else return FALSE;
-
-	return TRUE;
-}
-
-static gboolean
-str_for_key(const char *key, const char *found, const char *variant)
-{
-	if (g_str_equal(key, found))
-		return TRUE;
-	if (!variant)
-		return FALSE;
-	return (g_str_has_prefix(found, key)
-		&& g_str_has_suffix(found, variant)
-		&& strlen(found) == strlen(key) + strlen(variant) + 1);
-}
-
-/**
- * Info.plist should be re-read every time the variant changes, this is because
- * the keys that take precedence depend on the value of the current variant.
- */
-void
-pidgin_message_style_read_info_plist(PidginMessageStyle *style, const char *variant)
-{
-	/* note that if a variant is used the option:VARIANTNAME takes precedence */
-	char *contents = g_build_filename(style->style_dir, "Contents", NULL);
-	xmlnode *plist = xmlnode_from_file(contents, "Info.plist", "Info.plist", "webkit"), *iter;
-	xmlnode *dict = xmlnode_get_child(plist, "dict");
-
-	g_assert (dict);
-	for (iter = xmlnode_get_child(dict, "key"); iter; iter = xmlnode_get_next_twin(iter)) {
-		char* key = xmlnode_get_data_unescaped(iter);
-		gboolean pr = TRUE;
-
-		if (g_str_equal("MessageViewVersion", key))
-			pr = parse_info_plist_key_value(iter, &style->message_view_version, "integer");
-		else if (g_str_equal("CFBundleName", key))
-			pr = parse_info_plist_key_value(iter, &style->cf_bundle_name, "string");
-		else if (g_str_equal("CFBundleIdentifier", key))
-			pr = parse_info_plist_key_value(iter, &style->cf_bundle_identifier, "string");
-		else if (g_str_equal("CFBundleGetInfoString", key))
-			pr = parse_info_plist_key_value(iter, &style->cf_bundle_get_info_string, "string");
-		else if (str_for_key("DefaultFontFamily", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->default_font_family, "string");
-		else if (str_for_key("DefaultFontSize", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->default_font_size, "integer");
-		else if (str_for_key("ShowsUserIcons", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->shows_user_icons, "boolean");
-		else if (str_for_key("DisableCombineConsecutive", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->disable_combine_consecutive, "boolean");
-		else if (str_for_key("DefaultBackgroundIsTransparent", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->default_background_is_transparent, "boolean");
-		else if (str_for_key("DisableCustomBackground", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->disable_custom_background, "boolean");
-		else if (str_for_key("DefaultBackgroundColor", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->default_background_color, "string");
-		else if (str_for_key("AllowTextColors", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->allow_text_colors, "integer");
-		else if (str_for_key("ImageMask", key, variant))
-			pr = parse_info_plist_key_value(iter, &style->image_mask, "string");
-
-		if (!pr)
-			purple_debug_warning("webkit", "Failed to parse key %s\n", key);
-		g_free(key);
-	}
-
-	xmlnode_free(plist);
-}
-
-PidginMessageStyle *
-pidgin_message_style_load(const char *styledir)
-{
-	/*
-	 * the loading process described:
-	 *
-	 * First we load all the style .html files, etc.
-	 * The we load any config options that have been stored for
-	 * this variant.
-	 * Then we load the Info.plist, for the currently decided variant.
-	 * At this point, if we find that variants exist, yet
-	 * we don't have a variant selected, we choose DefaultVariant
-	 * and if that does not exist, we choose the first one in the
-	 * directory.
-	 */
-	char *file;
-	PidginMessageStyle *style = NULL;
-
-	style = pidgin_message_style_new(styledir);
-
-	/* load all other files */
-
-	/* The template path can either come from the theme, or can
-	 * be stock Template.html that comes with the plugin */
-	style->template_path = g_build_filename(styledir, "Contents", "Resources", "Template.html", NULL);
-
-	if (!g_file_test(style->template_path, G_FILE_TEST_EXISTS)) {
-		g_free(style->template_path);
-		style->template_path = g_build_filename(DATADIR, "pidgin", "webkit", "Template.html", NULL);
-	}
-
-	if (!g_file_get_contents(style->template_path, &style->template_html, NULL, NULL)) {
-		purple_debug_error("webkit", "Could not locate a Template.html (%s)\n", style->template_path);
-		pidgin_message_style_unref(style);
-		return NULL;
-	}
-
-	file = g_build_filename(styledir, "Contents", "Resources", "Status.html", NULL);
-	if (!g_file_get_contents(file, &style->status_html, NULL, NULL)) {
-		purple_debug_info("webkit", "%s could not find Resources/Status.html", styledir);
-		pidgin_message_style_unref(style);
-		g_free(file);
-		return NULL;
-	}
-	g_free(file);
-
-	file = g_build_filename(styledir, "Contents", "Resources", "main.css", NULL);
-	if (!g_file_get_contents(file, &style->basestyle_css, NULL, NULL))
-		style->basestyle_css = g_strdup("");
-	g_free(file);
-
-	file = g_build_filename(styledir, "Contents", "Resources", "Header.html", NULL);
-	if (!g_file_get_contents(file, &style->header_html, NULL, NULL))
-		style->header_html = g_strdup("");
-	g_free(file);
-
-	file = g_build_filename(styledir, "Contents", "Resources", "Footer.html", NULL);
-	if (!g_file_get_contents(file, &style->footer_html, NULL, NULL))
-		style->footer_html = g_strdup("");
-	g_free(file);
-
-	file = g_build_filename(styledir, "Contents", "Resources", "Incoming", "Content.html", NULL);
-	if (!g_file_get_contents(file, &style->incoming_content_html, NULL, NULL)) {
-		purple_debug_info("webkit", "%s did not have a Incoming/Content.html\n", styledir);
-		pidgin_message_style_unref(style);
-		g_free(file);
-		return NULL;
-	}
-	g_free(file);
-
-
-	/* according to the spec, the following are optional files */
-	file = g_build_filename(styledir, "Contents", "Resources", "Incoming", "NextContent.html", NULL);
-	if (!g_file_get_contents(file, &style->incoming_next_content_html, NULL, NULL)) {
-		style->incoming_next_content_html = g_strdup(style->incoming_content_html);
-	}
-	g_free(file);
-
-	file = g_build_filename(styledir, "Contents", "Resources", "Outgoing", "Content.html", NULL);
-	if (!g_file_get_contents(file, &style->outgoing_content_html, NULL, NULL)) {
-		style->outgoing_content_html = g_strdup(style->incoming_content_html);
-	}
-	g_free(file);
-
-	file = g_build_filename(styledir, "Contents", "Resources", "Outgoing", "NextContent.html", NULL);
-	if (!g_file_get_contents(file, &style->outgoing_next_content_html, NULL, NULL)) {
-		style->outgoing_next_content_html = g_strdup(style->outgoing_content_html);
-	}
-
-	pidgin_message_style_read_info_plist(style, NULL);
-	pidgin_message_style_load_state(style);
-
-	/* non variant dependent Info.plist checks */
-	if (style->message_view_version < 3) {
-		purple_debug_info("webkit", "%s is a legacy style (version %d) and will not be loaded\n", style->cf_bundle_name, style->message_view_version);
-		pidgin_message_style_unref(style);
-		return NULL;
-	}
-
-	if (!style->variant)
-	{
-		GList *variants = pidgin_message_style_get_variants(style);
-
-		if (variants)
-			pidgin_message_style_set_variant(style, variants->data);
-
-		glist_free_all_string(variants);
-	}
-
-	return style;
-}
-
-PidginMessageStyle *
-pidgin_message_style_copy(const PidginMessageStyle *style)
-{
-	PidginMessageStyle *ret = pidgin_message_style_new(style->style_dir);
-
-	ret->variant = g_strdup(style->variant);
-	ret->message_view_version = style->message_view_version;
-	ret->cf_bundle_name = g_strdup(style->cf_bundle_name);
-	ret->cf_bundle_identifier = g_strdup(style->cf_bundle_identifier);
-	ret->cf_bundle_get_info_string = g_strdup(style->cf_bundle_get_info_string);
-	ret->default_font_family = g_strdup(style->default_font_family);
-	ret->default_font_size = style->default_font_size;
-	ret->shows_user_icons = style->shows_user_icons;
-	ret->disable_combine_consecutive = style->disable_combine_consecutive;
-	ret->default_background_is_transparent = style->default_background_is_transparent;
-	ret->disable_custom_background = style->disable_custom_background;
-	ret->default_background_color = g_strdup(style->default_background_color);
-	ret->allow_text_colors = style->allow_text_colors;
-	ret->image_mask = g_strdup(style->image_mask);
-	ret->default_variant = g_strdup(style->default_variant);
-
-	ret->template_path = g_strdup(style->template_path);
-	ret->template_html = g_strdup(style->template_html);
-	ret->header_html = g_strdup(style->header_html);
-	ret->footer_html = g_strdup(style->footer_html);
-	ret->incoming_content_html = g_strdup(style->incoming_content_html);
-	ret->outgoing_content_html = g_strdup(style->outgoing_content_html);
-	ret->incoming_next_content_html = g_strdup(style->incoming_next_content_html);
-	ret->outgoing_next_content_html = g_strdup(style->outgoing_next_content_html);
-	ret->status_html = g_strdup(style->status_html);
-	ret->basestyle_css = g_strdup(style->basestyle_css);
-	return ret;
-}
-
-void
-pidgin_message_style_set_variant(PidginMessageStyle *style, const char *variant)
-{
-	/* I'm not going to test whether this variant is valid! */
-	g_free(style->variant);
-	style->variant = g_strdup(variant);
-
-	pidgin_message_style_read_info_plist(style, variant);
-
-	/* todo, the style has "changed". Ideally, I would like to use signals at this point. */
-}
-
-char *
-pidgin_message_style_get_variant(PidginMessageStyle *style)
-{
-	return g_strdup(style->variant);
-}
-
-/**
- * Get a list of variants supported by the style.
- */
-GList*
-pidgin_message_style_get_variants(PidginMessageStyle *style)
-{
-	GList *ret = NULL;
-	GDir *variants;
-	const char *css_file;
-	char *css;
-	char *variant_dir;
-
-	g_assert(style->style_dir);
-	variant_dir = g_build_filename(style->style_dir, "Contents", "Resources", "Variants", NULL);
-
-	variants = g_dir_open(variant_dir, 0, NULL);
-	if (!variants)
-		return NULL;
-
-	while ((css_file = g_dir_read_name(variants)) != NULL) {
-		if (!g_str_has_suffix(css_file, ".css"))
-			continue;
-
-		css = g_strndup(css_file, strlen(css_file) - 4);
-		ret = g_list_append(ret, css);
-	}
-
-	g_dir_close(variants);
-	g_free(variant_dir);
-
-	ret = g_list_sort(ret, (GCompareFunc)g_strcmp0);
-	return ret;
-}
-
-char *
-pidgin_message_style_get_css(PidginMessageStyle *style)
-{
-	if (!style->variant) {
-		return g_build_filename(style->style_dir, "Contents", "Resources", "main.css", NULL);
-	} else {
-		char *file = g_strdup_printf("%s.css", style->variant);
-		char *ret = g_build_filename(style->style_dir, "Contents", "Resources", "Variants",  file, NULL);
-		g_free(file);
-		return ret;
-	}
-}
-
--- a/pidgin/plugins/adiumthemes/message-style.h	Sun Oct 09 07:10:36 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#include <glib.h>
-
-/*
- * I'm going to allow a different style for each PidginConversation.
- * This way I can do two things: 1) change the theme on the fly and not
- * change existing themes, and 2) Use a different theme for IMs and
- * chats.
- */
-typedef struct _PidginMessageStyle {
-	int     ref_counter;
-
-	/* current config options */
-	char     *variant; /* allowed to be NULL if there are no variants */
-
-	/* Info.plist keys that change with Variant */
-
-	/* Static Info.plist keys */
-	int      message_view_version;
-	char     *cf_bundle_name;
-	char     *cf_bundle_identifier;
-	char     *cf_bundle_get_info_string;
-	char     *default_font_family;
-	int      default_font_size;
-	gboolean shows_user_icons;
-	gboolean disable_combine_consecutive;
-	gboolean default_background_is_transparent;
-	gboolean disable_custom_background;
-	char     *default_background_color;
-	gboolean allow_text_colors;
-	char     *image_mask;
-	char     *default_variant;
-
-	/* paths */
-	char    *style_dir;
-	char    *template_path;
-
-	/* caches */
-	char    *template_html;
-	char    *header_html;
-	char    *footer_html;
-	char    *incoming_content_html;
-	char    *outgoing_content_html;
-	char    *incoming_next_content_html;
-	char    *outgoing_next_content_html;
-	char    *status_html;
-	char    *basestyle_css;
-} PidginMessageStyle;
-
-PidginMessageStyle *pidgin_message_style_load(const char *styledir);
-PidginMessageStyle *pidgin_message_style_copy(const PidginMessageStyle *style);
-void pidgin_message_style_save_state(const PidginMessageStyle *style);
-void pidgin_message_style_unref(PidginMessageStyle *style);
-void pidgin_message_style_read_info_plist(PidginMessageStyle *style, const char *variant);
-char *pidgin_message_style_get_variant(PidginMessageStyle *style);
-GList *pidgin_message_style_get_variants(PidginMessageStyle *style);
-void pidgin_message_style_set_variant(PidginMessageStyle *style, const char *variant);
-
-char *pidgin_message_style_get_css(PidginMessageStyle *style);
-
--- a/pidgin/plugins/adiumthemes/webkit.c	Sun Oct 09 07:10:36 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,858 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#define PLUGIN_ID		"gtk-webview-adium-ims"
-#define PLUGIN_NAME		"webview-adium-ims"
-
-/*
- * A lot of this was originally written by Sean Egan, but I think I've
- * rewrote enough to replace the author for now.
- */
-#define PLUGIN_AUTHOR		"Arnold Noronha <arnstein87@gmail.com>"
-#define PURPLE_PLUGINS		"Hell yeah"
-
-/* System headers */
-#include <string.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include <webkit/webkit.h>
-
-/* Purple headers */
-#include <conversation.h>
-#include <debug.h>
-#include <internal.h>
-#include <notify.h>
-#include <util.h>
-#include <version.h>
-
-/* Pidgin headers */
-#include <gtkconv.h>
-#include <gtkplugin.h>
-#include <gtkwebview.h>
-#include <smileyparser.h>
-
-#include <libxml/xmlreader.h>
-
-#include "message-style.h"
-/* GObject data keys */
-#define MESSAGE_STYLE_KEY "message-style"
-
-static char  *cur_style_dir = NULL;
-static void  *handle = NULL;
-
-static inline char *
-get_absolute_path(const char *path)
-{
-	if (g_path_is_absolute(path))
-		return g_strdup(path);
-	else {
-		char *cwd, *ret;
-		cwd = g_get_current_dir();
-		ret = g_build_filename(cwd, path, NULL);
-		g_free(cwd);
-		return ret;
-	}
-}
-
-static void webkit_on_webview_destroy(GtkObject* obj, gpointer data);
-
-static void *
-webkit_plugin_get_handle(void)
-{
-	if (handle)
-		return handle;
-	else
-		return (handle = g_malloc(1));
-}
-
-static void
-webkit_plugin_free_handle(void)
-{
-	purple_signals_disconnect_by_handle(handle);
-	g_free(handle);
-}
-
-static char *
-replace_message_tokens(
-	const char *text,
-	PurpleConversation *conv,
-	const char *name,
-	const char *alias,
-	const char *message,
-	PurpleMessageFlags flags,
-	time_t mtime)
-{
-	PurpleAccount *account = purple_conversation_get_account(conv);
-	GString *str = g_string_new(NULL);
-	const char *cur = text;
-	const char *prev = cur;
-
-	while ((cur = strchr(cur, '%'))) {
-		const char *replace = NULL;
-		char *fin = NULL;
-
-		if (!strncmp(cur, "%message%", strlen("%message%"))) {
-			replace = message;
-		} else if (!strncmp(cur, "%messageClasses%", strlen("%messageClasses%"))) {
-			replace = flags & PURPLE_MESSAGE_SEND ? "outgoing" :
-				  flags & PURPLE_MESSAGE_RECV ? "incoming" : "event";
-		} else if (!strncmp(cur, "%time", strlen("%time"))) {
-			char *format = NULL;
-			if (*(cur + strlen("%time")) == '{') {
-				const char *start = cur + strlen("%time") + 1;
-				char *end = strstr(start, "}%");
-				if (!end) /* Invalid string */
-					continue;
-				format = g_strndup(start, end - start);
-				fin = end + 1;
-			}
-			replace = purple_utf8_strftime(format ? format : "%X", NULL);
-			g_free(format);
-		} else if (!strncmp(cur, "%userIconPath%", strlen("%userIconPath%"))) {
-			if (flags & PURPLE_MESSAGE_SEND) {
-				if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) {
-					replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
-				} else {
-					PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
-					replace = purple_imgstore_get_filename(img);
-				}
-				if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
-					replace = g_build_filename("Outgoing", "buddy_icon.png", NULL);
-				}
-			} else if (flags & PURPLE_MESSAGE_RECV) {
-				PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
-				replace = purple_buddy_icon_get_full_path(icon);
-				if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) {
-					replace = g_build_filename("Incoming", "buddy_icon.png", NULL);
-				}
-			}
-
-		} else if (!strncmp(cur, "%senderScreenName%", strlen("%senderScreenName%"))) {
-			replace = name;
-		} else if (!strncmp(cur, "%sender%", strlen("%sender%"))) {
-			replace = alias;
-		} else if (!strncmp(cur, "%service%", strlen("%service%"))) {
-			replace = purple_account_get_protocol_name(account);
-		} else {
-			cur++;
-			continue;
-		}
-
-		/* Here we have a replacement to make */
-		g_string_append_len(str, prev, cur - prev);
-		g_string_append(str, replace);
-
-		/* And update the pointers */
-		if (fin) {
-			prev = cur = fin + 1;
-		} else {
-			prev = cur = strchr(cur + 1, '%') + 1;
-		}
-
-	}
-
-	/* And wrap it up */
-	g_string_append(str, prev);
-	return g_string_free(str, FALSE);
-}
-
-static char *
-replace_header_tokens(char *text, PurpleConversation *conv)
-{
-	PurpleAccount *account = purple_conversation_get_account(conv);
-	GString *str = g_string_new(NULL);
-	char *cur = text;
-	char *prev = cur;
-
-	if (text == NULL)
-		return NULL;
-
-	while ((cur = strchr(cur, '%'))) {
-		const char *replace = NULL;
-		char *fin = NULL;
-
-		if (!strncmp(cur, "%chatName%", strlen("%chatName%"))) {
-			replace = purple_conversation_get_name(conv);
-		} else if (!strncmp(cur, "%sourceName%", strlen("%sourceName%"))) {
-			replace = purple_account_get_alias(account);
-			if (replace == NULL)
-				replace = purple_account_get_username(account);
-		} else if (!strncmp(cur, "%destinationName%", strlen("%destinationName%"))) {
-			PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
-			if (buddy) {
-				replace = purple_buddy_get_alias(buddy);
-			} else {
-				replace = purple_conversation_get_name(conv);
-			}
-		} else if (!strncmp(cur, "%incomingIconPath%", strlen("%incomingIconPath%"))) {
-			PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
-			replace = purple_buddy_icon_get_full_path(icon);
-		} else if (!strncmp(cur, "%outgoingIconPath%", strlen("%outgoingIconPath%"))) {
-		} else if (!strncmp(cur, "%timeOpened", strlen("%timeOpened"))) {
-			char *format = NULL;
-			if (*(cur + strlen("%timeOpened")) == '{') {
-				char *start = cur + strlen("%timeOpened") + 1;
-				char *end = strstr(start, "}%");
-				if (!end) /* Invalid string */
-					continue;
-				format = g_strndup(start, end - start);
-				fin = end + 1;
-			}
-			replace = purple_utf8_strftime(format ? format : "%X", NULL);
-			g_free(format);
-		} else {
-			continue;
-		}
-
-		/* Here we have a replacement to make */
-		g_string_append_len(str, prev, cur - prev);
-		g_string_append(str, replace);
-
-		/* And update the pointers */
-		if (fin) {
-			prev = cur = fin + 1;
-		} else {
-			prev = cur = strchr(cur + 1, '%') + 1;
-		}
-	}
-
-	/* And wrap it up */
-	g_string_append(str, prev);
-	return g_string_free(str, FALSE);
-}
-
-static char *
-replace_template_tokens(PidginMessageStyle *style, char *text, char *header, char *footer)
-{
-	GString *str = g_string_new(NULL);
-
-	char **ms = g_strsplit(text, "%@", 6);
-	char *base = NULL;
-	char *csspath = pidgin_message_style_get_css(style);
-	if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) {
-		g_strfreev(ms);
-		g_string_free(str, TRUE);
-		return NULL;
-	}
-
-	g_string_append(str, ms[0]);
-	g_string_append(str, "file://");
-	base = g_build_filename(style->style_dir, "Contents", "Resources", "Template.html", NULL);
-	g_string_append(str, base);
-	g_free(base);
-
-	g_string_append(str, ms[1]);
-
-	g_string_append(str, style->basestyle_css);
-
-	g_string_append(str, ms[2]);
-
-	g_string_append(str, "file://");
-	g_string_append(str, csspath);
-
-	g_string_append(str, ms[3]);
-	if (header)
-		g_string_append(str, header);
-	g_string_append(str, ms[4]);
-	if (footer)
-		g_string_append(str, footer);
-	g_string_append(str, ms[5]);
-
-	g_strfreev(ms);
-	g_free(csspath);
-	return g_string_free(str, FALSE);
-}
-
-static GtkWidget *
-get_webkit(PurpleConversation *conv)
-{
-	PidginConversation *gtkconv;
-	gtkconv = PIDGIN_CONVERSATION(conv);
-	if (!gtkconv)
-		return NULL;
-	else
-		return gtkconv->webview;
-}
-
-static void
-set_theme_webkit_settings(WebKitWebView *webview, PidginMessageStyle *style)
-{
-	WebKitWebSettings *settings;
-
-	g_object_get(G_OBJECT(webview), "settings", &settings, NULL);
-	if (style->default_font_family)
-		g_object_set(G_OBJECT(settings), "default-font-family", style->default_font_family, NULL);
-
-	if (style->default_font_size)
-		g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(style->default_font_size), NULL);
-
-	/* this does not work :( */
-	webkit_web_view_set_transparent(webview, style->default_background_is_transparent);
-}
-
-/*
- * The style specification says that if the conversation is a group
- * chat then the <div id="Chat"> element will be given a class
- * 'groupchat'. I can't add another '%@' in Template.html because
- * that breaks style-specific Template.html's. I have to either use libxml
- * or conveniently play with WebKit's javascript engine. The javascript
- * engine should work, but it's not an identical behavior.
- */
-static void
-webkit_set_groupchat(GtkWebView *webview)
-{
-	gtk_webview_safe_execute_script(webview, "document.getElementById('Chat').className = 'groupchat'");
-}
-
-
-/**
- * Called when either a new PurpleConversation is created
- * or when a PidginConversation changes its active PurpleConversation
- * This will not change the theme if the theme is already set.
- * (This is to prevent accidental theme changes if a new
- * PurpleConversation gets added.
- *
- * FIXME: it's not at all clear to me as to how
- * Adium themes handle the case when the PurpleConversation
- * changes.
- */
-static void
-init_theme_for_webkit(PurpleConversation *conv, char *style_dir)
-{
-	GtkWidget *webkit = PIDGIN_CONVERSATION(conv)->webview;
-	char *header, *footer;
-	char *template;
-
-	char* basedir;
-	char* baseuri;
-	PidginMessageStyle *style, *oldStyle;
-	PidginMessageStyle *copy;
-
-	oldStyle = g_object_get_data(G_OBJECT(webkit), MESSAGE_STYLE_KEY);
-	if (oldStyle)
-		return;
-
-	purple_debug_info("webkit", "loading %s\n", style_dir);
-	style = pidgin_message_style_load(style_dir);
-	g_assert(style);
-	g_assert(style->template_html); /* debugging test? */
-
-	basedir = g_build_filename(style->style_dir, "Contents", "Resources", "Template.html", NULL);
-	baseuri = g_strdup_printf("file://%s", basedir);
-	header = replace_header_tokens(style->header_html, conv);
-	g_assert(style);
-	footer = replace_header_tokens(style->footer_html, conv);
-	template = replace_template_tokens(style, style->template_html, header, footer);
-
-	g_assert(template);
-
-	purple_debug_info("webkit", "template: %s\n", template);
-
-	set_theme_webkit_settings(WEBKIT_WEB_VIEW(webkit), style);
-	webkit_web_view_load_string(WEBKIT_WEB_VIEW(webkit), template, "text/html", "UTF-8", baseuri);
-
-	copy = pidgin_message_style_copy(style);
-	g_object_set_data(G_OBJECT(webkit), MESSAGE_STYLE_KEY, copy);
-
-	pidgin_message_style_unref(style);
-	/* I need to unref this style when the webkit object destroys */
-	g_signal_connect(G_OBJECT(webkit), "destroy", G_CALLBACK(webkit_on_webview_destroy), copy);
-
-	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
-		webkit_set_groupchat(GTK_WEBVIEW(webkit));
-	g_free(basedir);
-	g_free(baseuri);
-	g_free(header);
-	g_free(footer);
-	g_free(template);
-}
-
-
-/* restore the non theme version of the conversation window */
-static void
-finalize_theme_for_webkit(PurpleConversation *conv)
-{
-	GtkWidget *webview = PIDGIN_CONVERSATION(conv)->webview;
-	PidginMessageStyle *style = g_object_get_data(G_OBJECT(webview), MESSAGE_STYLE_KEY);
-
-	webkit_web_view_load_string(WEBKIT_WEB_VIEW(webview), "", "text/html", "UTF-8", "");
-
-	g_object_set_data(G_OBJECT(webview), MESSAGE_STYLE_KEY, NULL);
-	pidgin_message_style_unref(style);
-}
-
-static void
-webkit_on_webview_destroy(GtkObject *object, gpointer data)
-{
-	pidgin_message_style_unref((PidginMessageStyle *)data);
-	g_object_set_data(G_OBJECT(object), MESSAGE_STYLE_KEY, NULL);
-}
-
-static gboolean
-webkit_on_displaying_im_msg(PurpleAccount *account,
-						 const char* name,
-						 char **pmessage,
-						 PurpleConversation *conv,
-						 PurpleMessageFlags flags,
-						 gpointer data)
-{
-	GtkWidget *webkit;
-	char *message = *pmessage;
-	const char *alias = name; /* FIXME: signal doesn't give me alias */
-	char *stripped;
-	char *message_html;
-	char *msg;
-	char *escape;
-	char *script;
-	char *func = "appendMessage";
-	char *smileyed;
-	time_t mtime = time(NULL); /* FIXME: this should come from the write_conv calback, but the signal doesn't pass this to me */
-
-	PurpleMessageFlags old_flags = GPOINTER_TO_INT(purple_conversation_get_data(conv, "webkit-lastflags"));
-	PidginMessageStyle *style;
-
-	webkit = get_webkit(conv);
-	stripped = g_strdup(message);
-
-	style = g_object_get_data(G_OBJECT(webkit), MESSAGE_STYLE_KEY);
-	g_assert(style);
-
-	if (flags & PURPLE_MESSAGE_SEND && old_flags & PURPLE_MESSAGE_SEND) {
-		message_html = style->outgoing_next_content_html;
-		func = "appendNextMessage";
-	} else if (flags & PURPLE_MESSAGE_SEND) {
-		message_html = style->outgoing_content_html;
-	} else if (flags & PURPLE_MESSAGE_RECV && old_flags & PURPLE_MESSAGE_RECV) {
-		message_html = style->incoming_next_content_html;
-		func = "appendNextMessage";
-	} else if (flags & PURPLE_MESSAGE_RECV) {
-		message_html = style->incoming_content_html;
-	} else {
-		message_html = style->status_html;
-	}
-	purple_conversation_set_data(conv, "webkit-lastflags", GINT_TO_POINTER(flags));
-
-	smileyed = smiley_parse_markup(stripped, purple_account_get_protocol_id(purple_conversation_get_account(conv)));
-	msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime);
-	escape = gtk_webview_quote_js_string(msg);
-	script = g_strdup_printf("%s(%s)", func, escape);
-
-	purple_debug_info("webkit", "JS: %s\n", script);
-	gtk_webview_safe_execute_script(GTK_WEBVIEW(webkit), script);
-
-	g_free(script);
-	g_free(smileyed);
-	g_free(msg);
-	g_free(stripped);
-	g_free(escape);
-
-	return TRUE; /* GtkConv should not handle this IM */
-}
-
-static gboolean
-webkit_on_displaying_chat_msg(PurpleAccount *account,
-					       const char *who,
-					       char **message,
-					       PurpleConversation *conv,
-					       PurpleMessageFlags flags,
-					       gpointer userdata)
-{
-	/* handle exactly like an IM message for now */
-	return webkit_on_displaying_im_msg(account, who, message, conv, flags, NULL);
-}
-
-static void
-webkit_on_conversation_displayed(PidginConversation *gtkconv, gpointer data)
-{
-	init_theme_for_webkit(gtkconv->active_conv, cur_style_dir);
-}
-
-static void
-webkit_on_conversation_switched(PurpleConversation *conv, gpointer data)
-{
-	init_theme_for_webkit(conv, cur_style_dir);
-}
-
-static void
-webkit_on_conversation_hiding(PidginConversation *gtkconv, gpointer data)
-{
-	/*
-	 * I'm not sure if I need to do anything here, but let's keep
-	 * this anyway.
-	 */
-}
-
-static GList *
-get_dir_dir_list(const char *dirname)
-{
-	GList *ret = NULL;
-	GDir  *dir = g_dir_open(dirname, 0, NULL);
-	const char* subdir;
-
-	if (!dir) return NULL;
-	while ((subdir = g_dir_read_name(dir))) {
-		ret = g_list_append(ret, g_build_filename(dirname, subdir, NULL));
-	}
-
-	g_dir_close(dir);
-	return ret;
-}
-
-/**
- * Get me a list of all the available themes specified by their
- * directories. I don't guarrantee that these are valid themes, just
- * that they are in the directories for themes.
- */
-static GList *
-get_style_directory_list(void)
-{
-	char *user_dir, *user_style_dir, *global_style_dir;
-	GList *list1, *list2;
-
-	user_dir = get_absolute_path(purple_user_dir());
-
-	user_style_dir = g_build_filename(user_dir, "styles", NULL);
-	global_style_dir = g_build_filename(DATADIR, "pidgin", "styles", NULL);
-
-	list1 = get_dir_dir_list(user_style_dir);
-	list2 = get_dir_dir_list(global_style_dir);
-
-	g_free(global_style_dir);
-	g_free(user_style_dir);
-	g_free(user_dir);
-
-	return g_list_concat(list1, list2);
-}
-
-/**
- * use heuristics or previous user options to figure out what
- * theme to use as default in this Pidgin instance.
- */
-static void
-style_set_default(void)
-{
-	GList *styles = get_style_directory_list(), *iter;
-	const char *stylepath = purple_prefs_get_string("/plugins/gtk/adiumthemes/stylepath");
-	g_assert(cur_style_dir == NULL);
-
-	if (stylepath && *stylepath)
-		styles = g_list_prepend(styles, g_strdup(stylepath));
-
-	/* pick any one that works. Note that we have first preference
-	 * for the one in the userdir */
-	for (iter = styles; iter; iter = g_list_next(iter)) {
-		PidginMessageStyle *style = pidgin_message_style_load(iter->data);
-		if (style) {
-			cur_style_dir = (char *)g_strdup(iter->data);
-			pidgin_message_style_unref(style);
-			break;
-		}
-		purple_debug_info("webkit", "Style %s is invalid\n", (char *)iter->data);
-	}
-
-	for (iter = styles; iter; iter = g_list_next(iter))
-		g_free(iter->data);
-	g_list_free(styles);
-}
-
-static gboolean
-plugin_load(PurplePlugin *plugin)
-{
-	style_set_default();
-	if (!cur_style_dir)
-		return FALSE; /* couldn't find a style */
-
-	purple_signal_connect(pidgin_conversations_get_handle(),
-			       "displaying-im-msg",
-			       webkit_plugin_get_handle(),
-			       PURPLE_CALLBACK(webkit_on_displaying_im_msg),
-			       NULL);
-
-	purple_signal_connect(pidgin_conversations_get_handle(),
-			       "displaying-chat-msg",
-			       webkit_plugin_get_handle(),
-			       PURPLE_CALLBACK(webkit_on_displaying_chat_msg),
-			       NULL);
-
-	purple_signal_connect(pidgin_conversations_get_handle(),
-			       "conversation-displayed",
-			       webkit_plugin_get_handle(),
-			       PURPLE_CALLBACK(webkit_on_conversation_displayed),
-			       NULL);
-
-	purple_signal_connect(pidgin_conversations_get_handle(),
-			       "conversation-switched",
-			       webkit_plugin_get_handle(),
-			       PURPLE_CALLBACK(webkit_on_conversation_switched),
-			       NULL);
-
-	purple_signal_connect(pidgin_conversations_get_handle(),
-			       "conversation-hiding",
-			       webkit_plugin_get_handle(),
-			       PURPLE_CALLBACK(webkit_on_conversation_hiding),
-			       NULL);
-
-	/* finally update each of the existing conversation windows */
-	{
-		GList *list = purple_get_conversations();
-		for (;list; list = g_list_next(list))
-			init_theme_for_webkit(list->data, cur_style_dir);
-
-	}
-	return TRUE;
-}
-
-static gboolean
-plugin_unload(PurplePlugin *plugin)
-{
-	GList *list;
-
-	webkit_plugin_free_handle();
-	cur_style_dir = NULL;
-	list = purple_get_conversations();
-	while (list) {
-		finalize_theme_for_webkit(list->data);
-		list = g_list_next(list);
-	}
-
-	return TRUE;
-}
-
-/*
- * UI config code
- */
-
-static void
-style_changed(GtkWidget *combobox, gpointer null)
-{
-	char *name = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combobox));
-	GtkWidget *dialog;
-	GList *styles = get_style_directory_list(), *iter;
-
-	/* find the full path for this name, I wish I could store this info in the combobox itself. :( */
-	for (iter = styles; iter; iter = g_list_next(iter)) {
-		char *basename = g_path_get_basename(iter->data);
-		if (g_str_equal(basename, name)) {
-			g_free(basename);
-			break;
-		}
-		g_free(basename);
-	}
-
-	g_assert(iter);
-	g_free(name);
-	g_free(cur_style_dir);
-	cur_style_dir = g_strdup(iter->data);;
-	purple_prefs_set_string("/plugins/gtk/adiumthemes/stylepath", cur_style_dir);
-
-	/* inform the user that existing conversations haven't changed */
-	dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "The style for existing conversations have not been changed. Please close and re-open the conversation for the changes to take effect.");
-	g_assert(dialog);
-	gtk_widget_show(dialog);
-	g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
-}
-
-static GtkWidget *
-get_style_config_frame(void)
-{
-	GtkWidget *combobox = gtk_combo_box_new_text();
-	GList *styles = get_style_directory_list(), *iter;
-	int index = 0, selected = 0;
-
-	for (iter = styles; iter; iter = g_list_next(iter)) {
-		PidginMessageStyle *style = pidgin_message_style_load(iter->data);
-
-		if (style) {
-			char *text = g_path_get_basename(iter->data);
-			gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), text);
-			g_free(text);
-
-			if (g_str_equal(iter->data, cur_style_dir))
-				selected = index;
-			index++;
-			pidgin_message_style_unref(style);
-		}
-	}
-	gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), selected);
-	g_signal_connect_after(G_OBJECT(combobox), "changed", G_CALLBACK(style_changed), NULL);
-	return combobox;
-}
-
-static void
-variant_update_conversation(PurpleConversation *conv)
-{
-	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
-	WebKitWebView *webview = WEBKIT_WEB_VIEW(gtkconv->webview);
-	PidginMessageStyle *style = (PidginMessageStyle *)g_object_get_data(G_OBJECT(webview), MESSAGE_STYLE_KEY);
-	char *script;
-
-	g_assert(style);
-
-	script = g_strdup_printf("setStylesheet(\"mainStyle\",\"%s\")", pidgin_message_style_get_css(style));
-	gtk_webview_safe_execute_script(GTK_WEBVIEW(webview), script);
-
-	set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), style);
-	g_free(script);
-}
-
-static void
-variant_changed(GtkWidget* combobox, gpointer null)
-{
-	char *name;
-	GList *list;
-	PidginMessageStyle *style = pidgin_message_style_load(cur_style_dir);
-
-	g_assert(style);
-	name = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combobox));
-	pidgin_message_style_set_variant(style, name);
-	pidgin_message_style_save_state(style);
-
-	/* update conversations */
-	list = purple_get_conversations();
-	while (list) {
-		variant_update_conversation(list->data);
-		list = g_list_next(list);
-	}
-
-	g_free(name);
-	pidgin_message_style_unref(style);
-}
-
-static GtkWidget *
-get_variant_config_frame()
-{
-	PidginMessageStyle *style = pidgin_message_style_load(cur_style_dir);
-	GList *variants = pidgin_message_style_get_variants(style), *iter;
-	char *cur_variant = pidgin_message_style_get_variant(style);
-	GtkWidget *combobox = gtk_combo_box_new_text();
-	int def = -1, index = 0;
-
-	pidgin_message_style_unref(style);
-
-	for (iter = variants; iter; iter = g_list_next(iter)) {
-		gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), iter->data);
-
-		if (g_str_equal(cur_variant, iter->data))
-			def = index;
-		index ++;
-
-	}
-
-	gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), def);
-	g_signal_connect(G_OBJECT(combobox), "changed", G_CALLBACK(variant_changed), NULL);
-
-	return combobox;
-}
-
-static void
-style_changed_reset_variants(GtkWidget* combobox, gpointer table)
-{
-	/* I hate to do this, I swear. But I don't know how to cleanly clean an existing combobox */
-	GtkWidget* variants = g_object_get_data(G_OBJECT(table), "variants-cbox");
-	gtk_widget_destroy(variants);
-	variants = get_variant_config_frame();
-	gtk_table_attach_defaults(GTK_TABLE(table), variants, 1, 2, 1, 2);
-	gtk_widget_show_all(GTK_WIDGET(table));
-
-	g_object_set_data(G_OBJECT(table), "variants-cbox", variants);
-}
-
-static GtkWidget*
-get_config_frame(PurplePlugin* plugin)
-{
-	GtkWidget *table = gtk_table_new(2, 2, FALSE);
-	GtkWidget *style_config = get_style_config_frame();
-	GtkWidget *variant_config = get_variant_config_frame();
-
-	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new("Message Style"), 0, 1, 0, 1);
-	gtk_table_attach_defaults(GTK_TABLE(table), style_config, 1, 2, 0, 1);
-	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new("Style Variant"), 0, 1, 1, 2);
-	gtk_table_attach_defaults(GTK_TABLE(table), variant_config, 1, 2, 1, 2);
-
-	g_object_set_data(G_OBJECT(table), "variants-cbox", variant_config);
-	/* to clarify, this is a second signal connected on style config */
-	g_signal_connect_after(G_OBJECT(style_config), "changed", G_CALLBACK(style_changed_reset_variants), table);
-
-	return table;
-}
-
-PidginPluginUiInfo ui_info =
-{
-        get_config_frame,
-        0, /* page_num (Reserved) */
-
-        /* padding */
-        NULL,
-        NULL,
-        NULL,
-        NULL
-};
-
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,		/* Magic				*/
-	PURPLE_MAJOR_VERSION,		/* Purple Major Version	*/
-	PURPLE_MINOR_VERSION,		/* Purple Minor Version	*/
-	PURPLE_PLUGIN_STANDARD,		/* plugin type			*/
-	PIDGIN_PLUGIN_TYPE,			/* ui requirement		*/
-	0,							/* flags				*/
-	NULL,						/* dependencies			*/
-	PURPLE_PRIORITY_DEFAULT,	/* priority				*/
-
-	PLUGIN_ID,					/* plugin id			*/
-	NULL,						/* name					*/
-	"0.1",					/* version				*/
-	NULL,						/* summary				*/
-	NULL,						/* description			*/
-	PLUGIN_AUTHOR,				/* author				*/
-	"http://pidgin.im",					/* website				*/
-
-	plugin_load,				/* load					*/
-	plugin_unload,				/* unload				*/
-	NULL,						/* destroy				*/
-
-	&ui_info,						/* ui_info				*/
-	NULL,						/* extra_info			*/
-	NULL,						/* prefs_info			*/
-	NULL,						/* actions				*/
-	NULL,						/* reserved 1			*/
-	NULL,						/* reserved 2			*/
-	NULL,						/* reserved 3			*/
-	NULL						/* reserved 4			*/
-};
-
-static void
-init_plugin(PurplePlugin *plugin) {
-	info.name = "Adium IMs";
-	info.summary = "Adium-like IMs with Pidgin";
-	info.description = "You can chat in Pidgin using Adium's WebKit view.";
-
-	purple_prefs_add_none("/plugins");
-	purple_prefs_add_none("/plugins/gtk");
-	purple_prefs_add_none("/plugins/gtk/adiumthemes");
-	purple_prefs_add_string("/plugins/gtk/adiumthemes/stylepath", "");
-}
-
-PURPLE_INIT_PLUGIN(webkit, init_plugin, info)
-
--- a/pidgin/plugins/musicmessaging/musicmessaging.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/plugins/musicmessaging/musicmessaging.c	Fri Dec 23 06:58:52 2011 +0000
@@ -466,14 +466,14 @@
 
 static void send_request(MMConversation *mmconv)
 {
-	PurpleConnection *connection = purple_conversation_get_gc(mmconv->conv);
+	PurpleConnection *connection = purple_conversation_get_connection(mmconv->conv);
 	const char *convName = purple_conversation_get_name(mmconv->conv);
 	serv_send_im(connection, convName, MUSICMESSAGING_START_MSG, PURPLE_MESSAGE_SEND);
 }
 
 static void send_request_confirmed(MMConversation *mmconv)
 {
-	PurpleConnection *connection = purple_conversation_get_gc(mmconv->conv);
+	PurpleConnection *connection = purple_conversation_get_connection(mmconv->conv);
 	const char *convName = purple_conversation_get_name(mmconv->conv);
 	serv_send_im(connection, convName, MUSICMESSAGING_CONFIRM_MSG, PURPLE_MESSAGE_SEND);
 }
--- a/pidgin/plugins/vvconfig.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/plugins/vvconfig.c	Fri Dec 23 06:58:52 2011 +0000
@@ -39,6 +39,7 @@
 	/* "esdmon",	"ESD", ? */
 	"osssrc",	"OSS",
 	"pulsesrc",	"PulseAudio",
+	"libsndiosrc",	"sndio",
 	/* "audiotestsrc wave=silence", "Silence", */
 	"audiotestsrc",	"Test Sound",
 	NULL
@@ -50,6 +51,7 @@
 	"esdsink",	"ESD",
 	"osssink",	"OSS",
 	"pulsesink",	"PulseAudio",
+	"libsndiosink",	"sndio",
 	NULL
 };
 
@@ -610,7 +612,7 @@
 			GstElement *valve;
 
 			percent = gst_msg_db_to_percent(msg, "rms");
-			gtk_progress_bar_set_fraction(ctx->level, percent * 5);
+			gtk_progress_bar_set_fraction(ctx->level, percent);
 
 			percent = gst_msg_db_to_percent(msg, "decay");
 			threshold = gtk_range_get_value(ctx->threshold) / 100.0;
--- a/pidgin/plugins/xmppconsole.c	Sun Oct 09 07:10:36 2011 +0000
+++ b/pidgin/plugins/xmppconsole.c	Fri Dec 23 06:58:52 2011 +0000
@@ -190,7 +190,7 @@
 	gc = console->gc;
 
 	if (gc)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(console->entry));
 	gtk_text_buffer_get_start_iter(buffer, &start);
@@ -649,7 +649,7 @@
 	if (!console)
 		return;
 
-	gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown), purple_account_get_username(gc->account));
+	gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown), purple_account_get_username(purple_connection_get_account(gc)));
 	console->accounts = g_list_append(console->accounts, gc);
 	console->count++;
 
@@ -799,14 +799,17 @@
 
 	toolbar = gtk_toolbar_new();
 	button = gtk_tool_button_new(NULL, "<iq/>");
+	gtk_tool_item_set_is_important(button, TRUE);
 	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(iq_clicked_cb), NULL);
 	gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(button));
 
 	button = gtk_tool_button_new(NULL, "<presence/>");
+	gtk_tool_item_set_is_important(button, TRUE);
 	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(presence_clicked_cb), NULL);
 	gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(button));
 
 	button = gtk_tool_button_new(NULL, "<message/>");
+	gtk_tool_item_set_is_important(button, TRUE);
 	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(message_clicked_cb), NULL);
 	gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(button));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/themes/Makefile.am	Fri Dec 23 06:58:52 2011 +0000
@@ -0,0 +1,6 @@
+
+themetemplatedir = $(datadir)/pidgin/theme/conversation
+themetemplate_DATA = Template.html
+
+EXTRA_DIST = $(themetemplate_DATA)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/themes/Template.html	Fri Dec 23 06:58:52 2011 +0000
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<base href="%@">
+	<script type="text/ecmascript" defer="defer">
+	
+		//Appending new content to the message view
+		function appendMessage(html) {
+			shouldScroll = nearBottom();
+		
+			//Remove any existing insertion point
+			insert = document.getElementById("insert");
+			if(insert) insert.parentNode.removeChild(insert);
+
+			//Append the new message to the bottom of our chat block
+			chat = document.getElementById("Chat");
+			range = document.createRange();
+			range.selectNode(chat);
+			documentFragment = range.createContextualFragment(html);
+			chat.appendChild(documentFragment);
+			
+			alignChat(shouldScroll);
+		}
+		function appendMessageNoScroll(html) {
+			//Remove any existing insertion point
+			insert = document.getElementById("insert");
+			if(insert) insert.parentNode.removeChild(insert);
+
+			//Append the new message to the bottom of our chat block
+			chat = document.getElementById("Chat");
+			range = document.createRange();
+			range.selectNode(chat);
+			documentFragment = range.createContextualFragment(html);
+			chat.appendChild(documentFragment);
+		}
+		function appendNextMessage(html){
+			shouldScroll = nearBottom();
+
+			//Locate the insertion point
+			insert = document.getElementById("insert");
+		
+			//make new node
+			range = document.createRange();
+			range.selectNode(insert.parentNode);
+			newNode = range.createContextualFragment(html);
+
+			//swap
+			insert.parentNode.replaceChild(newNode,insert);
+			
+			alignChat(shouldScroll);
+		}
+		function appendNextMessageNoScroll(html){
+			//Locate the insertion point
+			insert = document.getElementById("insert");
+		
+			//make new node
+			range = document.createRange();
+			range.selectNode(insert.parentNode);
+			newNode = range.createContextualFragment(html);
+
+			//swap
+			insert.parentNode.replaceChild(newNode,insert);
+		}
+		
+		//Auto-scroll to bottom.  Use nearBottom to determine if a scrollToBottom is desired.
+		function nearBottom() {
+			return ( document.body.scrollTop >= ( document.body.offsetHeight - ( window.innerHeight * 1.2 ) ) );
+		}
+		function scrollToBottom() {
+			document.body.scrollTop = document.body.offsetHeight;
+		}
+
+		//Dynamically exchange the active stylesheet
+		function setStylesheet( id, url ) {
+			code = "<style id=\"" + id + "\" type=\"text/css\" media=\"screen,print\">";
+			if( url.length ) code += "@import url( \"" + url + "\" );";
+			code += "</style>";
+			range = document.createRange();
+			head = document.getElementsByTagName( "head" ).item(0);
+			range.selectNode( head );
+			documentFragment = range.createContextualFragment( code );
+			head.removeChild( document.getElementById( id ) );
+			head.appendChild( documentFragment );
+		}
+		
+		//Swap an image with its alt-tag text on click, or expand/unexpand an attached image
+		document.onclick = imageCheck;
+		function imageCheck() {		
+			node = event.target;
+			if(node.tagName == 'IMG' && !client.zoomImage(node) && node.alt) {
+				a = document.createElement('a');
+				a.setAttribute('onclick', 'imageSwap(this)');
+				a.setAttribute('src', node.getAttribute('src'));
+				a.className = node.className;
+				text = document.createTextNode(node.alt);
+				a.appendChild(text);
+				node.parentNode.replaceChild(a, node);
+			}
+		}
+
+		function imageSwap(node) {
+			shouldScroll = nearBottom();
+
+			//Swap the image/text
+			img = document.createElement('img');
+			img.setAttribute('src', node.getAttribute('src'));
+			img.setAttribute('alt', node.firstChild.nodeValue);
+			img.className = node.className;
+			node.parentNode.replaceChild(img, node);
+			
+			alignChat(shouldScroll);
+		}
+		
+		//Align our chat to the bottom of the window.  If true is passed, view will also be scrolled down
+		function alignChat(shouldScroll) {
+			var windowHeight = window.innerHeight;
+			
+			if (windowHeight > 0) {
+				var contentElement = document.getElementById('Chat');
+				var contentHeight = contentElement.offsetHeight;
+				if (windowHeight - contentHeight > 0) {
+					contentElement.style.position = 'relative';
+					contentElement.style.top = (windowHeight - contentHeight) + 'px';
+				} else {
+					contentElement.style.position = 'static';
+				}
+			}
+			
+			if (shouldScroll) scrollToBottom();
+		}
+		
+		function windowDidResize(){
+			alignChat(true/*nearBottom()*/); //nearBottom buggy with inactive tabs
+		}
+		
+		window.onresize = windowDidResize;
+	</script>
+	
+	<style type="text/css">
+		.actionMessageUserName:before { content:"*"; }
+		.actionMessageBody:after { content:"*"; }
+		*{ word-wrap:break-word; }
+		img.scaledToFitImage { height:auto; width:100%; }
+	</style>
+	
+	<!-- This style is shared by all variants. !-->
+	<style id="baseStyle" type="text/css" media="screen,print">	
+		%@
+	</style>
+	
+	<!-- Although we call this mainStyle for legacy reasons, it's actually the variant style !-->
+	<style id="mainStyle" type="text/css" media="screen,print">	
+		@import url( "%@" );
+	</style>
+
+</head>
+<body onload="alignChat(true);" style="==bodyBackground==">
+%@
+<div id="Chat">
+</div>
+%@
+</body>
+</html>
--- a/po/ChangeLog	Sun Oct 09 07:10:36 2011 +0000
+++ b/po/ChangeLog	Fri Dec 23 06:58:52 2011 +0000
@@ -1,5 +1,8 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.10.1
+	* No changes
+
 version 2.10.0
 	* Afrikaans translation updated (Friedel Wolff)
 	* Albanian translation updated (Besnik Bleta)
--- a/po/de.po	Sun Oct 09 07:10:36 2011 +0000
+++ b/po/de.po	Fri Dec 23 06:58:52 2011 +0000
@@ -11,9 +11,9 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-08-11 10:27+0200\n"
-"PO-Revision-Date: 2011-08-11 10:12+0200\n"
-"Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
+"POT-Creation-Date: 2011-12-11 10:41+0100\n"
+"PO-Revision-Date: 2011-12-11 10:40+0100\n"
+"Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: German <de@li.org>\n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
@@ -50,17 +50,6 @@
 "  -n, --nologin       nicht automatisch anmelden\n"
 "  -v, --version       zeigt aktuelle Version und beendet das Programm\n"
 
-#, c-format
-msgid ""
-"%s encountered errors migrating your settings from %s to %s. Please "
-"investigate and complete the migration by hand. Please report this error at "
-"http://developer.pidgin.im"
-msgstr ""
-"%s ist beim Übertragen Ihrer Einstellungen von %s nach %s auf Fehler "
-"gestoßen. Bitte untersuchen Sie das Problem und vervollständigen Sie die "
-"Migration per Hand. Bitte melden Sie diesen Fehler auf http://developer."
-"pidgin.im"
-
 #. the user did not fill in the captcha
 msgid "Error"
 msgstr "Fehler"
@@ -213,6 +202,8 @@
 msgid "Error adding buddy"
 msgstr "Fehler beim Hinzufügen des Buddys"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Username"
 msgstr "Benutzer"
 
@@ -346,7 +337,11 @@
 msgid "View Log"
 msgstr "Mitschnitt anzeigen"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 #. General
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Nickname"
 msgstr "Spitzname"
 
@@ -800,7 +795,11 @@
 msgstr "Verbleibend"
 
 #. XXX: Use of ggp_str_to_uin() is an ugly hack!
+#. TODO: Check whether it's correct to call prepend_pair_html,
+#. or if we should be using prepend_pair_plaintext
 #. presence
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Status"
 msgstr "Status"
 
@@ -914,7 +913,7 @@
 msgstr "Ablehnen"
 
 msgid "Call in progress."
-msgstr "Verbindungsaufbau."
+msgstr "Anruf im Gange."
 
 msgid "The call has been terminated."
 msgstr "Der Anruf wurde beendet."
@@ -1389,6 +1388,8 @@
 msgid "Type"
 msgstr "Typ"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 #. Statuses are almost all the same. Define a macro to reduce code repetition.
 #. PurpleStatusPrimitive
 #. id - use default
@@ -1397,6 +1398,8 @@
 #. user_settable
 #. not independent
 #. Attributes - each status can have a message.
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Message"
 msgstr "Nachricht"
 
@@ -3025,19 +3028,29 @@
 msgstr "Keine Verbindung zum lokalen mDNS-Server. Ist er aktiviert?"
 
 # old strings
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "First name"
 msgstr "Vorname"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Last name"
 msgstr "Nachname"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 #. email
 msgid "Email"
 msgstr "E-Mail"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "AIM Account"
 msgstr "AIM-Konto"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "XMPP Account"
 msgstr "XMPP-Konto"
 
@@ -3152,6 +3165,8 @@
 msgid "Please, fill in the following fields"
 msgstr "Bitte füllen Sie die folgenden Felder aus"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "City"
 msgstr "Stadt"
 
@@ -3159,6 +3174,8 @@
 msgstr "Geburtsjahr"
 
 #. gender
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Gender"
 msgstr "Geschlecht"
 
@@ -3181,27 +3198,36 @@
 msgid "Please, enter your search criteria below"
 msgstr "Bitte geben Sie Ihre Suchkriterien unten ein"
 
-msgid "Fill in the fields."
-msgstr "Füllen Sie die Felder aus."
-
-msgid "Your current password is different from the one that you specified."
-msgstr "Ihr aktuelles Passwort ist anders als das angegebene."
-
-msgid "Unable to change password. Error occurred.\n"
-msgstr "Konnte das Passwort nicht ändern. Es trat ein Fehler auf.\n"
-
 msgid "Change password for the Gadu-Gadu account"
 msgstr "Ändern des Passworts für dieses Gadu-Gadu-Konto"
 
 msgid "Password was changed successfully!"
 msgstr "Das Passwort wurde erfolgreich geändert!"
 
+msgid "Unable to change password. Error occurred.\n"
+msgstr "Konnte das Passwort nicht ändern. Es trat ein Fehler auf.\n"
+
+msgid "Fill in the fields."
+msgstr "Füllen Sie die Felder aus."
+
+msgid "New password should be at most 15 characters long."
+msgstr "Das neue Passwort darf maximal 15 Zeichen lang sein."
+
+msgid "Your current password is different from the one that you specified."
+msgstr "Ihr aktuelles Passwort ist anders als das angegebene."
+
+msgid "Invalid email address"
+msgstr "Ungültige E-Mail-Adresse"
+
 msgid "Current password"
 msgstr "Aktuelles Passwort"
 
 msgid "Password (retype)"
 msgstr "Passwort (nochmal)"
 
+msgid "Email Address"
+msgstr "E-Mail-Adresse"
+
 msgid "Enter current token"
 msgstr "Geben Sie das aktuelle Token ein"
 
@@ -3257,14 +3283,20 @@
 msgid "Away"
 msgstr "Abwesend"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "UIN"
 msgstr "UIN"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 #. first name
 #. optional information
 msgid "First Name"
 msgstr "Vorname"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Birth Year"
 msgstr "Geburtsjahr"
 
@@ -3304,6 +3336,30 @@
 msgid "Connected"
 msgstr "Verbunden"
 
+msgid "Unable to resolve hostname"
+msgstr "Hostname konnte nicht aufgelöst werden"
+
+msgid "Incorrect password"
+msgstr "Falsches Passwort"
+
+msgid "SSL Connection Failed"
+msgstr "SSL-Verbindung gescheitert"
+
+msgid ""
+"Your account has been disabled because too many incorrect passwords were "
+"entered"
+msgstr ""
+"Ihr Konto wurde wegen zu vielen falsch eingegebenen Passworten gesperrt"
+
+msgid "Service temporarily unavailable"
+msgstr "Dienst momentan nicht verfügbar"
+
+msgid "Error connecting to proxy server"
+msgstr "Fehler beim Verbinden mit dem Proxy-Server"
+
+msgid "Error connecting to master server"
+msgstr "Fehler beim Verbinden mit dem Master-Server"
+
 msgid "Connection failed"
 msgstr "Verbindung fehlgeschlagen"
 
@@ -3313,6 +3369,12 @@
 msgid "Chat _name:"
 msgstr "Chat_name:"
 
+msgid "The username specified is invalid."
+msgstr "Der angegebene Benutzername ist ungültig."
+
+msgid "SSL support unavailable"
+msgstr "SSL-Unterstützung nicht verfügbar"
+
 #, c-format
 msgid "Unable to resolve hostname '%s': %s"
 msgstr "Hostname '%s' kann nicht aufgelöst werden: %s"
@@ -3331,12 +3393,12 @@
 msgid "Not connected to the server"
 msgstr "Nicht mit dem Server verbunden"
 
+msgid "Change password..."
+msgstr "Passwort ändern..."
+
 msgid "Find buddies..."
 msgstr "Finde Buddys..."
 
-msgid "Change password..."
-msgstr "Passwort ändern..."
-
 msgid "Upload buddylist to Server"
 msgstr "Buddy-Liste zum Server hochladen"
 
@@ -3367,25 +3429,24 @@
 msgid "Polish popular IM"
 msgstr "Beliebter polnischer IM-Dienst"
 
-msgid "Gadu-Gadu User"
-msgstr "Gadu-Gadu-Benutzer"
-
 msgid "GG server"
 msgstr "GG-Server"
 
+msgid "Use encryption if available"
+msgstr "Verschlüsselung benutzen, wenn verfügbar"
+
+msgid "Require encryption"
+msgstr "Verschlüsselung fordern"
+
 msgid "Don't use encryption"
 msgstr "Keine Verschlüsselung benutzen"
 
-msgid "Use encryption if available"
-msgstr "Verschlüsselung benutzen, wenn verfügbar"
-
-#. TODO
-msgid "Require encryption"
-msgstr "Verschlüsselung fordern"
-
 msgid "Connection security"
 msgstr "Verbindungssicherheit"
 
+msgid "Show links from strangers"
+msgstr "Links von Fremden anzeigen"
+
 #, c-format
 msgid "Unknown command: %s"
 msgstr "Unbekanntes Kommando: %s"
@@ -3438,9 +3499,6 @@
 msgid "IRC nick and server may not contain whitespace"
 msgstr "IRC-Server und -Spitzname dürfen keinen Leerraum enthalten"
 
-msgid "SSL support unavailable"
-msgstr "SSL-Unterstützung nicht verfügbar"
-
 msgid "Unable to connect"
 msgstr "Verbindung nicht möglich"
 
@@ -3474,7 +3532,9 @@
 msgid "The IRC Protocol Plugin that Sucks Less"
 msgstr "Das IRC-Protokoll-Plugin mit weniger Problemen"
 
-#. host to connect to
+#. set up account ID as user:server
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Server"
 msgstr "Server"
 
@@ -4013,6 +4073,8 @@
 msgid "Unable to establish SSL connection"
 msgstr "Kann SSL-Verbindung nicht erstellen"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Full Name"
 msgstr "Vollständiger Name"
 
@@ -4083,9 +4145,13 @@
 "Die folgenden Punkte sind optional. Geben Sie nur die Informationen an, die "
 "Sie angeben möchten."
 
+#. TODO: Check whether it's correct to call prepend_pair_html,
+#. or if we should be using prepend_pair_plaintext
 msgid "Client"
 msgstr "Client"
 
+#. TODO: Check whether it's correct to call prepend_pair_html,
+#. or if we should be using prepend_pair_plaintext
 msgid "Operating System"
 msgstr "Betriebssystem"
 
@@ -4095,6 +4161,8 @@
 msgid "Priority"
 msgstr "Priorität"
 
+#. TODO: Check whether it's correct to call prepend_pair_html,
+#. or if we should be using prepend_pair_plaintext
 msgid "Resource"
 msgstr "Ressource"
 
@@ -4191,9 +4259,6 @@
 "Füllen Sie ein oder mehrere Felder aus, um nach entsprechenden XMPP-"
 "Benutzern zu suchen."
 
-msgid "Email Address"
-msgstr "E-Mail-Adresse"
-
 msgid "Search for XMPP users"
 msgstr "Suche nach XMPP-Benutzern"
 
@@ -4404,6 +4469,8 @@
 msgid "Not Authorized"
 msgstr "Nicht autorisiert"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Mood"
 msgstr "Stimmung"
 
@@ -5253,9 +5320,6 @@
 msgid "Syntax Error (probably a client bug)"
 msgstr "Syntaxfehler (wahrscheinlich ein Client-Bug)"
 
-msgid "Invalid email address"
-msgstr "Ungültige E-Mail-Adresse"
-
 msgid "User does not exist"
 msgstr "Benutzer existiert nicht"
 
@@ -5323,9 +5387,6 @@
 msgid "Not logged in"
 msgstr "Nicht angemeldet"
 
-msgid "Service temporarily unavailable"
-msgstr "Dienst momentan nicht verfügbar"
-
 msgid "Database server error"
 msgstr "Fehler des Datenbank-Servers"
 
@@ -5673,6 +5734,8 @@
 msgid "Occupation"
 msgstr "Beruf"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Location"
 msgstr "Ort"
 
@@ -6056,9 +6119,6 @@
 msgid "Do you want to delete this buddy from your address book as well?"
 msgstr "Möchten Sie diesen Buddy außerdem aus Ihrem Adressbuch löschen?"
 
-msgid "The username specified is invalid."
-msgstr "Der angegebene Benutzername ist ungültig."
-
 msgid "The Display Name you entered is invalid."
 msgstr "Der eingegebene Anzeigename ist ungültig."
 
@@ -6074,6 +6134,8 @@
 
 #. no profile information yet, so we cannot update
 #. (reference: "libpurple/request.h")
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Profile"
 msgstr "Profil"
 
@@ -6187,6 +6249,8 @@
 msgid "About..."
 msgstr "Über..."
 
+#. we are trying to send a file to MXit
+#. need to reserve some space for packet headers
 #. the file is too big
 msgid "The file you are trying to send is too large!"
 msgstr "Die Datei, die Sie senden möchten ist zu groß!"
@@ -6307,16 +6371,14 @@
 msgid "Loading menu..."
 msgstr "Lade das Menü..."
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Status Message"
 msgstr "Status-Nachricht"
 
 msgid "Rejection Message"
 msgstr "Ablehnungsnachricht"
 
-#. hidden number
-msgid "Hidden Number"
-msgstr "Versteckte Nummer"
-
 msgid "No profile available"
 msgstr "Kein Profil verfügbar"
 
@@ -6400,6 +6462,12 @@
 msgid "Message Error"
 msgstr "Nachrichtenfehler"
 
+#. could not be decrypted
+msgid "An encrypted message was received which could not be decrypted."
+msgstr ""
+"Eine verschlüsselte Nachricht wurde empfangen und konnte nicht entschlüsselt "
+"werden."
+
 msgid "Cannot perform redirect using the specified protocol"
 msgstr "Kann die Umleitung nicht mit dem angegebenen Protokoll durchführen"
 
@@ -6664,18 +6732,26 @@
 msgid "Base font size (points)"
 msgstr "Basis-Schriftgröße (Punkt)"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "User"
 msgstr "Benutzer"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Headline"
 msgstr "Überschrift"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Song"
 msgstr "Lied"
 
 msgid "Total Friends"
 msgstr "Freunde insgesamt"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Client Version"
 msgstr "Client-Version"
 
@@ -6879,9 +6955,6 @@
 msgid "Password has expired"
 msgstr "Passwort ist abgelaufen"
 
-msgid "Incorrect password"
-msgstr "Falsches Passwort"
-
 msgid "Account has been disabled"
 msgstr "Konto wurde deaktiviert"
 
@@ -6908,12 +6981,6 @@
 "Konnte den Rechnernamen des Benutzers, den Sie eingegeben haben, nicht "
 "erkennen"
 
-msgid ""
-"Your account has been disabled because too many incorrect passwords were "
-"entered"
-msgstr ""
-"Ihr Konto wurde wegen zu vielen falsch eingegebenen Passworten gesperrt"
-
 msgid "You cannot add the same person twice to a conversation"
 msgstr "Sie können die selbe Person nicht zweimal zu einem Gespräch hinzufügen"
 
@@ -7039,12 +7106,9 @@
 msgid "User ID"
 msgstr "Benutzer-ID"
 
-#. tag = _("DN");
-#. value = nm_user_record_get_dn(user_record);
-#. if (value) {
-#. purple_notify_user_info_add_pair(user_info, tag, value);
-#. }
-#.
+msgid "DN"
+msgstr "DN"
+
 msgid "Full name"
 msgstr "Vollständiger Name"
 
@@ -8147,6 +8211,7 @@
 msgid "Mobile Phone"
 msgstr "Handynummer"
 
+#. TODO: Is it correct to pass info->email here...?
 msgid "Personal Web Page"
 msgstr "Persönliche Webseite"
 
@@ -8167,6 +8232,7 @@
 msgid "Position"
 msgstr "Position"
 
+#. TODO: Is it correct to pass info->email here...?
 msgid "Web Page"
 msgstr "Webseite"
 
@@ -8433,33 +8499,16 @@
 msgid "Topic:"
 msgstr "Thema:"
 
-msgid "No Sametime Community Server specified"
-msgstr "Kein Sametime-Community Server angegeben"
-
-#, c-format
-msgid ""
-"No host or IP address has been configured for the Meanwhile account %s. "
-"Please enter one below to continue logging in."
-msgstr ""
-"Es wurde kein Rechner für das Meanwhile-Konto %s angegeben. Bitte geben Sie "
-"einen Rechner an, um die Anmeldung fortzusetzen."
-
-msgid "Meanwhile Connection Setup"
-msgstr "Meanwhile-Verbindungseinstellungen"
-
-msgid "No Sametime Community Server Specified"
-msgstr "Kein Sametime-Community Server angegeben"
-
-msgid "Connect"
-msgstr "Verbinden"
+msgid "A server is required to connect this account"
+msgstr "Es wird ein Server benötigt um dieses Konto zu verbinden."
+
+msgid "Last Known Client"
+msgstr "Letzter bekannter Client"
 
 #, c-format
 msgid "Unknown (0x%04x)<br>"
 msgstr "Unbekannt (0x%04x)<br>"
 
-msgid "Last Known Client"
-msgstr "Letzter bekannter Client"
-
 msgid "User Name"
 msgstr "Benutzername"
 
@@ -8782,21 +8831,33 @@
 msgid "Robot"
 msgstr "Robot"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "User Modes"
 msgstr "Benutzermodi"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Preferred Contact"
 msgstr "Bevorzugter Kontakt"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Preferred Language"
 msgstr "Bevorzugte Sprache"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Device"
 msgstr "Gerät"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Timezone"
 msgstr "Zeitzone"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Geolocation"
 msgstr "Geographische Koordinaten"
 
@@ -9666,78 +9727,12 @@
 msgid "Whiteboard"
 msgstr "Whiteboard"
 
-msgid "No server statistics available"
-msgstr "Keine Serverstatistik verfügbar"
-
-msgid "Error during connecting to SILC Server"
-msgstr "Fehler beim Verbinden mit dem SILC-Server"
-
-#, c-format
-msgid "Failure: Version mismatch, upgrade your client"
-msgstr "Fehler: Unterschiedliche Version, aktualisieren Sie Ihren Client"
-
-#, c-format
-msgid "Failure: Remote does not trust/support your public key"
-msgstr ""
-"Fehler: Die entfernte Seite vertraut Ihrem öffentlichen Schlüssel nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed KE group"
-msgstr ""
-"Fehler: Entferntes Programm unterstützt nicht die vorgeschlagen KE-Gruppe"
-
-#, c-format
-msgid "Failure: Remote does not support proposed cipher"
-msgstr ""
-"Fehler: Entferntes Programm unterstützt die vorgeschlagene Chiffre nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed PKCS"
-msgstr "Fehler: Entferntes Programm unterstützt die vorgeschlagene PKCS nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed hash function"
-msgstr ""
-"Fehler: Entferntes Programm unterstützt die vorgeschlagen Hashfunktion nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed HMAC"
-msgstr "Fehler: Entferntes Programm unterstützt das vorgeschlagene HMAC nicht"
-
-#, c-format
-msgid "Failure: Incorrect signature"
-msgstr "Fehler: Falsche Signatur"
-
-#, c-format
-msgid "Failure: Invalid cookie"
-msgstr "Fehler: Ungültiger Cookie"
-
-#, c-format
-msgid "Failure: Authentication failed"
-msgstr "Fehler: Authentifizierung fehlgeschlagen"
-
-msgid "Unable to initialize SILC Client connection"
-msgstr "SILC-Client-Verbindung konnte nicht hergestellt werden"
-
-msgid "John Noname"
-msgstr "Max Mustermann"
-
-#, c-format
-msgid "Unable to load SILC key pair: %s"
-msgstr "SILC-Schlüsselpaar konnte nicht geladen werden: %s"
-
-msgid "Unable to create connection"
-msgstr "Kann Verbindung nicht erstellen"
-
 msgid "Unknown server response"
 msgstr "Unbekannte Serverantwort"
 
 msgid "Unable to create listen socket"
 msgstr "Lauschender Socket konnte nicht erstellt werden"
 
-msgid "Unable to resolve hostname"
-msgstr "Hostname konnte nicht aufgelöst werden"
-
 msgid "SIP usernames may not contain whitespaces or @ symbols"
 msgstr "SIP-Benutzernamen dürfen keine Leerzeichen oder @-Symbole enthalten"
 
@@ -10218,6 +10213,8 @@
 msgid "Hidden or not logged-in"
 msgstr "Versteckt oder nicht angemeldet"
 
+#. TODO: Need to escape locs.host and locs.time?
+#. TODO: Need to escape the two strings that make up tmp?
 #, c-format
 msgid "<br>At %s since %s"
 msgstr "<br>Bei %s seit %s"
@@ -10426,9 +10423,6 @@
 msgid "Stored Image. (that'll have to do for now)"
 msgstr "Gespeichertes Bild. (Das muss erstmal reichen)"
 
-msgid "SSL Connection Failed"
-msgstr "SSL-Verbindung gescheitert"
-
 msgid "SSL Handshake Failed"
 msgstr "SSL-Verhandlung gescheitert"
 
@@ -11394,6 +11388,21 @@
 msgid "SSL Servers"
 msgstr "SSL-Server"
 
+msgid "Unsafe debugging is now disabled."
+msgstr "Unsicheres Debugging ist nun deaktiviert."
+
+msgid "Unsafe debugging is now enabled."
+msgstr "Unsicheres Debugging ist nun aktiviert."
+
+msgid "Verbose debugging is now disabled."
+msgstr "Ausführliches Debugging ist nun deaktiviert."
+
+msgid "Verbose debugging is now enabled."
+msgstr "Ausführliches Debugging ist nun aktiviert."
+
+msgid "Supported debug options are: plugins version unsafe verbose"
+msgstr "Unterstützte Debug-Optionen sind: plugins version unsafe verbose"
+
 msgid "Unknown command."
 msgstr "Unbekanntes Kommando."
 
@@ -11428,9 +11437,6 @@
 msgid "Ignore"
 msgstr "Ignorieren"
 
-msgid "Get Away Message"
-msgstr "Neue Abwesenheitsnachricht abholen"
-
 msgid "Last Said"
 msgstr "Zuletzt gesagt"
 
@@ -12178,12 +12184,6 @@
 msgid "View User Log"
 msgstr "Benutzer-Mitschnitt anzeigen"
 
-msgid "Alias Contact"
-msgstr "Kontakt-Alias"
-
-msgid "Enter an alias for this contact."
-msgstr "Geben Sie einen Alias für diesen Kontakt ein."
-
 #, c-format
 msgid "Enter an alias for %s."
 msgstr "Geben Sie einen Alias %s ein."
@@ -12779,9 +12779,18 @@
 msgid "Incoming Call"
 msgstr "Eingehender Anruf"
 
+msgid "_Hold"
+msgstr "_Halten"
+
 msgid "_Pause"
 msgstr "_Pause"
 
+msgid "_Mute"
+msgstr "Stu_mmschalten"
+
+msgid "Call in progress"
+msgstr "Anruf im Gange"
+
 #, c-format
 msgid "%s has %d new message."
 msgid_plural "%s has %d new messages."
@@ -13004,6 +13013,9 @@
 msgid "The default Pidgin buddy list theme"
 msgstr "Das Standard-Buddy-Listen-Thema für Pidgin"
 
+msgid "The default Pidgin conversation theme"
+msgstr "Das Standard-Thema für Pidgin-Unterhaltungen"
+
 msgid "The default Pidgin status icon theme"
 msgstr "Das Standard-Status-Icon-Thema für Pidgin"
 
@@ -13031,6 +13043,13 @@
 msgid "Buddy List Theme:"
 msgstr "Buddy-Listen-Thema:"
 
+msgid "Conversation Theme:"
+msgstr "Unterhaltungs-Thema:"
+
+#, fuzzy
+msgid "\tVariant:"
+msgstr "\tVariante:"
+
 msgid "Status Icon Theme:"
 msgstr "Status-Icon-Thema:"