changeset 32805:064eb5d78946

propagate from branch 'im.pidgin.pidgin.2.x.y' (head 0ba3afb8adb303a77581a7872d674c600979a5a6) to branch 'im.pidgin.pidgin' (head 7711a4d267e1fe776387496c764fb63227d70aec)
author Mark Doliner <mark@kingant.net>
date Mon, 31 Oct 2011 01:25:36 +0000
parents 15e80ced77a2 (current diff) b6276b10cb10 (diff)
children e323c2f84872
files ChangeLog gaim-uninstalled.pc.in gaim.pc.in libpurple/gaim-compat.h libpurple/protocols/silc10/Makefile.am libpurple/protocols/silc10/Makefile.mingw libpurple/protocols/silc10/README libpurple/protocols/silc10/TODO libpurple/protocols/silc10/buddy.c libpurple/protocols/silc10/chat.c libpurple/protocols/silc10/ft.c libpurple/protocols/silc10/ops.c libpurple/protocols/silc10/pk.c libpurple/protocols/silc10/silc.c libpurple/protocols/silc10/silcpurple.h libpurple/protocols/silc10/util.c libpurple/protocols/silc10/wb.c libpurple/protocols/silc10/wb.h libpurple/purple-2-uninstalled.pc.in libpurple/purple-2.pc.in libpurple/purple-uninstalled.pc.in libpurple/purple.pc.in pidgin/gtkdocklet-gtk.c pidgin/gtkgaim-compat.h pidgin/pidgin-2-uninstalled.pc.in pidgin/pidgin-2.pc.in pidgin/pidgin-uninstalled.pc.in pidgin/pidgin.pc.in
diffstat 399 files changed, 11275 insertions(+), 21677 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Oct 31 01:22:26 2011 +0000
+++ b/ChangeLog	Mon Oct 31 01:25:36 2011 +0000
@@ -1,5 +1,42 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 3.0.0 (??/??/????):
+	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.
+	* Ignore new invites to join a GroupChat if you're already joined, or
+	  still have a pending invite.
+	* The buddy's name was not centered vertically in the buddy-list if they
+	  did not have a status-message or mood set.
+
+	XMPP:
+	* Strip element prefixes from XHTML-IM messages as they're presented
+	  to the core (and UIs) as incoming messages (Thijs Alkemade).
+	  (#14529)
+	* Support file transfers up to ~9 EiB.
+
 version 2.10.1 (10/11/2011):
 	Finch:
 	* Fix compilation on OpenBSD.
--- a/ChangeLog.API	Mon Oct 31 01:22:26 2011 +0000
+++ b/ChangeLog.API	Mon Oct 31 01:25:36 2011 +0000
@@ -1,5 +1,242 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 3.0.0 (??/??/????):
+	libpurple:
+		Added:
+		* pidgin_create_webview
+		* purple_account_get_ui_data
+		* purple_account_set_ui_data
+		* 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_notify_searchresult_column_get_title
+		* purple_notify_searchresult_column_is_visible
+		* purple_notify_searchresult_column_set_visible
+		* purple_notify_user_info_prepend_pair_plaintext
+		* purple_menu_action_get_callback
+		* purple_menu_action_get_children
+		* purple_menu_action_get_data
+		* purple_menu_action_set_label
+		* purple_menu_action_set_data
+		* purple_menu_action_set_callback
+		* purple_menu_action_set_children
+		* purple_request_field_get_tooltip
+		* purple_request_field_group_get_fields_list
+		* purple_request_field_set_tooltip
+		* purple_request_fields_get_ui_data
+		* purple_request_fields_set_ui_data
+		* purple_roomlist_get_account
+		* purple_roomlist_get_proto_data
+		* purple_roomlist_get_ui_data
+		* purple_roomlist_room_get_expanded_once
+		* purple_roomlist_room_set_expanded_once
+		* purple_roomlist_set_proto_data
+		* purple_roomlist_set_ui_data
+		* purple_whiteboard_get_account
+		* purple_whiteboard_get_draw_list
+		* purple_whiteboard_set_draw_list
+		* purple_whiteboard_get_protocol_data
+		* purple_whiteboard_set_protocol_data
+		* purple_whiteboard_get_state
+		* purple_whiteboard_set_state
+		* purple_whiteboard_get_ui_data
+		* purple_whiteboard_set_ui_data
+		* purple_whiteboard_get_who
+		* purple_xfer_get_fd
+		* purple_xfer_get_protocol_data
+		* purple_xfer_get_ui_data
+		* purple_xfer_get_watcher
+		* purple_xfer_set_fd
+		* purple_Xfer_set_local_port
+		* purple_xfer_set_protocol_data
+		* purple_xfer_set_status
+		* purple_xfer_set_ui_data
+		* purple_xfer_set_watcher
+		* Various WebKit-related functions in gtkwebview.h
+		* xmlnode_get_default_namespace
+		* xmlnode_strip_prefixes
+
+		Changed:
+		* purple_account_add_buddy now takes an invite message as the last
+		  parameter
+		* purple_account_add_buddies now takes an invite message as the last
+		  parameter
+		* purple_certificate_check_signature_chain now returns a list of failing
+		  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
+		* purple_network_listen now takes a boolean indicating external port
+		  mapping as the fourth parameter
+		* purple_network_listen_range now takes a boolean indicating external
+		  port mapping as the fifth parameter
+		* purple_network_listen_range now takes the protocol family as the
+		  third parameter
+		* purple_notify_user_info_add_pair renamed to
+		  purple_notify_user_info_add_pair_html
+		* purple_notify_user_info_get_entries returns a GQueue instead of
+		  a GList
+		* 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
+		* _GntKeyPressMode
+		* _GntMouseEvent
+		* _GntParamFlags
+		* _GntProgressBarOrientation
+		* _GntTreeColumnFlag
+		* _GntWidgetFlags
+		* _PurpleCipherBatchMode
+		* _PurpleCipherCaps
+		* _PurpleCmdFlag
+		* _PurpleCmdPriority
+		* _PurpleCmdRet
+		* _PurpleCmdStatus
+		* _PurplePrefType
+		* _PurplePrivacyType
+		* _PurpleSoundEventID
+		* _XMLNodeType
+		* GtkIMHtml.clipboard_html_string
+		* GtkIMHtml.clipboard_text_string
+		* GtkIMHtmlFontDetail
+		* gtk_imhtml_animation_free
+		* gtk_imhtml_animation_new
+		* gtk_imhtml_image_add_to
+		* gtk_imhtml_image_free
+		* gtk_imhtml_image_new
+		* gtk_imhtml_image_scale
+		* pidgin_blist_update_account_error_state
+		* pidgin_check_if_dir
+		* PIDGIN_DIALOG
+		* pidgin_dialogs_alias_contact
+		* pidgin_set_custom_buddy_icon
+		* pidgin_setup_screenname_autocomplete
+		* PidginBuddyList.connection_errors
+		* PidginConversation.sg
+		* purple_account_add_buddies_with_invite
+		* purple_account_add_buddy_with_invite
+		* purple_blist_update_buddy_icon
+		* purple_buddy_get_local_alias
+		* purple_buddy_icons_has_custom_icon
+		* purple_buddy_icons_find_custom_icon
+		* purple_buddy_icons_set_custom_icon
+		* purple_certificate_check_signature_chain_with_failing. Use
+		  purple_certificate_check_signature_chain, instead
+		* purple_connection_error_reason
+		* purple_connection_new
+		* purple_connection_new_unregister
+		* purple_connection_destroy
+		* purple_contact_set_alias
+		* purple_conv_chat_set_users
+		* purple_core_migrate
+		* purple_dnsquery_a_account
+		* purple_network_listen_family. Use purple_network_listen, instead.
+		* purple_network_listen_map_external
+		* purple_network_listen_range_family. Use purple_network_listen,
+		  instead.
+		* purple_notify_searchresults_column_get_title
+		* purple_notify_searchresults_get_columns_count
+		* purple_notify_searchresults_get_rows_count
+		* purple_notify_searchresults_row_get
+		* purple_plugins_register_load_notify_cb
+		* purple_plugins_register_probe_notify_cb
+		* purple_plugins_register_unload_notify_cb
+		* purple_plugins_unregister_load_notify_cb
+		* purple_plugins_unregister_probe_notify_cb
+		* purple_plugins_unregister_unload_notify_cb
+		* purple_presence_add_status
+		* purple_presence_add_list
+		* purple_proxy_connect_socks5
+		* purple_request_field_list_add
+		* purple_srv_cancel
+		* purple_srv_resolve_account
+		* purple_ssl_connect_fd
+		* purple_status_set_attr_boolean
+		* purple_status_set_attr_int
+		* purple_status_set_attr_string
+		* purple_status_type_add_attr
+		* purple_status_type_add_attrs
+		* purple_status_type_add_attrs_vargs
+		* purple_status_type_get_primary_attr
+		* purple_status_type_set_primary_attr
+		* purple_strlcat
+		* purple_strlcpy
+		* purple_txt_cancel
+		* purple_txt_resolve_account
+		* purple_util_fetch_url_len. Use purple_util_fetch_url, instead.
+		* purple_util_fetch_url_request_len. Use purple_util_fetch_url_request,
+		  instead.
+		* purple_util_fetch_url_request_len_with_account.  Use
+		  purple_util_fetch_url_request, instead.
+		* PurpleConnectionUiOps.report_disconnect_reason
+		* PurplePluginProtocolInfo.add_buddy_with_invite
+		* PurplePluginProtocolInfo.add_buddies_with_invite
+		* 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
+		* struct _PurpleConversation
+		* struct _PurpleConvChat
+		* struct _PurpleConvChatBuddy
+		* struct _PurpleConvIm
+		* struct _PurpleConvMessage
+		* struct _PurpleMenuAction
+		* struct _PurplePounce
+		* struct _PurpleProxyInfo
+		* struct _PurpleRequestField
+		* 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.0:
 	libpurple:
 		Added:
--- a/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ b/Makefile.am	Mon Oct 31 01:25:36 2011 +0000
@@ -11,8 +11,6 @@
 		config.h.mingw \
 		doxy2devhelp.xsl \
 		fix-casts.sh \
-		gaim.pc.in \
-		gaim-uninstalled.pc.in \
 		intltool-extract.in \
 		intltool-merge.in \
 		intltool-update.in \
--- a/configure.ac	Mon Oct 31 01:22:26 2011 +0000
+++ b/configure.ac	Mon Oct 31 01:25:36 2011 +0000
@@ -43,11 +43,11 @@
 #
 # Make sure to update finch/libgnt/configure.ac with libgnt version changes.
 #
-m4_define([purple_lt_current], [10])
-m4_define([purple_major_version], [2])
-m4_define([purple_minor_version], [10])
+m4_define([purple_lt_current], [20])
+m4_define([purple_major_version], [3])
+m4_define([purple_minor_version], [0])
 m4_define([purple_micro_version], [0])
-m4_define([purple_version_suffix], [])
+m4_define([purple_version_suffix], [devel])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
 m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix]))
@@ -56,7 +56,7 @@
 m4_define([gnt_major_version], [2])
 m4_define([gnt_minor_version], [8])
 m4_define([gnt_micro_version], [9])
-m4_define([gnt_version_suffix], [])
+m4_define([gnt_version_suffix], [devel])
 m4_define([gnt_version],
           [gnt_major_version.gnt_minor_version.gnt_micro_version])
 m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
@@ -328,6 +328,9 @@
 dnl #######################################################################
 dnl # Check for GLib 2.16 (required)
 dnl #######################################################################
+# TODO: gmodule-2.0 is only needed if enable_plugins is 'yes'.  It
+#       might be nice to change this check so that it's not required
+#       if enable_plugins is 'no'.
 PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
 	AC_MSG_RESULT(no)
 	AC_MSG_ERROR([
@@ -431,6 +434,16 @@
 	PKG_CHECK_MODULES(PANGO, [pango >= 1.4.0],
 			AC_DEFINE(HAVE_PANGO14, 1, [Define if we have Pango 1.4 or newer.]),:)
 
+	PKG_CHECK_MODULES(WEBKIT, [webkit-1.0 >= 1.1.1], , [
+		AC_MSG_RESULT(no)
+		AC_MSG_ERROR([
+You must have WebKit 1.1.1 or newer development headers installed to compile
+Pidgin.  If you want to build only Finch then specify --disable-gtkui when
+running configure.
+])])
+	AC_SUBST(WEBKIT_CFLAGS)
+	AC_SUBST(WEBKIT_LIBS)
+
 	dnl #######################################################################
 	dnl # Check if we should compile with X support
 	dnl #######################################################################
@@ -938,25 +951,6 @@
 	], [
 		have_silc="no"
 	])
-	if test "x$have_silc" = "xno"; then
-		PKG_CHECK_MODULES(SILC, silcclient, [
-			have_silc="yes"
-			silc10includes="yes"
-			silc10client="yes"
-		], [
-			have_silc="no"
-		])
-		dnl If silcclient.pc wasn't found, check for just silc.pc
-		if test "x$have_silc" = "xno"; then
-			PKG_CHECK_MODULES(SILC, silc, [
-				have_silc="yes"
-				silc10includes="yes"
-				silc10client="yes"
-			], [
-				have_silc="no"
-			])
-		fi
-	fi
 else
 	if test "$ac_silc_includes" != "no"; then
 		SILC_CFLAGS="-I$ac_silc_includes"
@@ -974,17 +968,6 @@
 
 	if test "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes"; then
 		have_silc="yes"
-	else
-		CPPFLAGS_save="$CPPFLAGS"
-		CPPFLAGS="$CPPFLAGS $SILC_CFLAGS"
-		AC_CHECK_HEADER(silcincludes.h, [silc10includes=yes])
-		CPPFLAGS="$CPPFLAGS_save"
-
-		SILC_LIBS="$SILC_LIBS -lsilc -lsilcclient -lpthread $LIBDL"
-		AC_CHECK_LIB(silcclient, silc_client_init, [silc10client=yes], , $SILC_LIBS)
-		if test "x$silc10includes" = "xyes" -a "x$silc10client" = "xyes"; then
-			have_silc="yes"
-		fi
 	fi
 fi
 AC_SUBST(SILC_LIBS)
@@ -992,20 +975,6 @@
 dnl SILC Toolkit >= 1.0.1 has a new MIME API
 if test "x$silcclient" = "xyes"; then
 	AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h])
-elif test "x$silc10client" = "xyes"; then
-	CPPFLAGS_save="$CPPFLAGS"
-	CPPFLAGS="$CPPFLAGS $SILC_CFLAGS"
-		AC_MSG_CHECKING(for silcmime.h)
-		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <silcincludes.h>
-#include <silcmime.h>
-		]], [[]])], [
-		AC_MSG_RESULT(yes)
-		AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h])
-		], [
-		AC_MSG_RESULT(no)
-		])
-	CPPFLAGS="$CPPFLAGS_save"
 fi
 
 dnl #######################################################################
@@ -1111,7 +1080,7 @@
 fi
 
 if test "x$STATIC_PRPLS" = "xall" ; then
-	STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+	STATIC_PRPLS="bonjour gg irc jabber msn mxit myspace novell oscar sametime silc simple yahoo zephyr"
 fi
 if test "x$have_meanwhile" != "xyes" ; then
 	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'`
@@ -1120,10 +1089,7 @@
 	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'`
 fi
 if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then
-	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'`
-fi
-if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then
-	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc10//'`
+	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'`
 fi
 AC_SUBST(STATIC_PRPLS)
 STATIC_LINK_LIBS=
@@ -1147,8 +1113,6 @@
 	else
 		if test "x$i" = "xsilc"; then
 			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
-		elif test "x$i" = "xsilc10"; then
-			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la"
 		else
 			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la"
 		fi
@@ -1161,15 +1125,14 @@
 		irc)		static_irc=yes ;;
 		jabber)		static_jabber=yes ;;
 		msn)		static_msn=yes ;;
+		mxit)		static_mxit=yes ;;
 		myspace)	static_myspace=yes ;;
-		mxit)		static_mxit=yes ;;
 		novell)		static_novell=yes ;;
 		oscar)		static_oscar=yes ;;
 		aim)		static_oscar=yes ;;
 		icq)		static_oscar=yes ;;
 		sametime)	static_sametime=yes ;;
 		silc)		static_silc=yes ;;
-		silc10)		static_silc=yes ;;
 		simple)		static_simple=yes ;;
 		yahoo)		static_yahoo=yes ;;
 		zephyr)		static_zephyr=yes ;;
@@ -1181,8 +1144,8 @@
 AM_CONDITIONAL(STATIC_IRC, test "x$static_irc" = "xyes")
 AM_CONDITIONAL(STATIC_JABBER, test "x$static_jabber" = "xyes")
 AM_CONDITIONAL(STATIC_MSN, test "x$static_msn" = "xyes")
+AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "xyes")
 AM_CONDITIONAL(STATIC_MYSPACE, test "x$static_myspace" = "xyes")
-AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "xyes")
 AM_CONDITIONAL(STATIC_NOVELL, test "x$static_novell" = "xyes")
 AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "xyes")
 AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes")
@@ -1196,7 +1159,7 @@
 
 AC_ARG_WITH(dynamic_prpls, [AC_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`])
 if test "x$DYNAMIC_PRPLS" = "xall" ; then
-	DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+	DYNAMIC_PRPLS="bonjour gg irc jabber msn mxit myspace novell oscar sametime silc simple yahoo zephyr"
 fi
 if test "x$have_meanwhile" != "xyes"; then
 	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'`
@@ -1205,10 +1168,7 @@
 	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'`
 fi
 if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then
-	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'`
-fi
-if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then
-	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc10//'`
+	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'`
 fi
 AC_SUBST(DYNAMIC_PRPLS)
 for i in $DYNAMIC_PRPLS ; do
@@ -1218,8 +1178,8 @@
 		irc)		dynamic_irc=yes ;;
 		jabber)		dynamic_jabber=yes ;;
 		msn)		dynamic_msn=yes ;;
+		mxit)		dynamic_mxit=yes ;;
 		myspace)	dynamic_myspace=yes ;;
-		mxit)		dynamic_mxit=yes ;;
 		novell)		dynamic_novell=yes ;;
 		null)		dynamic_null=yes ;;
 		oscar)		dynamic_oscar=yes ;;
@@ -1227,7 +1187,6 @@
 		icq)		dynamic_oscar=yes ;;
 		sametime)	dynamic_sametime=yes ;;
 		silc)		dynamic_silc=yes ;;
-		silc10)		dynamic_silc=yes ;;
 		simple)		dynamic_simple=yes ;;
 		yahoo)		dynamic_yahoo=yes ;;
 		zephyr)		dynamic_zephyr=yes ;;
@@ -2530,10 +2489,8 @@
 		   m4macros/Makefile
 		   pidgin.apspec
 		   pidgin/Makefile
-		   pidgin/pidgin.pc
-		   pidgin/pidgin-uninstalled.pc
-		   pidgin/pidgin-2.pc
-		   pidgin/pidgin-2-uninstalled.pc
+		   pidgin/pidgin-3.pc
+		   pidgin/pidgin-3-uninstalled.pc
 		   pidgin/pixmaps/Makefile
 		   pidgin/pixmaps/emotes/default/24/Makefile
 		   pidgin/pixmaps/emotes/none/Makefile
@@ -2547,13 +2504,12 @@
 		   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
-		   libpurple/purple.pc
-		   libpurple/purple-uninstalled.pc
-		   libpurple/purple-2.pc
-		   libpurple/purple-2-uninstalled.pc
+		   libpurple/purple-3.pc
+		   libpurple/purple-3-uninstalled.pc
 		   libpurple/plugins/Makefile
 		   libpurple/plugins/mono/Makefile
 		   libpurple/plugins/mono/api/Makefile
@@ -2576,7 +2532,6 @@
 		   libpurple/protocols/oscar/Makefile
 		   libpurple/protocols/sametime/Makefile
 		   libpurple/protocols/silc/Makefile
-		   libpurple/protocols/silc10/Makefile
 		   libpurple/protocols/simple/Makefile
 		   libpurple/protocols/yahoo/Makefile
 		   libpurple/protocols/zephyr/Makefile
--- a/doc/account-signals.dox	Mon Oct 31 01:22:26 2011 +0000
+++ b/doc/account-signals.dox	Mon Oct 31 01:25:36 2011 +0000
@@ -34,7 +34,6 @@
   @signaldesc
    Emitted when an account is created by calling purple_account_new.
   @param account The account.
-  @since 2.6.0
  @endsignaldef
 
  @signaldef account-destroying
@@ -44,7 +43,6 @@
   @signaldesc
    Emitted when an account is about to be destroyed.
   @param account The account.
-  @since 2.6.0
  @endsignaldef
 
  @signaldef account-added
@@ -156,7 +154,6 @@
   @return Less than zero to deny the request without prompting, greater
           than zero if the request should be granted. If zero is returned,
           then the user will be prompted with the request.
-  @since 2.3.0
  @endsignaldef
 
  @signaldef account-authorization-requested-with-message
@@ -173,7 +170,6 @@
           get informed, PURPLE_ACCOUNT_RESPONSE_ACCEPT if the request should be
           granted. If PURPLE_ACCOUNT_RESPONSE_PASS is returned, then the user
           will be prompted with the request.
-  @since 2.8.0
  @endsignaldef
 
  @signaldef account-authorization-denied
@@ -184,7 +180,6 @@
    Emitted when the authorization request for a buddy is denied.
   @param account The account.
   @param user    The name of the user requesting authorization.
-  @since 2.3.0
  @endsignaldef
 
  @signaldef account-authorization-granted
@@ -195,7 +190,6 @@
    Emitted when the authorization request for a buddy is granted.
   @param account The account.
   @param user    The name of the user requesting authorization.
-  @since 2.3.0
  @endsignaldef
 
  @signaldef account-error-changed
@@ -214,7 +208,6 @@
                    pointer just after the next time this signal is emitted
                    for this @a account.
   @see purple_account_get_current_error()
-  @since 2.3.0
  @endsignaldef
 
  @signaldef account-signed-on
@@ -224,7 +217,6 @@
   @signaldesc
    Emitted when an account has signed on.
   @param account The account that has signed on.
-  @since 2.7.0
  @endsignaldef
 
  @signaldef account-signed-off
@@ -234,7 +226,6 @@
   @signaldesc
    Emitted when an account has signed off.
   @param account The account that has signed off.
-  @since 2.7.0
  @endsignaldef
 
  @signaldef account-connection-error
@@ -246,7 +237,6 @@
    @param account The account on which the error has occurred
    @param err     The error that occurred
    @param desc    A description of the error, giving more information.
-  @since 2.7.0
  @endsignaldef
  */
 // vim: syntax=c.doxygen tw=75 et
--- a/doc/blist-signals.dox	Mon Oct 31 01:22:26 2011 +0000
+++ b/doc/blist-signals.dox	Mon Oct 31 01:25:36 2011 +0000
@@ -136,7 +136,6 @@
   @param buddy	  The buddy
   @param newcaps
   @param oldcaps
-  @since 2.7.0
  @endsignaldef
 
  @signaldef ui-caps-changed
@@ -147,7 +146,6 @@
     Emitted when updating the media capabilities of the UI.
   @param newcaps
   @param oldcaps
-  @since 2.7.0
  @endsignaldef
  
  */
--- a/doc/connection-signals.dox	Mon Oct 31 01:22:26 2011 +0000
+++ b/doc/connection-signals.dox	Mon Oct 31 01:25:36 2011 +0000
@@ -44,7 +44,6 @@
   @return @c TRUE if the signal was handled or @c FALSE otherwise.  In
           practice, the return value is irrelevant, as it really only
           exists so plugins can block the UI's autojoin.
-  @since 2.7.0
  @endsignaldef
 
  @signaldef signing-off
--- a/doc/conversation-signals.dox	Mon Oct 31 01:22:26 2011 +0000
+++ b/doc/conversation-signals.dox	Mon Oct 31 01:25:36 2011 +0000
@@ -149,7 +149,6 @@
   @param message The message that was blocked.
   @param flags   The IM message flags.
   @param when    The time the message was sent.
-  @since 2.5.0
  @endsignaldef
 
  @signaldef writing-chat-msg
@@ -436,7 +435,6 @@
   @param name     The name of the chat invited to.
   @param message  The invitation message sent.
   @param data     Hashtable containing data about the invited chat.
-  @since 2.5.0
  @endsignaldef
 
  @signaldef chat-joined
@@ -477,7 +475,6 @@
    conversation.
   @param conv   The conversation.
   @param list   A pointer to the list of actions.
-  @since 2.1.0
  @endsignaldef
 
  @signaldef cleared-message-history
@@ -487,7 +484,6 @@
   @signaldesc
     Emitted when the conversation history is cleared.
   @param conv   The conversation.
-  @since 2.8.0
  @endsignaldef
 
  @signaldef sent-attention
@@ -501,7 +497,6 @@
   @param who      The name of the person receiving the attention
   @param conv     The conversation
   @param type     The attention type (an index starting at 0)
-  @since 2.7.0
  @endsignaldef
 
  @signaldef got-attention
@@ -515,7 +510,6 @@
   @param who      The name of the person sending the attention
   @param conv     The conversation
   @param type     The attention type (an index starting at 0)
-  @since 2.7.0
  @endsignaldef
 */
 // vim: syntax=c.doxygen tw=75 et
--- a/doc/gtkconv-signals.dox	Mon Oct 31 01:22:26 2011 +0000
+++ b/doc/gtkconv-signals.dox	Mon Oct 31 01:25:36 2011 +0000
@@ -129,7 +129,6 @@
   @signaldesc
    Emitted immediately before an existing conversation is hidden.
   @param gtkconv  The PidginConversation
-  @since 2.2.0
  @endsignaldef
 
  @signaldef conversation-displayed
@@ -139,7 +138,6 @@
   @signaldesc
    Emitted right after the Pidgin UI is attached to a new or a hidden conversation.
   @param gtkconv  The PidginConversation
-  @since 2.2.0
  @endsignaldef
 
 */
--- a/doc/notify-signals.dox	Mon Oct 31 01:22:26 2011 +0000
+++ b/doc/notify-signals.dox	Mon Oct 31 01:25:36 2011 +0000
@@ -35,7 +35,6 @@
   @param from      Who the email is from.
   @param to        Who the email is to.
   @param url       A url to view the email.
-  @since 2.1.0
  @endsignaldef
 
  @signaldef displaying-emails-notification
@@ -53,7 +52,6 @@
   @param tos        Who the emails are to.
   @param urls       The urls to view the emails.
   @param count      Number of emails being notified of.
-  @since 2.1.0
  @endsignaldef
 
 */
--- a/finch/finch.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/finch.c	Mon Oct 31 01:25:36 2011 +0000
@@ -351,29 +351,6 @@
 	/* We don't want debug-messages to show up and corrupt the display */
 	purple_debug_set_enabled(debug_enabled);
 
-	/* If we're using a custom configuration directory, we
-	 * do NOT want to migrate, or weird things will happen. */
-	if (opt_config_dir_arg == NULL)
-	{
-		if (!purple_core_migrate())
-		{
-			char *old = g_strconcat(purple_home_dir(),
-			                        G_DIR_SEPARATOR_S ".gaim", NULL);
-			char *text = g_strdup_printf(_(
-				"%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"), _("Finch"),
-				old, purple_user_dir());
-
-			g_free(old);
-
-			purple_print_utf8_to_console(stderr, text);
-			g_free(text);
-
-			return 0;
-		}
-	}
-
 	purple_core_set_ui_ops(gnt_core_get_ui_ops());
 	purple_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops());
 	purple_idle_set_ui_ops(finch_idle_get_ui_ops());
--- a/finch/gntaccount.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntaccount.h	Mon Oct 31 01:25:36 2011 +0000
@@ -59,8 +59,6 @@
  * Show the edit dialog for an account.
  *
  * @param account  The account to edit, or @c NULL to create a new account.
- *
- * @since 2.2.0
  */
 void finch_account_dialog_show(PurpleAccount *account);
 
--- a/finch/gntblist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntblist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -663,7 +663,7 @@
 		purple_blist_add_buddy(buddy, NULL, grp, NULL);
 	}
 
-	purple_account_add_buddy_with_invite(account, buddy, invite);
+	purple_account_add_buddy(account, buddy, invite);
 }
 
 static void
@@ -1060,7 +1060,7 @@
 						purple_buddy_get_account(buddy),
 						purple_buddy_get_name(buddy));
 		} else {
-			FinchConv *ggconv = FINCH_GET_DATA(conv);
+			FinchConv *ggconv = FINCH_CONV(conv);
 			gnt_window_present(ggconv->window);
 		}
 		finch_conversation_set_active(conv);
@@ -1078,9 +1078,10 @@
 	PurpleBlistNode *node = ggblist->cnode;
 	if (action) {
 		void (*callback)(PurpleBlistNode *, gpointer);
-		callback = (void (*)(PurpleBlistNode *, gpointer))action->callback;
+		callback = (void (*)(PurpleBlistNode *, gpointer))
+			purple_menu_action_get_callback(action);
 		if (callback)
-			callback(node, action->data);
+			callback(node, purple_menu_action_get_data(action));
 		else
 			return;
 	}
@@ -1095,15 +1096,17 @@
 	if (action == NULL)
 		return;
 
-	item = gnt_menuitem_new(action->label);
-	if (action->callback)
+	item = gnt_menuitem_new(purple_menu_action_get_label(action));
+	if (purple_menu_action_get_callback(action))
 		gnt_menuitem_set_callback(GNT_MENU_ITEM(item), context_menu_callback, action);
 	gnt_menu_add_item(menu, GNT_MENU_ITEM(item));
 
-	if (action->children) {
+	list = purple_menu_action_get_children(action);
+
+	if (list) {
 		GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
 		gnt_menuitem_set_submenu(item, GNT_MENU(sub));
-		for (list = action->children; list; list = list->next)
+		for (; list; list = list->next)
 			gnt_append_menu_action(GNT_MENU(sub), list->data, action);
 	}
 }
@@ -1123,7 +1126,7 @@
 		PurpleMenuAction *act = (PurpleMenuAction *) list->data;
 		if (!act)
 			continue;
-		act->data = node;
+		purple_menu_action_set_data(act, node);
 		gnt_append_menu_action(menu, act, NULL);
 		g_signal_connect_swapped(G_OBJECT(menu), "destroy",
 			G_CALLBACK(purple_menu_action_free), act);
@@ -1216,7 +1219,7 @@
 autojoin_toggled(GntMenuItem *item, gpointer data)
 {
 	PurpleMenuAction *action = data;
-	purple_blist_node_set_bool(action->data, "gnt-autojoin",
+	purple_blist_node_set_bool(purple_menu_action_get_data(action), "gnt-autojoin",
 				gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item)));
 }
 
@@ -1224,7 +1227,8 @@
 create_chat_menu(GntMenu *menu, PurpleChat *chat)
 {
 	PurpleMenuAction *action = purple_menu_action_new(_("Auto-join"), NULL, chat, NULL);
-	GntMenuItem *check = gnt_menuitem_check_new(action->label);
+	GntMenuItem *check = gnt_menuitem_check_new(
+			purple_menu_action_get_label(action));
 	gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(check),
 				purple_blist_node_get_bool((PurpleBlistNode*)chat, "gnt-autojoin"));
 	gnt_menu_add_item(menu, check);
@@ -1268,7 +1272,7 @@
 {
 	PurpleNotifyUserInfo *info = purple_notify_user_info_new();
 	gpointer uihandle;
-	purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
+	purple_notify_user_info_add_pair_plaintext(info, _("Information"), _("Retrieving..."));
 	uihandle = purple_notify_userinfo(conn, name, info, NULL, NULL);
 	purple_notify_user_info_destroy(info);
 
@@ -1783,15 +1787,13 @@
 	presence = purple_buddy_get_presence(buddy);
 
 	if (!full || g_utf8_collate(purple_buddy_get_name(buddy), alias)) {
-		char *esc = g_markup_escape_text(alias, -1);
-		purple_notify_user_info_add_pair(user_info, _("Nickname"), esc);
-		g_free(esc);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), alias);
 	}
 
 	tmp = g_strdup_printf("%s (%s)",
 			purple_account_get_username(account),
 			purple_account_get_protocol_name(account));
-	purple_notify_user_info_add_pair(user_info, _("Account"), tmp);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), tmp);
 	g_free(tmp);
 
 	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
@@ -1806,7 +1808,7 @@
 			time_t idle = purple_presence_get_idle_time(pre);
 			if (idle > 0) {
 				char *st = purple_str_seconds_to_string(time(NULL) - idle);
-				purple_notify_user_info_add_pair(user_info, _("Idle"), st);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), st);
 				g_free(st);
 			}
 		}
--- a/finch/gntblist.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntblist.h	Mon Oct 31 01:25:36 2011 +0000
@@ -115,15 +115,12 @@
  * @param name   The user to get information about.
  *
  * @return  Returns the ui-handle for the userinfo notification.
- *
- * @since 2.1.0
  */
 gpointer finch_retrieve_user_info(PurpleConnection *conn, const char *name);
 
 /**
  * Get the tree list of the buddy list.
  * @return  The GntTree widget.
- * @since 2.4.0
  */
 GntTree * finch_blist_get_tree(void);
 
@@ -131,7 +128,6 @@
  * Add an alternate buddy list manager.
  *
  * @param manager   The alternate buddylist manager.
- * @since 2.4.0
  */
 void finch_blist_install_manager(const FinchBlistManager *manager);
 
@@ -139,7 +135,6 @@
  * Remove an alternate buddy list manager.
  *
  * @param manager   The buddy list manager to remove.
- * @since 2.4.0
  */
 void finch_blist_uninstall_manager(const FinchBlistManager *manager);
 
@@ -149,7 +144,6 @@
  * @param id   The identifier for the desired buddy list manager.
  *
  * @return  The manager with the requested identifier, if available. @c NULL otherwise.
- * @since 2.4.0
  */
 FinchBlistManager * finch_blist_manager_find(const char *id);
 
@@ -157,7 +151,6 @@
  * Request the active buddy list manager to add a node.
  *
  * @param node  The node to add
- * @since 2.4.0
  */
 void finch_blist_manager_add_node(PurpleBlistNode *node);
 
--- a/finch/gntconn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntconn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -165,7 +165,6 @@
 	NULL, /* connected */
 	NULL, /* disconnected */
 	NULL, /* notice */
-	NULL,
 	NULL, /* network_connected */
 	NULL, /* network_disconnected */
 	finch_connection_report_disconnect,
--- a/finch/gntconv.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntconv.c	Mon Oct 31 01:25:36 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);
 		}
@@ -282,7 +282,7 @@
 		return;
 
 	im = PURPLE_CONV_IM(conv);
-	ggc = FINCH_GET_DATA(conv);
+	ggc = FINCH_CONV(conv);
 
 	if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) {
 		int scroll;
@@ -321,7 +321,7 @@
 	PurpleConversation *conv = find_conv_with_contact(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy));
 	if (conv == NULL)
 		return;
-	generate_send_to_menu(FINCH_GET_DATA(conv));
+	generate_send_to_menu(FINCH_CONV(conv));
 }
 
 static void
@@ -333,7 +333,7 @@
 		PurpleConversation *cc = find_conv_with_contact(
 				purple_conversation_get_account(conv), purple_conversation_get_name(conv));
 		if (cc)
-			generate_send_to_menu(FINCH_GET_DATA(cc));
+			generate_send_to_menu(FINCH_CONV(cc));
 		list = list->next;
 	}
 
@@ -398,7 +398,7 @@
 static void
 cleared_message_history_cb(PurpleConversation *conv, gpointer data)
 {
-	FinchConv *ggc = FINCH_GET_DATA(conv);
+	FinchConv *ggc = FINCH_CONV(conv);
 	if (ggc)
 		gnt_text_view_clear(GNT_TEXT_VIEW(ggc->tv));
 }
@@ -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
@@ -749,7 +749,7 @@
 static void
 finch_create_conversation(PurpleConversation *conv)
 {
-	FinchConv *ggc = FINCH_GET_DATA(conv);
+	FinchConv *ggc = FINCH_CONV(conv);
 	char *title;
 	PurpleConversationType type;
 	PurpleConversation *cc;
@@ -763,8 +763,8 @@
 
 	account = purple_conversation_get_account(conv);
 	cc = find_conv_with_contact(account, purple_conversation_get_name(conv));
-	if (cc && FINCH_GET_DATA(cc))
-		ggc = FINCH_GET_DATA(cc);
+	if (cc && FINCH_CONV(cc))
+		ggc = FINCH_CONV(cc);
 	else
 		ggc = g_new0(FinchConv, 1);
 
@@ -776,9 +776,9 @@
 
 	ggc->list = g_list_prepend(ggc->list, conv);
 	ggc->active_conv = conv;
-	FINCH_SET_DATA(conv, ggc);
+	purple_conversation_set_ui_data(conv, ggc);
 
-	if (cc && FINCH_GET_DATA(cc) && cc != conv) {
+	if (cc && FINCH_CONV(cc) && cc != conv) {
 		finch_conversation_set_active(conv);
 		return;
 	}
@@ -885,7 +885,7 @@
 finch_destroy_conversation(PurpleConversation *conv)
 {
 	/* do stuff here */
-	FinchConv *ggc = FINCH_GET_DATA(conv);
+	FinchConv *ggc = FINCH_CONV(conv);
 	ggc->list = g_list_remove(ggc->list, conv);
 	if (ggc->list && conv == ggc->active_conv) {
 		ggc->active_conv = ggc->list->data;
@@ -905,7 +905,7 @@
 finch_write_common(PurpleConversation *conv, const char *who, const char *message,
 		PurpleMessageFlags flags, time_t mtime)
 {
-	FinchConv *ggconv = FINCH_GET_DATA(conv);
+	FinchConv *ggconv = FINCH_CONV(conv);
 	char *strip, *newline;
 	GntTextFormatFlags fl = 0;
 	int pos;
@@ -1069,7 +1069,7 @@
 static void
 finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arrivals)
 {
-	FinchConv *ggc = FINCH_GET_DATA(conv);
+	FinchConv *ggc = FINCH_CONV(conv);
 	GntEntry *entry = GNT_ENTRY(ggc->entry);
 
 	if (!new_arrivals)
@@ -1084,10 +1084,10 @@
 		for (iter = users; iter; iter = iter->next)
 		{
 			PurpleConvChatBuddy *cbuddy = iter->data;
-			char *str;
+			const char *str;
 
-			if ((str = cbuddy->alias) == NULL)
-				str = cbuddy->name;
+			if ((str = purple_conv_chat_cb_get_alias(cbuddy)) == NULL)
+				str = purple_conv_chat_cb_get_name(cbuddy);
 			g_string_append_printf(string, "[ %s ]", str);
 		}
 
@@ -1100,10 +1100,10 @@
 	{
 		PurpleConvChatBuddy *cbuddy = users->data;
 		GntTree *tree = GNT_TREE(ggc->u.chat->userlist);
-		gnt_entry_add_suggest(entry, cbuddy->name);
-		gnt_entry_add_suggest(entry, cbuddy->alias);
-		gnt_tree_add_row_after(tree, g_strdup(cbuddy->name),
-				gnt_tree_create_row(tree, chat_flag_text(cbuddy->flags), cbuddy->alias), NULL, NULL);
+		gnt_entry_add_suggest(entry, purple_conv_chat_cb_get_name(cbuddy));
+		gnt_entry_add_suggest(entry, purple_conv_chat_cb_get_alias(cbuddy));
+		gnt_tree_add_row_after(tree, g_strdup(purple_conv_chat_cb_get_name(cbuddy)),
+				gnt_tree_create_row(tree, chat_flag_text(purple_conv_chat_cb_get_flags(cbuddy)), purple_conv_chat_cb_get_alias(cbuddy)), NULL, NULL);
 	}
 }
 
@@ -1111,7 +1111,7 @@
 finch_chat_rename_user(PurpleConversation *conv, const char *old, const char *new_n, const char *new_a)
 {
 	/* Update the name for string completion */
-	FinchConv *ggc = FINCH_GET_DATA(conv);
+	FinchConv *ggc = FINCH_CONV(conv);
 	GntEntry *entry = GNT_ENTRY(ggc->entry);
 	GntTree *tree = GNT_TREE(ggc->u.chat->userlist);
 	PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), new_n);
@@ -1122,14 +1122,14 @@
 	gnt_entry_add_suggest(entry, new_n);
 	gnt_entry_add_suggest(entry, new_a);
 	gnt_tree_add_row_after(tree, g_strdup(new_n),
-			gnt_tree_create_row(tree, chat_flag_text(cb->flags), new_a), NULL, NULL);
+			gnt_tree_create_row(tree, chat_flag_text(purple_conv_chat_cb_get_flags(cb)), new_a), NULL, NULL);
 }
 
 static void
 finch_chat_remove_users(PurpleConversation *conv, GList *list)
 {
 	/* Remove the name from string completion */
-	FinchConv *ggc = FINCH_GET_DATA(conv);
+	FinchConv *ggc = FINCH_CONV(conv);
 	GntEntry *entry = GNT_ENTRY(ggc->entry);
 	for (; list; list = list->next) {
 		GntTree *tree = GNT_TREE(ggc->u.chat->userlist);
@@ -1142,8 +1142,8 @@
 finch_chat_update_user(PurpleConversation *conv, const char *user)
 {
 	PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), user);
-	FinchConv *ggc = FINCH_GET_DATA(conv);
-	gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(cb->flags));
+	FinchConv *ggc = FINCH_CONV(conv);
+	gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(purple_conv_chat_cb_get_flags(cb)));
 }
 
 static void
@@ -1368,7 +1368,7 @@
 static PurpleCmdRet
 users_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data)
 {
-	FinchConv *fc = FINCH_GET_DATA(conv);
+	FinchConv *fc = FINCH_CONV(conv);
 	FinchConvChat *ch;
 	if (!fc)
 		return PURPLE_CMD_RET_FAILED;
@@ -1494,7 +1494,7 @@
 
 void finch_conversation_set_active(PurpleConversation *conv)
 {
-	FinchConv *ggconv = FINCH_GET_DATA(conv);
+	FinchConv *ggconv = FINCH_CONV(conv);
 	PurpleAccount *account;
 	char *title;
 
@@ -1513,7 +1513,7 @@
 
 void finch_conversation_set_info_widget(PurpleConversation *conv, GntWidget *widget)
 {
-	FinchConv *fc = FINCH_GET_DATA(conv);
+	FinchConv *fc = FINCH_CONV(conv);
 	int height, width;
 
 	gnt_box_remove_all(GNT_BOX(fc->info));
--- a/finch/gntconv.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntconv.h	Mon Oct 31 01:25:36 2011 +0000
@@ -33,7 +33,7 @@
 #include "conversation.h"
 
 /* Grabs the conv out of a PurpleConverstation */
-#define FINCH_CONV(conv) ((FinchConv *)(conv)->ui_data)
+#define FINCH_CONV(conv) ((FinchConv *)purple_conversation_get_ui_data(conv))
 
 /***************************************************************************
  * @name GNT Conversations API
--- a/finch/gntft.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntft.c	Mon Oct 31 01:25:36 2011 +0000
@@ -42,9 +42,6 @@
 #include "gntft.h"
 #include "prefs.h"
 
-#define FINCHXFER(xfer) \
-	(PurpleGntXferUiData *)FINCH_GET_DATA(xfer)
-
 typedef struct
 {
 	gboolean keep_open;
@@ -152,7 +149,7 @@
 		while (iter) {
 			PurpleXfer *xfer = iter->data;
 			iter = iter->next;
-			if (purple_xfer_is_completed(xfer) || purple_xfer_is_canceled(xfer))
+			if (purple_xfer_is_completed(xfer) || purple_xfer_is_cancelled(xfer))
 			finch_xfer_dialog_remove_xfer(xfer);
 		}
 	}
@@ -163,7 +160,7 @@
 {
 	PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree));
 	if (selected_xfer && (purple_xfer_is_completed(selected_xfer) ||
-				purple_xfer_is_canceled(selected_xfer))) {
+				purple_xfer_is_cancelled(selected_xfer))) {
 		finch_xfer_dialog_remove_xfer(selected_xfer);
 	}
 }
@@ -262,7 +259,7 @@
 
 	for (iter = purple_xfers_get_all(); iter; iter = iter->next) {
 		PurpleXfer *xfer = (PurpleXfer *)iter->data;
-		PurpleGntXferUiData *data = FINCHXFER(xfer);
+		PurpleGntXferUiData *data = purple_xfer_get_ui_data(xfer);
 		if (data->in_list) {
 			finch_xfer_dialog_add_xfer(xfer);
 			finch_xfer_dialog_update_xfer(xfer);
@@ -302,7 +299,7 @@
 
 	purple_xfer_ref(xfer);
 
-	data = FINCHXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 	data->in_list = TRUE;
 
 	finch_xfer_dialog_show();
@@ -340,7 +337,7 @@
 	g_return_if_fail(xfer_dialog != NULL);
 	g_return_if_fail(xfer != NULL);
 
-	data = FINCHXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 
 	if (data == NULL)
 		return;
@@ -370,7 +367,7 @@
 	g_return_if_fail(xfer_dialog != NULL);
 	g_return_if_fail(xfer != NULL);
 
-	data = FINCHXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 
 	if (data == NULL)
 		return;
@@ -385,7 +382,7 @@
 
 	update_title_progress();
 
-	if (purple_xfer_is_canceled(xfer))
+	if (purple_xfer_is_cancelled(xfer))
 		status = _("Cancelled");
 	else
 		status = _("Failed");
@@ -416,7 +413,7 @@
 	g_return_if_fail(xfer_dialog != NULL);
 	g_return_if_fail(xfer != NULL);
 
-	if ((data = FINCHXFER(xfer)) == NULL)
+	if ((data = purple_xfer_get_ui_data(xfer)) == NULL)
 		return;
 
 	if (data->in_list == FALSE || data->notified)
@@ -471,9 +468,9 @@
 {
 	PurpleGntXferUiData *data;
 
-	/* This is where we're setting xfer->ui_data for the first time. */
+	/* This is where we're setting xfer's "ui_data" for the first time. */
 	data = g_new0(PurpleGntXferUiData, 1);
-	FINCH_SET_DATA(xfer, data);
+	purple_xfer_set_ui_data(xfer, data);
 }
 
 static void
@@ -481,11 +478,11 @@
 {
 	PurpleGntXferUiData *data;
 
-	data = FINCHXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 	if (data) {
 		g_free(data->name);
 		g_free(data);
-		FINCH_SET_DATA(xfer, NULL);
+		purple_xfer_set_ui_data(xfer, NULL);
 	}
 }
 
--- a/finch/gntnotify.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntnotify.c	Mon Oct 31 01:25:36 2011 +0000
@@ -290,7 +290,7 @@
 
 	text = g_string_new("<span>");
 
-	for (l = purple_notify_user_info_get_entries(user_info); l != NULL;
+	for (l = purple_notify_user_info_get_entries(user_info)->head; l != NULL;
 			l = l->next) {
 		PurpleNotifyUserInfoEntry *user_info_entry = l->data;
 		PurpleNotifyUserInfoEntryType type = purple_notify_user_info_entry_get_type(user_info_entry);
@@ -429,7 +429,10 @@
 	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);
 		i++;
 	}
 
--- a/finch/gntprefs.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntprefs.c	Mon Oct 31 01:25:36 2011 +0000
@@ -62,14 +62,6 @@
 
 void finch_prefs_update_old()
 {
-	const char *str = NULL;
-
-	purple_prefs_rename("/gaim/gnt", "/finch");
-	purple_prefs_rename("/purple/gnt", "/finch");
-
-	if ((str = purple_prefs_get_string("/purple/away/idle_reporting")) &&
-			strcmp(str, "gaim") == 0)
-		purple_prefs_set_string("/purple/away/idle_reporting", "purple");
 }
 
 typedef struct
--- a/finch/gntrequest.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntrequest.c	Mon Oct 31 01:25:36 2011 +0000
@@ -41,12 +41,6 @@
 #include "debug.h"
 #include "util.h"
 
-/* XXX: Until gobjectification ... */
-#undef FINCH_GET_DATA
-#undef FINCH_SET_DATA
-#define FINCH_GET_DATA(obj)  purple_request_field_get_ui_data(obj)
-#define FINCH_SET_DATA(obj, data)  purple_request_field_set_ui_data(obj, data)
-
 typedef struct
 {
 	void *user_data;
@@ -323,26 +317,26 @@
 				continue;
 			if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
 			{
-				GntWidget *check = FINCH_GET_DATA(field);
+				GntWidget *check = purple_request_field_get_ui_data(field);
 				gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check));
 				purple_request_field_bool_set_value(field, value);
 			}
 			else if (type == PURPLE_REQUEST_FIELD_STRING)
 			{
-				GntWidget *entry = FINCH_GET_DATA(field);
+				GntWidget *entry = purple_request_field_get_ui_data(field);
 				const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
 				purple_request_field_string_set_value(field, (text && *text) ? text : NULL);
 			}
 			else if (type == PURPLE_REQUEST_FIELD_INTEGER)
 			{
-				GntWidget *entry = FINCH_GET_DATA(field);
+				GntWidget *entry = purple_request_field_get_ui_data(field);
 				const char *text = gnt_entry_get_text(GNT_ENTRY(entry));
 				int value = (text && *text) ? atoi(text) : 0;
 				purple_request_field_int_set_value(field, value);
 			}
 			else if (type == PURPLE_REQUEST_FIELD_CHOICE)
 			{
-				GntWidget *combo = FINCH_GET_DATA(field);
+				GntWidget *combo = purple_request_field_get_ui_data(field);
 				int id;
 				id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)));
 				purple_request_field_choice_set_value(field, id);
@@ -352,7 +346,7 @@
 				GList *list = NULL, *iter;
 				if (purple_request_field_list_get_multi_select(field))
 				{
-					GntWidget *tree = FINCH_GET_DATA(field);
+					GntWidget *tree = purple_request_field_get_ui_data(field);
 
 					iter = purple_request_field_list_get_items(field);
 					for (; iter; iter = iter->next)
@@ -365,7 +359,7 @@
 				}
 				else
 				{
-					GntWidget *combo = FINCH_GET_DATA(field);
+					GntWidget *combo = purple_request_field_get_ui_data(field);
 					gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
 
 					iter = purple_request_field_list_get_items(field);
@@ -384,7 +378,7 @@
 			}
 			else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
 			{
-				GntWidget *combo = FINCH_GET_DATA(field);
+				GntWidget *combo = purple_request_field_get_ui_data(field);
 				PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo));
 				purple_request_field_account_set_value(field, acc);
 			}
@@ -633,36 +627,36 @@
 
 			if (type == PURPLE_REQUEST_FIELD_BOOLEAN)
 			{
-				FINCH_SET_DATA(field, create_boolean_field(field));
+				purple_request_field_set_ui_data(field, create_boolean_field(field));
 			}
 			else if (type == PURPLE_REQUEST_FIELD_STRING)
 			{
-				FINCH_SET_DATA(field, create_string_field(field, &username));
+				purple_request_field_set_ui_data(field, create_string_field(field, &username));
 			}
 			else if (type == PURPLE_REQUEST_FIELD_INTEGER)
 			{
-				FINCH_SET_DATA(field, create_integer_field(field));
+				purple_request_field_set_ui_data(field, create_integer_field(field));
 			}
 			else if (type == PURPLE_REQUEST_FIELD_CHOICE)
 			{
-				FINCH_SET_DATA(field, create_choice_field(field));
+				purple_request_field_set_ui_data(field, create_choice_field(field));
 			}
 			else if (type == PURPLE_REQUEST_FIELD_LIST)
 			{
-				FINCH_SET_DATA(field, create_list_field(field));
+				purple_request_field_set_ui_data(field, create_list_field(field));
 			}
 			else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
 			{
 				accountlist = create_account_field(field);
-				FINCH_SET_DATA(field, accountlist);
+				purple_request_field_set_ui_data(field, accountlist);
 			}
 			else
 			{
-				FINCH_SET_DATA(field, gnt_label_new_with_format(_("Not implemented yet."),
+				purple_request_field_set_ui_data(field, gnt_label_new_with_format(_("Not implemented yet."),
 						GNT_TEXT_FLAG_BOLD));
 			}
 			gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
-			gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(FINCH_GET_DATA(field)));
+			gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(purple_request_field_get_ui_data(field)));
 		}
 		if (grlist->next)
 			gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
--- a/finch/gntrequest.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntrequest.h	Mon Oct 31 01:25:36 2011 +0000
@@ -63,7 +63,6 @@
  * @param field   The request field.
  *
  * @return A GntWidget for the request field.
- * @since 2.4.0
  */
 GntWidget *finch_request_field_get_widget(PurpleRequestField *field);
 /*@}*/
--- a/finch/gntroomlist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntroomlist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -41,6 +41,7 @@
 
 #define PREF_ROOT "/finch/roomlist"
 
+
 /* Yes, just one roomlist at a time. Let's not get greedy. Aight? */
 struct _FinchRoomlist
 {
@@ -146,9 +147,9 @@
 			purple_roomlist_room_join(froomlist.roomlist, room);
 			break;
 		case PURPLE_ROOMLIST_ROOMTYPE_CATEGORY:
-			if (!room->expanded_once) {
+			if (!purple_roomlist_room_get_expanded_once(room)) {
 				purple_roomlist_expand_category(froomlist.roomlist, room);
-				room->expanded_once = TRUE;
+				purple_roomlist_room_set_expanded_once(room, TRUE);
 			}
 			break;
 	}
@@ -343,7 +344,7 @@
 static void
 fl_create(PurpleRoomlist *list)
 {
-	FINCH_SET_DATA(list, &froomlist);
+	purple_roomlist_set_ui_data(list, &froomlist);
 	setup_roomlist(NULL);
 	update_roomlist(list);
 }
--- a/finch/gntsound.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntsound.c	Mon Oct 31 01:25:36 2011 +0000
@@ -150,7 +150,7 @@
 		return ret;
 
 	account = purple_conversation_get_account(conv);
-	nick = g_strdup(purple_normalize(account, chat->nick));
+	nick = g_strdup(purple_normalize(account, purple_conv_chat_get_nick(chat)));
 	name = g_strdup(purple_normalize(account, aname));
 
 	if (g_utf8_collate(nick, name) == 0)
@@ -268,7 +268,7 @@
 	if (chat_nick_matches_name(conv, sender))
 		return;
 
-	if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, chat->nick))
+	if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_conv_chat_get_nick(chat)))
 		play_conv_event(conv, PURPLE_SOUND_CHAT_NICK);
 	else
 		play_conv_event(conv, event);
--- a/finch/gntsound.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/gntsound.h	Mon Oct 31 01:25:36 2011 +0000
@@ -37,8 +37,6 @@
  * Get the name of the active sound profile.
  *
  * @return The name of the profile
- *
- * @since 2.1.0
  */
 const char *finch_sound_get_active_profile(void);
 
@@ -46,8 +44,6 @@
  * Set the active profile.  If the profile doesn't exist, nothing is changed.
  *
  * @param name  The name of the profile
- *
- * @since 2.1.0
  */
 void finch_sound_set_active_profile(const char *name);
 
@@ -56,8 +52,6 @@
  *
  * @return A list of strings denoting sound profile names.
  *         Caller must free the list (but not the data).
- *
- * @since 2.1.0
  */
 GList *finch_sound_get_profiles(void);
 
@@ -66,8 +60,6 @@
  *
  * @return Returns FALSE if preference is set to 'No sound', or if volume is
  *         set to zero.
- *
- * @since 2.2.0
  */
 gboolean finch_sound_is_enabled(void);
 
@@ -75,15 +67,11 @@
  * Gets GNT sound UI ops.
  *
  * @return The UI operations structure.
- *
- * @since 2.1.0
  */
 PurpleSoundUiOps *finch_sound_get_ui_ops(void);
 
 /**
  * Show the sound settings dialog.
- *
- * @since 2.1.0
  */
 void finch_sounds_show_all(void);
 
--- a/finch/libgnt/gntfilesel.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/libgnt/gntfilesel.h	Mon Oct 31 01:25:36 2011 +0000
@@ -81,7 +81,7 @@
 	void (*gnt_reserved4)(void);
 };
 
-typedef enum _GntFileType
+typedef enum
 {
 	GNT_FILE_REGULAR,
 	GNT_FILE_DIR
--- a/finch/libgnt/gntprogressbar.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/libgnt/gntprogressbar.h	Mon Oct 31 01:25:36 2011 +0000
@@ -37,7 +37,7 @@
 #define GNT_IS_PROGRESS_BAR_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GNT_TYPE_PROGRESS_BAR))
 #define GNT_PROGRESS_BAR_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), GNT_TYPE_PROGRESS_BAR, GntProgressBarClass))
 
-typedef enum _GntProgressBarOrientation
+typedef enum
 {
    GNT_PROGRESS_LEFT_TO_RIGHT,
    GNT_PROGRESS_RIGHT_TO_LEFT,
--- a/finch/libgnt/gnttree.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/libgnt/gnttree.h	Mon Oct 31 01:25:36 2011 +0000
@@ -47,7 +47,7 @@
 typedef struct _GntTreeRow		GntTreeRow;
 typedef struct _GntTreeCol		GntTreeCol;
 
-typedef enum _GntTreeColumnFlag {
+typedef enum {
 	GNT_TREE_COLUMN_INVISIBLE    = 1 << 0,
 	GNT_TREE_COLUMN_FIXED_SIZE   = 1 << 1,
 	GNT_TREE_COLUMN_BINARY_DATA  = 1 << 2,
--- a/finch/libgnt/gntwidget.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/libgnt/gntwidget.h	Mon Oct 31 01:25:36 2011 +0000
@@ -49,7 +49,7 @@
 typedef struct _GntWidgetPriv		GntWidgetPriv;
 typedef struct _GntWidgetClass		GntWidgetClass;
 
-typedef enum _GntWidgetFlags
+typedef enum
 {
 	GNT_WIDGET_DESTROYING     = 1 << 0,
 	GNT_WIDGET_CAN_TAKE_FOCUS = 1 << 1,
@@ -69,7 +69,7 @@
 } GntWidgetFlags;
 
 /* XXX: This will probably move elsewhere */
-typedef enum _GntMouseEvent
+typedef enum
 {
 	GNT_LEFT_MOUSE_DOWN = 1,
 	GNT_RIGHT_MOUSE_DOWN,
@@ -80,7 +80,7 @@
 } GntMouseEvent;
 
 /* XXX: I'll have to ask grim what he's using this for in guifications. */
-typedef enum _GntParamFlags
+typedef enum
 {
 	GNT_PARAM_SERIALIZABLE	= 1 << G_PARAM_USER_SHIFT
 } GntParamFlags;
--- a/finch/libgnt/gntwm.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/libgnt/gntwm.h	Mon Oct 31 01:25:36 2011 +0000
@@ -41,7 +41,7 @@
 #define GNT_IS_WM_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WM))
 #define GNT_WM_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WM, GntWMClass))
 
-typedef enum _GntKeyPressMode
+typedef enum
 {
 	GNT_KP_MODE_NORMAL,
 	GNT_KP_MODE_RESIZE,
--- a/finch/plugins/gntgf.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/plugins/gntgf.c	Mon Oct 31 01:25:36 2011 +0000
@@ -168,7 +168,7 @@
 		beep();
 
 	if (conv != NULL) {
-		FinchConv *fc = conv->ui_data;
+		FinchConv *fc = FINCH_CONV(conv);
 		if (gnt_widget_has_focus(fc->window))
 			return;
 	}
@@ -256,7 +256,7 @@
 	if (flags & PURPLE_MESSAGE_WHISPER)
 		return;
 
-	nick = PURPLE_CONV_CHAT(conv)->nick;
+	nick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(conv));
 
 	if (g_utf8_collate(sender, nick) == 0)
 		return;
--- a/finch/plugins/gnttinyurl.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/plugins/gnttinyurl.c	Mon Oct 31 01:25:36 2011 +0000
@@ -319,7 +319,7 @@
 			url = g_strdup_printf("%s%s", purple_prefs_get_string(PREF_URL), purple_url_encode(tmp));
 		}
 		g_free(tmp);
-		purple_util_fetch_url(url, TRUE, "finch", FALSE, url_fetched, cbdata);
+		purple_util_fetch_url(url, TRUE, "finch", FALSE, -1, url_fetched, cbdata);
 		i = gnt_text_view_get_lines_below(tv);
 		str = g_strdup_printf(_("\nFetching TinyURL..."));
 		gnt_text_view_append_text_with_tag((tv), str, GNT_TEXT_FLAG_DIM, cbdata->tag);
@@ -383,7 +383,7 @@
 	/* Store the return value of _fetch_url and destroy that when win is
 	   destroyed, so that the callback for _fetch_url does not try to molest a
 	   non-existent window */
-	urlcb = purple_util_fetch_url(fullurl, TRUE, "finch", FALSE, tinyurl_notify_fetch_cb, win);
+	urlcb = purple_util_fetch_url(fullurl, TRUE, "finch", FALSE, -1, tinyurl_notify_fetch_cb, win);
 	g_free(fullurl);
 	g_signal_connect_swapped(G_OBJECT(win), "destroy",
 			G_CALLBACK(purple_util_fetch_url_cancel), urlcb);
--- a/finch/plugins/lastlog.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/finch/plugins/lastlog.c	Mon Oct 31 01:25:36 2011 +0000
@@ -60,7 +60,7 @@
 static PurpleCmdRet
 lastlog_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer null)
 {
-	FinchConv *ggconv = conv->ui_data;
+	FinchConv *ggconv = FINCH_CONV(conv);
 	char **strings = g_strsplit(GNT_TEXT_VIEW(ggconv->tv)->string->str, "\n", 0);
 	GntWidget *win, *tv;
 	int i, j;
--- a/gaim-uninstalled.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
- 
-Name: Pidgin (Gaim compatibility)
-Description: Pidgin is a GTK2-based instant messenger application.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${pc_top_builddir}/${pcfiledir}/libpurple -I${pc_top_builddir}/${pcfiledir}/pidgin
-Libs: ${pc_top_builddir}/${pcfiledir}/libpurple/libpurple.la
--- a/gaim.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-Name: Pidgin (Gaim compatibility)
-Description: Pidgin is a GTK2-based instant messenger application.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${includedir}/libpurple
-Libs: -L${libdir} -lpurple
--- a/libpurple/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/Makefile.am	Mon Oct 31 01:25:36 2011 +0000
@@ -9,8 +9,8 @@
 		purple-send-async \
 		purple-url-handler \
 		purple.h.in \
-		purple.pc.in \
-		purple-uninstalled.pc.in \
+		purple-3.pc.in \
+		purple-3-uninstalled.pc.in \
 		version.h.in \
 		Makefile.mingw \
 		win32/global.mak \
@@ -30,7 +30,7 @@
 endif
 
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = purple.pc
+pkgconfig_DATA = purple-3.pc
 
 SUBDIRS = $(GCONF_DIR) plugins protocols ciphers . tests example
 
@@ -117,7 +117,6 @@
 	desktopitem.h \
 	eventloop.h \
 	ft.h \
-	gaim-compat.h \
 	idle.h \
 	imgstore.h \
 	log.h \
--- a/libpurple/account.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/account.c	Mon Oct 31 01:25:36 2011 +0000
@@ -41,14 +41,6 @@
 #include "util.h"
 #include "xmlnode.h"
 
-typedef struct
-{
-	PurpleConnectionErrorInfo *current_error;
-} PurpleAccountPrivate;
-
-#define PURPLE_ACCOUNT_GET_PRIVATE(account) \
-	((PurpleAccountPrivate *) (account->priv))
-
 /* TODO: Should use PurpleValue instead of this?  What about "ui"? */
 typedef struct
 {
@@ -361,8 +353,6 @@
 static xmlnode *
 account_to_xmlnode(PurpleAccount *account)
 {
-	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
-
 	xmlnode *node, *child;
 	const char *tmp;
 	PurplePresence *presence;
@@ -419,7 +409,7 @@
 		xmlnode_insert_child(node, child);
 	}
 
-	child = current_error_to_xmlnode(priv->current_error);
+	child = current_error_to_xmlnode(account->current_error);
 	xmlnode_insert_child(node, child);
 
 	return node;
@@ -874,7 +864,7 @@
 		return NULL;
 	}
 
-	ret = purple_account_new(name, _purple_oscar_convert(name, protocol_id)); /* XXX: */
+	ret = purple_account_new(name, protocol_id);
 	g_free(name);
 	g_free(protocol_id);
 
@@ -924,15 +914,6 @@
 		{
 			purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len);
 		}
-		else
-		{
-			/* Try to see if the icon got left behind in the old cache. */
-			g_free(filename);
-			filename = g_build_filename(g_get_home_dir(), ".gaim", "icons", data, NULL);
-			if (g_file_get_contents(filename, &contents, &len, NULL)) {
-				purple_buddy_icons_set_account_icon(ret, (guchar*)contents, len);
-			}
-		}
 
 		g_free(filename);
 		g_free(data);
@@ -1005,7 +986,6 @@
 purple_account_new(const char *username, const char *protocol_id)
 {
 	PurpleAccount *account = NULL;
-	PurpleAccountPrivate *priv = NULL;
 	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleStatusType *status_type;
@@ -1020,8 +1000,6 @@
 
 	account = g_new0(PurpleAccount, 1);
 	PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount);
-	priv = g_new0(PurpleAccountPrivate, 1);
-	account->priv = priv;
 
 	purple_account_set_username(account, username);
 
@@ -1064,7 +1042,6 @@
 void
 purple_account_destroy(PurpleAccount *account)
 {
-	PurpleAccountPrivate *priv = NULL;
 	GList *l;
 
 	g_return_if_fail(account != NULL);
@@ -1095,7 +1072,8 @@
 
 	purple_account_set_status_types(account, NULL);
 
-	purple_presence_destroy(account->presence);
+	if (account->presence)
+		purple_presence_destroy(account->presence);
 
 	if(account->system_log)
 		purple_log_free(account->system_log);
@@ -1110,13 +1088,11 @@
 		account->permit = g_slist_delete_link(account->permit, account->permit);
 	}
 
-	priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
-	PURPLE_DBUS_UNREGISTER_POINTER(priv->current_error);
-	if (priv->current_error) {
-		g_free(priv->current_error->description);
-		g_free(priv->current_error);
+	PURPLE_DBUS_UNREGISTER_POINTER(account->current_error);
+	if (account->current_error) {
+		g_free(account->current_error->description);
+		g_free(account->current_error);
 	}
-	g_free(priv);
 
 	PURPLE_DBUS_UNREGISTER_POINTER(account);
 	g_free(account);
@@ -1615,7 +1591,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,
@@ -2495,6 +2471,24 @@
 	return setting->value.boolean;
 }
 
+gpointer
+purple_account_get_ui_data(const PurpleAccount *account)
+{
+        g_return_val_if_fail(account != NULL, NULL);
+
+        return account->ui_data;
+}
+
+void
+purple_account_set_ui_data(PurpleAccount *account,
+                                 gpointer ui_data)
+{
+        g_return_if_fail(account != NULL);
+
+        account->ui_data = ui_data;
+}
+
+
 PurpleLog *
 purple_account_get_log(PurpleAccount *account, gboolean create)
 {
@@ -2527,7 +2521,7 @@
 }
 
 void
-purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy)
+purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message)
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc;
@@ -2544,40 +2538,13 @@
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (prpl_info != NULL) {
-		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite))
-			prpl_info->add_buddy_with_invite(gc, buddy, purple_buddy_get_group(buddy), NULL);
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy))
-			prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy));
+		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy))
+			prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy), message);
 	}
 }
 
 void
-purple_account_add_buddy_with_invite(PurpleAccount *account, PurpleBuddy *buddy, const char *message)
-{
-	PurplePluginProtocolInfo *prpl_info = NULL;
-	PurpleConnection *gc;
-	PurplePlugin *prpl = NULL;
-
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(buddy != NULL);
-
-	gc = purple_account_get_connection(account);
-	if (gc != NULL)
-		prpl = purple_connection_get_prpl(gc);
-
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info != NULL) {
-		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite))
-			prpl_info->add_buddy_with_invite(gc, buddy, purple_buddy_get_group(buddy), message);
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy))
-			prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy));
-	}
-}
-
-void
-purple_account_add_buddies(PurpleAccount *account, GList *buddies)
+purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message)
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
@@ -2598,73 +2565,13 @@
 			groups = g_list_append(groups, purple_buddy_get_group(buddy));
 		}
 
-		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies_with_invite))
-			prpl_info->add_buddies_with_invite(gc, buddies, groups, NULL);
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies))
-			prpl_info->add_buddies(gc, buddies, groups);
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite)) {
-			GList *curb = buddies, *curg = groups;
-
-			while ((curb != NULL) && (curg != NULL)) {
-				prpl_info->add_buddy_with_invite(gc, curb->data, curg->data, NULL);
-				curb = curb->next;
-				curg = curg->next;
-			}
-		}
+		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies))
+			prpl_info->add_buddies(gc, buddies, groups, message);
 		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) {
 			GList *curb = buddies, *curg = groups;
 
 			while ((curb != NULL) && (curg != NULL)) {
-				prpl_info->add_buddy(gc, curb->data, curg->data);
-				curb = curb->next;
-				curg = curg->next;
-			}
-		}
-
-		g_list_free(groups);
-	}
-}
-
-void
-purple_account_add_buddies_with_invite(PurpleAccount *account, GList *buddies, const char *message)
-{
-	PurplePluginProtocolInfo *prpl_info = NULL;
-	PurpleConnection *gc = purple_account_get_connection(account);
-	PurplePlugin *prpl = NULL;
-
-	if (gc != NULL)
-		prpl = purple_connection_get_prpl(gc);
-
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info) {
-		GList *cur, *groups = NULL;
-
-		/* Make a list of what group each buddy is in */
-		for (cur = buddies; cur != NULL; cur = cur->next) {
-			PurpleBuddy *buddy = cur->data;
-			groups = g_list_append(groups, purple_buddy_get_group(buddy));
-		}
-
-		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies_with_invite))
-			prpl_info->add_buddies_with_invite(gc, buddies, groups, message);
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite)) {
-			GList *curb = buddies, *curg = groups;
-
-			while ((curb != NULL) && (curg != NULL)) {
-				prpl_info->add_buddy_with_invite(gc, curb->data, curg->data, message);
-				curb = curb->next;
-				curg = curg->next;
-			}
-		}
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies))
-			prpl_info->add_buddies(gc, buddies, groups);
-		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) {
-			GList *curb = buddies, *curg = groups;
-
-			while ((curb != NULL) && (curg != NULL)) {
-				prpl_info->add_buddy(gc, curb->data, curg->data);
+				prpl_info->add_buddy(gc, curb->data, curg->data, message);
 				curb = curb->next;
 				curg = curg->next;
 			}
@@ -2804,18 +2711,16 @@
 static void
 set_current_error(PurpleAccount *account, PurpleConnectionErrorInfo *new_err)
 {
-	PurpleAccountPrivate *priv;
 	PurpleConnectionErrorInfo *old_err;
 
 	g_return_if_fail(account != NULL);
 
-	priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
-	old_err = priv->current_error;
+	old_err = account->current_error;
 
 	if(new_err == old_err)
 		return;
 
-	priv->current_error = new_err;
+	account->current_error = new_err;
 
 	purple_signal_emit(purple_accounts_get_handle(),
 	                   "account-error-changed",
@@ -2857,8 +2762,7 @@
 const PurpleConnectionErrorInfo *
 purple_account_get_current_error(PurpleAccount *account)
 {
-	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
-	return priv->current_error;
+	return account->current_error;
 }
 
 void
--- a/libpurple/account.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/account.h	Mon Oct 31 01:25:36 2011 +0000
@@ -168,7 +168,7 @@
 	PurpleAccountRegistrationCb registration_cb;
 	void *registration_cb_user_data;
 
-	gpointer priv;              /**< Pointer to opaque private data. */
+	PurpleConnectionErrorInfo *current_error;	/**< Errors */
 };
 
 #ifdef __cplusplus
@@ -433,8 +433,6 @@
  *
  * @param account      The account.
  * @param privacy_type The privacy type.
- *
- * @since 2.7.0
  */
 void purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type);
 
@@ -491,8 +489,6 @@
  *                   is successfully set on the server (or NULL).
  * @param failure_cb A callback which will be called if the alias
  *                   is not successfully set on the server (or NULL).
- *
- * @since 2.7.0
  */
 void purple_account_set_public_alias(PurpleAccount *account,
 	const char *alias, PurpleSetPublicAliasSuccessCallback success_cb,
@@ -506,7 +502,6 @@
  * @param success_cb A callback which will be called with the alias
  * @param failure_cb A callback which will be called if the prpl is
  *                   unable to retrieve the server-side alias.
- * @since 2.7.0
  */
 void purple_account_get_public_alias(PurpleAccount *account,
 	PurpleGetPublicAliasSuccessCallback success_cb,
@@ -542,8 +537,6 @@
  *
  * @param account The account.
  * @param setting The setting to remove.
- *
- * @since 2.6.0
  */
 void purple_account_remove_setting(PurpleAccount *account, const char *setting);
 
@@ -610,6 +603,25 @@
 							  const char *name, gboolean value);
 
 /**
+ * Returns the UI data associated with this account.
+ *
+ * @param account The account.
+ *
+ * @return The UI data associated with this object.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libuprple core.
+ */
+gpointer purple_account_get_ui_data(const PurpleAccount *account);
+
+/**
+ * Set the UI data associated with this account.
+ *
+ * @param account The account.
+ * @param ui_data A pointer to associate with this object.
+ */
+void purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data);
+
+/**
  * Returns whether or not the account is connected.
  *
  * @param account The account.
@@ -717,8 +729,6 @@
  * @param account The account.
  *
  * @return The name to display.
- *
- * @since 2.7.0
  */
 const gchar *purple_account_get_name_for_display(const PurpleAccount *account);
 
@@ -767,8 +777,6 @@
  * @param account   The account.
  *
  * @return The privacy type.
- *
- * @since 2.7.0
  */
 PurplePrivacyType purple_account_get_privacy_type(const PurpleAccount *account);
 
@@ -958,40 +966,18 @@
  *
  * @param account The account.
  * @param buddy The buddy to add.
- *
- * @deprecated Use purple_account_add_buddy_with_invite and \c NULL message.
+ * @param message The invite message.  This may be ignored by a prpl.
  */
-void purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy);
-/**
- * Adds a buddy to the server-side buddy list for the specified account.
- *
- * @param account The account.
- * @param buddy The buddy to add.
- * @param message The invite message.  This may be ignored by a prpl.
- *
- * @since 2.8.0
- */
-void purple_account_add_buddy_with_invite(PurpleAccount *account, PurpleBuddy *buddy, const char *message);
+void purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message);
 
 /**
  * Adds a list of buddies to the server-side buddy list.
  *
  * @param account The account.
  * @param buddies The list of PurpleBlistNodes representing the buddies to add.
- *
- * @deprecated Use purple_account_add_buddies_with_invite and \c NULL message.
+ * @param message The invite message.  This may be ignored by a prpl.
  */
-void purple_account_add_buddies(PurpleAccount *account, GList *buddies);
-/**
- * Adds a list of buddies to the server-side buddy list.
- *
- * @param account The account.
- * @param buddies The list of PurpleBlistNodes representing the buddies to add.
- * @param message The invite message.  This may be ignored by a prpl.
- *
- * @since 2.8.0
- */
-void purple_account_add_buddies_with_invite(PurpleAccount *account, GList *buddies, const char *message);
+void purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message);
 
 /**
  * Removes a buddy from the server-side buddy list.
--- a/libpurple/accountopt.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/accountopt.c	Mon Oct 31 01:25:36 2011 +0000
@@ -28,6 +28,51 @@
 #include "accountopt.h"
 #include "util.h"
 
+/**
+ * An option for an account.
+ *
+ * This is set by protocol plugins, and appears in the account settings
+ * dialogs.
+ */
+struct _PurpleAccountOption
+{
+	PurplePrefType type;      /**< The type of value.                     */
+
+	char *text;             /**< The text that will appear to the user. */
+	char *pref_name;        /**< The name of the associated preference. */
+
+	union
+	{
+		gboolean boolean;   /**< The default boolean value.             */
+		int integer;        /**< The default integer value.             */
+		char *string;       /**< The default string value.              */
+		GList *list;        /**< The default list value.                */
+
+	} default_value;
+
+	gboolean masked;        /**< Whether the value entered should be
+	                         *   obscured from view (for passwords and
+	                         *   similar options)
+	                         */
+};
+
+/**
+ * A username split.
+ *
+ * This is used by some protocols to separate the fields of the username
+ * into more human-readable components.
+ */
+struct _PurpleAccountUserSplit
+{
+	char *text;             /**< The text that will appear to the user. */
+	char *default_value;    /**< The default value.                     */
+	char  field_sep;        /**< The field separator.                   */
+	gboolean reverse;       /**< TRUE if the separator should be found
+							  starting a the end of the string, FALSE
+							  otherwise                                 */
+};
+
+
 PurpleAccountOption *
 purple_account_option_new(PurplePrefType type, const char *text,
 						const char *pref_name)
--- a/libpurple/accountopt.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/accountopt.h	Mon Oct 31 01:25:36 2011 +0000
@@ -28,50 +28,15 @@
 
 #include "prefs.h"
 
-/**
- * An option for an account.
- *
- * This is set by protocol plugins, and appears in the account settings
- * dialogs.
- */
-typedef struct
-{
-	PurplePrefType type;      /**< The type of value.                     */
-
-	char *text;             /**< The text that will appear to the user. */
-	char *pref_name;        /**< The name of the associated preference. */
-
-	union
-	{
-		gboolean boolean;   /**< The default boolean value.             */
-		int integer;        /**< The default integer value.             */
-		char *string;       /**< The default string value.              */
-		GList *list;        /**< The default list value.                */
-
-	} default_value;
+/**************************************************************************/
+/** Data Structures                                                       */
+/**************************************************************************/
 
-	gboolean masked;        /**< Whether the value entered should be
-	                         *   obscured from view (for passwords and
-	                         *   similar options)
-	                         */
-} PurpleAccountOption;
+/** @copydoc _PurpleAccountOption */
+typedef struct _PurpleAccountOption		PurpleAccountOption;
+/** @copydoc _PurpleAccountUserSplit */
+typedef struct _PurpleAccountUserSplit	PurpleAccountUserSplit;
 
-/**
- * A username split.
- *
- * This is used by some protocols to separate the fields of the username
- * into more human-readable components.
- */
-typedef struct
-{
-	char *text;             /**< The text that will appear to the user. */
-	char *default_value;    /**< The default value.                     */
-	char  field_sep;        /**< The field separator.                   */
-	gboolean reverse;       /**< TRUE if the separator should be found
-							  starting a the end of the string, FALSE
-							  otherwise                                 */
-
-} PurpleAccountUserSplit;
 
 #ifdef __cplusplus
 extern "C" {
--- a/libpurple/blist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/blist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -314,7 +314,7 @@
 	node = xmlnode_new("account");
 	xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account));
 	xmlnode_set_attrib(node, "name", purple_account_get_username(account));
-	g_snprintf(buf, sizeof(buf), "%d", account->perm_deny);
+	g_snprintf(buf, sizeof(buf), "%d", purple_account_get_privacy_type(account));
 	xmlnode_set_attrib(node, "mode", buf);
 
 	for (cur = account->permit; cur; cur = cur->next)
@@ -461,19 +461,16 @@
 	PurpleAccount *account;
 	PurpleBuddy *buddy;
 	char *name = NULL, *alias = NULL;
-	const char *acct_name, *proto, *protocol;
+	const char *acct_name, *proto;
 	xmlnode *x;
 
 	acct_name = xmlnode_get_attrib(bnode, "account");
-	protocol = xmlnode_get_attrib(bnode, "protocol");
-	protocol = _purple_oscar_convert(acct_name, protocol); /* XXX: Remove */
 	proto = xmlnode_get_attrib(bnode, "proto");
-	proto = _purple_oscar_convert(acct_name, proto); /* XXX: Remove */
-
-	if (!acct_name || (!proto && !protocol))
+
+	if (!acct_name || !proto)
 		return;
 
-	account = purple_accounts_find(acct_name, proto ? proto : protocol);
+	account = purple_accounts_find(acct_name, proto);
 
 	if (!account)
 		return;
@@ -532,19 +529,18 @@
 {
 	PurpleChat *chat;
 	PurpleAccount *account;
-	const char *acct_name, *proto, *protocol;
+	const char *acct_name, *proto;
 	xmlnode *x;
 	char *alias = NULL;
 	GHashTable *components;
 
 	acct_name = xmlnode_get_attrib(cnode, "account");
-	protocol = xmlnode_get_attrib(cnode, "protocol");
 	proto = xmlnode_get_attrib(cnode, "proto");
 
-	if (!acct_name || (!proto && !protocol))
+	if (!acct_name || !proto)
 		return;
 
-	account = purple_accounts_find(acct_name, proto ? proto : protocol);
+	account = purple_accounts_find(acct_name, proto);
 
 	if (!account)
 		return;
@@ -630,23 +626,22 @@
 			xmlnode *x;
 			PurpleAccount *account;
 			int imode;
-			const char *acct_name, *proto, *mode, *protocol;
+			const char *acct_name, *proto, *mode;
 
 			acct_name = xmlnode_get_attrib(anode, "name");
-			protocol = xmlnode_get_attrib(anode, "protocol");
 			proto = xmlnode_get_attrib(anode, "proto");
 			mode = xmlnode_get_attrib(anode, "mode");
 
-			if (!acct_name || (!proto && !protocol) || !mode)
+			if (!acct_name || !proto || !mode)
 				continue;
 
-			account = purple_accounts_find(acct_name, proto ? proto : protocol);
+			account = purple_accounts_find(acct_name, proto);
 
 			if (!account)
 				continue;
 
 			imode = atoi(mode);
-			account->perm_deny = (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL);
+			purple_account_set_privacy_type(account, (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL));
 
 			for (x = anode->child; x; x = x->next) {
 				char *name;
@@ -961,12 +956,6 @@
 		ops->update(purplebuddylist, node);
 }
 
-void
-purple_blist_update_buddy_icon(PurpleBuddy *buddy)
-{
-	purple_blist_update_node_icon((PurpleBlistNode *)buddy);
-}
-
 /*
  * TODO: Maybe remove the call to this from server.c and call it
  * from oscar.c and toc.c instead?
@@ -1318,7 +1307,7 @@
 
 				purple_account_remove_buddies(account, buddies, groups);
 				g_list_free(groups);
-				purple_account_add_buddies(account, buddies);
+				purple_account_add_buddies(account, buddies, NULL);
 			}
 
 			g_list_free(buddies);
@@ -1748,11 +1737,6 @@
 	return (PurpleGroup *)(((PurpleBlistNode *)contact)->parent);
 }
 
-void purple_contact_set_alias(PurpleContact *contact, const char *alias)
-{
-	purple_blist_alias_contact(contact,alias);
-}
-
 const char *purple_contact_get_alias(PurpleContact* contact)
 {
 	g_return_val_if_fail(contact != NULL, NULL);
@@ -2380,26 +2364,6 @@
 	return NULL;
 }
 
-const char *purple_buddy_get_local_alias(PurpleBuddy *buddy)
-{
-	PurpleContact *c;
-
-	g_return_val_if_fail(buddy != NULL, NULL);
-
-	/* Search for an alias for the buddy. In order of precedence: */
-	/* The buddy alias */
-	if (buddy->alias != NULL)
-		return buddy->alias;
-
-	/* The contact alias */
-	c = purple_buddy_get_contact(buddy);
-	if ((c != NULL) && (c->alias != NULL))
-		return c->alias;
-
-	/* The buddy's user name (i.e. no alias) */
-	return buddy->name;
-}
-
 const char *purple_chat_get_name(PurpleChat *chat)
 {
 	char *ret = NULL;
--- a/libpurple/blist.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/blist.h	Mon Oct 31 01:25:36 2011 +0000
@@ -75,9 +75,6 @@
 
 } PurpleBlistNodeFlags;
 
-/**
- * @since 2.6.0
- */
 #define PURPLE_BLIST_NODE(obj) ((PurpleBlistNode *)(obj))
 
 #define PURPLE_BLIST_NODE_HAS_FLAG(b, f) (purple_blist_node_get_flags((PurpleBlistNode*)(b)) & (f))
@@ -86,24 +83,12 @@
 #define PURPLE_BLIST_NODE_NAME(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CHAT_NODE  ? purple_chat_get_name((PurpleChat*)n) :        \
 				     purple_blist_node_get_type(n) == PURPLE_BLIST_BUDDY_NODE ? purple_buddy_get_name((PurpleBuddy*)n) : NULL)
 
-/**
- * @since 2.6.0
- */
 #define PURPLE_GROUP(obj) ((PurpleGroup *)(obj))
 
-/**
- * @since 2.6.0
- */
 #define PURPLE_CONTACT(obj) ((PurpleContact *)(obj))
 
-/**
- * @since 2.6.0
- */
 #define PURPLE_BUDDY(obj) ((PurpleBuddy *)(obj))
 
-/**
- * @since 2.6.0
- */
 #define PURPLE_CHAT(obj) ((PurpleChat *)(obj))
 
 #include "account.h"
@@ -226,8 +211,6 @@
 	 * previous libpurple versions.
 	 *
 	 * @param node    The node which has been modified.
-	 *
-	 * @since 2.6.0.
 	 */
 	void (*save_node)(PurpleBlistNode *node);
 
@@ -241,7 +224,6 @@
 	 * previous libpurple versions.
 	 *
 	 * @param node  The node which has been modified.
-	 * @since 2.6.0.
 	 */
 	void (*remove_node)(PurpleBlistNode *node);
 
@@ -256,7 +238,6 @@
 	 *
 	 * @param account  The account whose data to save. If NULL, save all data
 	 *                  for all accounts.
-	 * @since 2.6.0.
 	 */
 	void (*save_account)(PurpleAccount *account);
 
@@ -311,7 +292,6 @@
  *         freeing the list.
  *
  * @see purple_find_buddies
- * @since 2.6.0
  */
 GSList *purple_blist_get_buddies(void);
 
@@ -319,8 +299,6 @@
  * Returns the UI data for the list.
  *
  * @return The UI data for the list.
- *
- * @since 2.6.0
  */
 gpointer purple_blist_get_ui_data(void);
 
@@ -328,8 +306,6 @@
  * Sets the UI data for the list.
  *
  * @param ui_data The UI data for the list.
- *
- * @since 2.6.0
  */
 void purple_blist_set_ui_data(gpointer ui_data);
 
@@ -352,7 +328,7 @@
  *
  * @param node A node.
  * @return  The parent node.
- * @since 2.4.0
+ *
  * @see purple_blist_node_get_first_child
  * @see purple_blist_node_get_sibling_next
  * @see purple_blist_node_get_sibling_prev
@@ -365,7 +341,7 @@
  *
  * @param node A node.
  * @return  The child node.
- * @since 2.4.0
+ *
  * @see purple_blist_node_get_parent
  * @see purple_blist_node_get_sibling_next
  * @see purple_blist_node_get_sibling_prev
@@ -378,7 +354,7 @@
  *
  * @param node A node.
  * @return  The sibling node.
- * @since 2.4.0
+ *
  * @see purple_blist_node_get_parent
  * @see purple_blist_node_get_first_child
  * @see purple_blist_node_get_sibling_prev
@@ -391,7 +367,7 @@
  *
  * @param node A node.
  * @return  The sibling node.
- * @since 2.4.0
+ *
  * @see purple_blist_node_get_parent
  * @see purple_blist_node_get_first_child
  * @see purple_blist_node_get_sibling_next
@@ -404,7 +380,6 @@
  *
  * @param node The node.
  * @return The UI data.
- * @since 2.6.0
  */
 gpointer purple_blist_node_get_ui_data(const PurpleBlistNode *node);
 
@@ -413,8 +388,6 @@
  *
  * @param node The node.
  * @param ui_data The UI data.
- *
- * @since 2.6.0
  */
 void purple_blist_node_set_ui_data(PurpleBlistNode *node, gpointer ui_data);
 
@@ -454,21 +427,9 @@
  * Updates a node's custom icon.
  *
  * @param node  The PurpleBlistNode whose custom icon has changed.
- *
- * @since 2.5.0
  */
 void purple_blist_update_node_icon(PurpleBlistNode *node);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BLIST_C_)
-/**
- * Updates a buddy's icon.
- *
- * @param buddy  The buddy whose buddy icon has changed
- * @deprecated Use purple_blist_update_node_icon() instead.
- */
-void purple_blist_update_buddy_icon(PurpleBuddy *buddy);
-#endif
-
 /**
  * Renames a buddy in the buddy list.
  *
@@ -623,7 +584,6 @@
  * @return      The protocol data.
  *
  * @see purple_buddy_set_protocol_data()
- * @since 2.6.0
  */
 gpointer purple_buddy_get_protocol_data(const PurpleBuddy *buddy);
 
@@ -636,7 +596,6 @@
  * @param data  The data.
  *
  * @see purple_buddy_get_protocol_data()
- * @since 2.6.0
  */
 void purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data);
 
@@ -663,8 +622,6 @@
  *
  * @param buddy The buddy.
  * @return      The media caps.
- *
- * @since 2.7.0
  */
 PurpleMediaCaps purple_buddy_get_media_caps(const PurpleBuddy *buddy);
 
@@ -739,8 +696,6 @@
  *
  * @param contact  The contact
  * @return         The group
- *
- * @since 2.7.0
  */
 PurpleGroup *purple_contact_get_group(const PurpleContact *contact);
 
@@ -774,18 +729,6 @@
  */
 PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BLIST_C_)
-/**
- * Sets the alias for a contact.
- *
- * @param contact  The contact
- * @param alias    The alias to set, or NULL to unset
- *
- * @deprecated Use purple_blist_alias_contact() instead.
- */
-void purple_contact_set_alias(PurpleContact *contact, const char *alias);
-#endif
-
 /**
  * Gets the alias for a contact.
  *
@@ -876,19 +819,6 @@
  */
 const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BLIST_C_)
-/**
- * Returns the correct alias for this user, ignoring server aliases.  Used
- * when a user-recognizable name is required.  In order: buddy's alias; buddy's
- * contact alias; buddy's user name.
- *
- * @param buddy  The buddy whose alias will be returned.
- * @return       The appropriate name or alias.
- * @deprecated   Try purple_buddy_get_alias(), if server aliases are okay.
- */
-const char *purple_buddy_get_local_alias(PurpleBuddy *buddy);
-#endif
-
 /**
  * Returns the correct name to display for a buddy. In order of precedence:
  * the buddy's alias; the buddy's server alias; the buddy's contact alias;
@@ -904,8 +834,6 @@
  *
  * @param buddy  The buddy
  * @return       The local alias for the buddy
- *
- * @since 2.6.0
  */
 const char *purple_buddy_get_local_buddy_alias(PurpleBuddy *buddy);
 
@@ -981,8 +909,6 @@
  * @param chat  The chat.
  *
  * @return  The account the chat belongs to.
- *
- * @since 2.4.0
  */
 PurpleAccount *purple_chat_get_account(PurpleChat *chat);
 
@@ -992,8 +918,6 @@
  * @param chat  The chat.
  *
  * @constreturn  The hashtable.
- *
- * @since 2.4.0
  */
 GHashTable *purple_chat_get_components(PurpleChat *chat);
 
@@ -1211,8 +1135,6 @@
  * @param node The node.
  *
  * @return The type of the node.
- *
- * @since 2.1.0
  */
 PurpleBlistNodeType purple_blist_node_get_type(PurpleBlistNode *node);
 
--- a/libpurple/buddyicon.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/buddyicon.c	Mon Oct 31 01:25:36 2011 +0000
@@ -105,9 +105,6 @@
 /** "Should icons be cached to disk?" */
 static gboolean    icon_caching  = TRUE;
 
-/* For ~/.gaim to ~/.purple migration. */
-static char *old_icons_dir = NULL;
-
 static void delete_buddy_icon_settings(PurpleBlistNode *node, const char *setting_name);
 
 /*
@@ -759,7 +756,7 @@
 	else
 		g_hash_table_remove(pointer_icon_cache, account);
 
-	if (purple_account_is_connected(account))
+	if (!purple_account_is_disconnected(account))
 	{
 		PurpleConnection *gc;
 		PurplePluginProtocolInfo *prpl_info;
@@ -958,31 +955,6 @@
 	return purple_buddy_icons_node_set_custom_icon(node, data, len);
 }
 
-gboolean
-purple_buddy_icons_has_custom_icon(PurpleContact *contact)
-{
-	return purple_buddy_icons_node_has_custom_icon((PurpleBlistNode*)contact);
-}
-
-PurpleStoredImage *
-purple_buddy_icons_find_custom_icon(PurpleContact *contact)
-{
-	return purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact);
-}
-
-PurpleStoredImage *
-purple_buddy_icons_set_custom_icon(PurpleContact *contact, guchar *icon_data,
-                                   size_t icon_len)
-{
-	return purple_buddy_icons_node_set_custom_icon((PurpleBlistNode*)contact, icon_data, icon_len);
-}
-
-void
-_purple_buddy_icon_set_old_icons_dir(const char *dirname)
-{
-	old_icons_dir = g_strdup(dirname);
-}
-
 static void
 delete_buddy_icon_settings(PurpleBlistNode *node, const char *setting_name)
 {
@@ -995,133 +967,6 @@
 	}
 }
 
-static void
-migrate_buddy_icon(PurpleBlistNode *node, const char *setting_name,
-                   const char *dirname, const char *filename)
-{
-	char *path;
-
-	if (filename[0] != '/')
-	{
-		path = g_build_filename(dirname, filename, NULL);
-		if (g_file_test(path, G_FILE_TEST_EXISTS))
-		{
-			g_free(path);
-			return;
-		}
-		g_free(path);
-
-		path = g_build_filename(old_icons_dir, filename, NULL);
-	}
-	else
-		path = g_strdup(filename);
-
-	if (g_file_test(path, G_FILE_TEST_EXISTS))
-	{
-		guchar *icon_data;
-		size_t icon_len;
-		FILE *file;
-		char *new_filename;
-
-		if (!read_icon_file(path, &icon_data, &icon_len))
-		{
-			g_free(path);
-			delete_buddy_icon_settings(node, setting_name);
-			return;
-		}
-
-		if (icon_data == NULL || icon_len <= 0)
-		{
-			/* This really applies to the icon_len check.
-			 * icon_data should never be NULL if
-			 * read_icon_file() returns TRUE. */
-			purple_debug_error("buddyicon", "Empty buddy icon file: %s\n", path);
-			delete_buddy_icon_settings(node, setting_name);
-			g_free(path);
-			return;
-		}
-
-		g_free(path);
-
-		new_filename = purple_util_get_image_filename(icon_data, icon_len);
-		if (new_filename == NULL)
-		{
-			purple_debug_error("buddyicon",
-				"New icon filename is NULL. This should never happen! "
-				"The old filename was: %s\n", path);
-			delete_buddy_icon_settings(node, setting_name);
-			g_return_if_reached();
-		}
-
-		path = g_build_filename(dirname, new_filename, NULL);
-		if ((file = g_fopen(path, "wb")) != NULL)
-		{
-			if (!fwrite(icon_data, icon_len, 1, file))
-			{
-				purple_debug_error("buddyicon", "Error writing %s: %s\n",
-				                   path, g_strerror(errno));
-			}
-			else
-				purple_debug_info("buddyicon", "Wrote migrated cache file: %s\n", path);
-
-			fclose(file);
-		}
-		else
-		{
-			purple_debug_error("buddyicon", "Unable to create file %s: %s\n",
-			                   path, g_strerror(errno));
-			g_free(new_filename);
-			g_free(path);
-
-			delete_buddy_icon_settings(node, setting_name);
-			return;
-		}
-		g_free(path);
-
-		purple_blist_node_set_string(node,
-		                             setting_name,
-		                             new_filename);
-		ref_filename(new_filename);
-
-		g_free(new_filename);
-
-		if (purple_strequal(setting_name, "buddy_icon"))
-		{
-			const char *hash;
-
-			hash = purple_blist_node_get_string(node, "avatar_hash");
-			if (hash != NULL)
-			{
-				purple_blist_node_set_string(node, "icon_checksum", hash);
-				purple_blist_node_remove_setting(node, "avatar_hash");
-			}
-			else
-			{
-				PurpleAccount *account = purple_buddy_get_account((PurpleBuddy *)node);
-				const char *prpl_id = purple_account_get_protocol_id(account);
-
-				if (g_str_equal(prpl_id, "prpl-yahoo") || g_str_equal(prpl_id, "prpl-yahoojp"))
-				{
-					int checksum = purple_blist_node_get_int(node, "icon_checksum");
-					if (checksum != 0)
-					{
-						char *checksum_str = g_strdup_printf("%i", checksum);
-						purple_blist_node_remove_setting(node, "icon_checksum");
-						purple_blist_node_set_string(node, "icon_checksum", checksum_str);
-						g_free(checksum_str);
-					}
-				}
-			}
-		}
-	}
-	else
-	{
-		purple_debug_error("buddyicon", "Old icon file doesn't exist: %s\n", path);
-		delete_buddy_icon_settings(node, setting_name);
-		g_free(path);
-	}
-}
-
 void
 _purple_buddy_icons_account_loaded_cb()
 {
@@ -1153,22 +998,6 @@
 	PurpleBlistNode *node = purple_blist_get_root();
 	const char *dirname = purple_buddy_icons_get_cache_dir();
 
-	/* Doing this once here saves having to check it inside a loop. */
-	if (old_icons_dir != NULL)
-	{
-		if (!g_file_test(dirname, G_FILE_TEST_IS_DIR))
-		{
-			purple_debug_info("buddyicon", "Creating icon cache directory.\n");
-
-			if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
-			{
-				purple_debug_error("buddyicon",
-				                   "Unable to create directory %s: %s\n",
-				                   dirname, g_strerror(errno));
-			}
-		}
-	}
-
 	while (node != NULL)
 	{
 		if (PURPLE_BLIST_NODE_IS_BUDDY(node))
@@ -1178,26 +1007,17 @@
 			filename = purple_blist_node_get_string(node, "buddy_icon");
 			if (filename != NULL)
 			{
-				if (old_icons_dir != NULL)
+				char *path = g_build_filename(dirname, filename, NULL);
+				if (!g_file_test(path, G_FILE_TEST_EXISTS))
 				{
-					migrate_buddy_icon(node,
-					                   "buddy_icon",
-					                   dirname, filename);
+					purple_blist_node_remove_setting(node,
+					                                 "buddy_icon");
+					purple_blist_node_remove_setting(node,
+					                                 "icon_checksum");
 				}
 				else
-				{
-					char *path = g_build_filename(dirname, filename, NULL);
-					if (!g_file_test(path, G_FILE_TEST_EXISTS))
-					{
-						purple_blist_node_remove_setting(node,
-						                                 "buddy_icon");
-						purple_blist_node_remove_setting(node,
-						                                 "icon_checksum");
-					}
-					else
-						ref_filename(filename);
-					g_free(path);
-				}
+					ref_filename(filename);
+				g_free(path);
 			}
 		}
 		else if (PURPLE_BLIST_NODE_IS_CONTACT(node) ||
@@ -1209,24 +1029,15 @@
 			filename = purple_blist_node_get_string(node, "custom_buddy_icon");
 			if (filename != NULL)
 			{
-				if (old_icons_dir != NULL)
+				char *path = g_build_filename(dirname, filename, NULL);
+				if (!g_file_test(path, G_FILE_TEST_EXISTS))
 				{
-					migrate_buddy_icon(node,
-					                   "custom_buddy_icon",
-					                   dirname, filename);
+					purple_blist_node_remove_setting(node,
+					                                 "custom_buddy_icon");
 				}
 				else
-				{
-					char *path = g_build_filename(dirname, filename, NULL);
-					if (!g_file_test(path, G_FILE_TEST_EXISTS))
-					{
-						purple_blist_node_remove_setting(node,
-						                                 "custom_buddy_icon");
-					}
-					else
-						ref_filename(filename);
-					g_free(path);
-				}
+					ref_filename(filename);
+				g_free(path);
 			}
 		}
 		node = purple_blist_node_next(node, TRUE);
@@ -1298,11 +1109,9 @@
 	g_hash_table_destroy(icon_data_cache);
 	g_hash_table_destroy(icon_file_cache);
 	g_hash_table_destroy(pointer_icon_cache);
-	g_free(old_icons_dir);
 	g_free(cache_dir);
 
 	cache_dir = NULL;
-	old_icons_dir = NULL;
 }
 
 void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int *height)
--- a/libpurple/buddyicon.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/buddyicon.h	Mon Oct 31 01:25:36 2011 +0000
@@ -275,7 +275,6 @@
  * @param node The blist node.
  *
  * @return A boolean indicating if @a node has a custom buddy icon.
- * @since 2.5.0
  */
 gboolean
 purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node);
@@ -293,7 +292,6 @@
  * @param node The node.
  *
  * @return The custom buddy icon.
- * @since 2.5.0
  */
 PurpleStoredImage *
 purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node);
@@ -311,7 +309,6 @@
  *
  * @return The icon that was set. The caller does NOT own a reference to this,
  *         and must call purple_imgstore_ref() if it wants one.
- * @since 2.5.0
  */
 PurpleStoredImage *
 purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
@@ -329,45 +326,11 @@
  *
  * @return The icon that was set. The caller does NOT own a reference to this,
  *         and must call purple_imgstore_ref() if it wants one.
- * @since 2.5.0
  */
 PurpleStoredImage *
 purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node,
                                                   const gchar *filename);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BUDDYICON_C_)
-/**
- * PurpleContact version of purple_buddy_icons_node_has_custom_icon.
- *
- * @copydoc purple_buddy_icons_node_has_custom_icon()
- *
- * @deprecated Use purple_buddy_icons_node_has_custom_icon instead.
- */
-gboolean
-purple_buddy_icons_has_custom_icon(PurpleContact *contact);
-
-/**
- * PurpleContact version of purple_buddy_icons_node_find_custom_icon.
- *
- * @copydoc purple_buddy_icons_node_find_custom_icon()
- *
- * @deprecated Use purple_buddy_icons_node_find_custom_icon instead.
- */
-PurpleStoredImage *
-purple_buddy_icons_find_custom_icon(PurpleContact *contact);
-
-/**
- * PurpleContact version of purple_buddy_icons_node_set_custom_icon.
- *
- * @copydoc purple_buddy_icons_node_set_custom_icon()
- *
- * @deprecated Use purple_buddy_icons_node_set_custom_icon instead.
- */
-PurpleStoredImage *
-purple_buddy_icons_set_custom_icon(PurpleContact *contact,
-                                   guchar *icon_data, size_t icon_len);
-#endif
-
 /**
  * Sets whether or not buddy icon caching is enabled.
  *
--- a/libpurple/certificate.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/certificate.c	Mon Oct 31 01:25:36 2011 +0000
@@ -275,7 +275,7 @@
 }
 
 gboolean
-purple_certificate_check_signature_chain_with_failing(GList *chain,
+purple_certificate_check_signature_chain(GList *chain,
                                                       PurpleCertificate **failing)
 {
 	GList *cur;
@@ -363,12 +363,6 @@
 	return TRUE;
 }
 
-gboolean
-purple_certificate_check_signature_chain(GList *chain)
-{
-	return purple_certificate_check_signature_chain_with_failing(chain, NULL);
-}
-
 PurpleCertificate *
 purple_certificate_import(PurpleCertificateScheme *scheme, const gchar *filename)
 {
@@ -1622,7 +1616,7 @@
 	ca = purple_certificate_find_pool(x509_tls_cached.scheme_name, "ca");
 
 	/* Next, check that the certificate chain is valid */
-	if (!purple_certificate_check_signature_chain_with_failing(chain,
+	if (!purple_certificate_check_signature_chain(chain,
 				&failing_crt))
 	{
 		gboolean chain_validated = FALSE;
@@ -1704,7 +1698,7 @@
 		flags |= PURPLE_CERTIFICATE_CA_UNKNOWN;
 
 		purple_debug_warning("certificate/x509/tls_cached",
-				  "No Certificate Authorities with either DN found "
+				  "No Certificate Authorities with either DN "
 				  "found. I'll prompt the user, I guess.\n");
 
 		x509_tls_cached_check_subject_name(vrq, flags);
--- a/libpurple/certificate.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/certificate.h	Mon Oct 31 01:25:36 2011 +0000
@@ -2,7 +2,6 @@
  * @file certificate.h Public-Key Certificate API
  * @ingroup core
  * @see @ref certificate-signals
- * @since 2.2.0
  */
 
 /*
@@ -462,33 +461,12 @@
  *                   chain fails to validate, this will be set to the
  *                   certificate whose signature could not be validated.
  * @return TRUE if the chain is valid. See description.
- *
- * @since 2.6.0
- * @deprecated  This function will become
- *              purple_certificate_check_signature_chain in 3.0.0
  */
 gboolean
-purple_certificate_check_signature_chain_with_failing(GList *chain,
+purple_certificate_check_signature_chain(GList *chain,
 		PurpleCertificate **failing);
 
 /**
- * Check that a certificate chain is valid
- *
- * Uses purple_certificate_signed_by() to verify that each PurpleCertificate
- * in the chain carries a valid signature from the next. A single-certificate
- * chain is considered to be valid.
- *
- * @param chain      List of PurpleCertificate instances comprising the chain,
- *                   in the order certificate, issuer, issuer's issuer, etc.
- * @return TRUE if the chain is valid. See description.
- * @todo Specify which certificate in the chain caused a failure
- * @deprecated  This function will be removed in 3.0.0 and replaced with
- *              purple_certificate_check_signature_chain_with_failing
- */
-gboolean
-purple_certificate_check_signature_chain(GList *chain);
-
-/**
  * Imports a PurpleCertificate from a file
  *
  * @param scheme      Scheme to import under
--- a/libpurple/cipher.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/cipher.h	Mon Oct 31 01:25:36 2011 +0000
@@ -41,7 +41,7 @@
 /**
  * Modes for batch encrypters
  */
-typedef enum _PurpleCipherBatchMode {
+typedef enum {
 	PURPLE_CIPHER_BATCH_MODE_ECB,
 	PURPLE_CIPHER_BATCH_MODE_CBC
 } PurpleCipherBatchMode;
@@ -49,7 +49,7 @@
 /**
  * The operation flags for a cipher
  */
-typedef enum _PurpleCipherCaps {
+typedef enum {
 	PURPLE_CIPHER_CAPS_SET_OPT          = 1 << 1,   /**< Set option flag	*/
 	PURPLE_CIPHER_CAPS_GET_OPT          = 1 << 2,   /**< Get option flag	*/
 	PURPLE_CIPHER_CAPS_INIT             = 1 << 3,   /**< Init flag			*/
--- a/libpurple/cmds.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/cmds.h	Mon Oct 31 01:25:36 2011 +0000
@@ -32,7 +32,7 @@
 /*@{*/
 
 /** The possible results of running a command with purple_cmd_do_command(). */
-typedef enum _PurpleCmdStatus {
+typedef enum {
 	PURPLE_CMD_STATUS_OK,
 	PURPLE_CMD_STATUS_FAILED,
 	PURPLE_CMD_STATUS_NOT_FOUND,
@@ -48,7 +48,7 @@
  *  #PURPLE_CMD_RET_CONTINUE to cause the core to fall through to other
  *  commands with the same name.
  */
-typedef enum _PurpleCmdRet {
+typedef enum {
 	PURPLE_CMD_RET_OK,       /**< Everything's okay; Don't look for another command to call. */
 	PURPLE_CMD_RET_FAILED,   /**< The command failed, but stop looking.*/
 	PURPLE_CMD_RET_CONTINUE /**< Continue, looking for other commands with the same name to call. */
@@ -68,7 +68,7 @@
  */
 typedef guint PurpleCmdId;
 
-typedef enum _PurpleCmdPriority {
+typedef enum {
 	PURPLE_CMD_P_VERY_LOW  = -1000,
 	PURPLE_CMD_P_LOW       =     0,
 	PURPLE_CMD_P_DEFAULT   =  1000,
@@ -85,7 +85,7 @@
  *
  *  @see purple_cmd_register
  */
-typedef enum _PurpleCmdFlag {
+typedef enum {
 	/** Command is usable in IMs. */
 	PURPLE_CMD_FLAG_IM               = 0x01,
 	/** Command is usable in multi-user chats. */
@@ -225,19 +225,16 @@
 /**
  * Get the handle for the commands API
  * @return The handle
- * @since 2.5.0
  */
 gpointer purple_cmds_get_handle(void);
 
 /**
  * Initialize the commands subsystem.
- * @since 2.5.0
  */
 void purple_cmds_init(void);
 
 /**
  * Uninitialize the commands subsystem.
- * @since 2.5.0
  */
 void purple_cmds_uninit(void);
 
--- a/libpurple/connection.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/connection.c	Mon Oct 31 01:25:36 2011 +0000
@@ -92,12 +92,6 @@
 }
 
 void
-purple_connection_new(PurpleAccount *account, gboolean regist, const char *password)
-{
-	_purple_connection_new(account, regist, password);
-}
-
-void
 _purple_connection_new(PurpleAccount *account, gboolean regist, const char *password)
 {
 	PurpleConnection *gc;
@@ -171,11 +165,6 @@
 		prpl_info->login(account);
 	}
 }
-void
-purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data)
-{
-	_purple_connection_new_unregister(account, password, cb, user_data);
-}
 
 void
 _purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data)
@@ -234,12 +223,6 @@
 }
 
 void
-purple_connection_destroy(PurpleConnection *gc)
-{
-	_purple_connection_destroy(gc);
-}
-
-void
 _purple_connection_destroy(PurpleConnection *gc)
 {
 	PurpleAccount *account;
@@ -404,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);
@@ -436,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)
 {
@@ -457,7 +456,7 @@
 {
 	g_return_val_if_fail(gc != NULL, NULL);
 
-	return gc->password ? gc->password : gc->account->password;
+	return gc->password ? gc->password : purple_account_get_password(gc->account);
 }
 
 const char *
@@ -528,22 +527,7 @@
 }
 
 void
-purple_connection_error(PurpleConnection *gc, const char *text)
-{
-	/* prpls that have not been updated to use disconnection reasons will
-	 * be setting wants_to_die before calling this function, so choose
-	 * PURPLE_CONNECTION_ERROR_OTHER_ERROR (which is fatal) if it's true,
-	 * and PURPLE_CONNECTION_ERROR_NETWORK_ERROR (which isn't) if not.  See
-	 * the documentation in connection.h.
-	 */
-	PurpleConnectionError reason = gc->wants_to_die
-	                             ? PURPLE_CONNECTION_ERROR_OTHER_ERROR
-	                             : PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-	purple_connection_error_reason (gc, reason, text);
-}
-
-void
-purple_connection_error_reason (PurpleConnection *gc,
+purple_connection_error (PurpleConnection *gc,
                                 PurpleConnectionError reason,
                                 const char *description)
 {
@@ -557,13 +541,13 @@
 	 */
 	if (reason > PURPLE_CONNECTION_ERROR_OTHER_ERROR) {
 		purple_debug_error("connection",
-			"purple_connection_error_reason: reason %u isn't a "
+			"purple_connection_error: reason %u isn't a "
 			"valid reason\n", reason);
 		reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
 	}
 
 	if (description == NULL) {
-		purple_debug_error("connection", "purple_connection_error_reason called with NULL description\n");
+		purple_debug_error("connection", "purple_connection_error called with NULL description\n");
 		description = _("Unknown error");
 	}
 
@@ -578,13 +562,8 @@
 
 	ops = purple_connections_get_ui_ops();
 
-	if (ops != NULL)
-	{
-		if (ops->report_disconnect_reason != NULL)
-			ops->report_disconnect_reason (gc, reason, description);
-		if (ops->report_disconnect != NULL)
-			ops->report_disconnect (gc, description);
-	}
+	if (ops && ops->report_disconnect)
+		ops->report_disconnect(gc, reason, description);
 
 	purple_signal_emit(purple_connections_get_handle(), "connection-error",
 		gc, reason, description);
@@ -615,7 +594,7 @@
 			reason = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR;
 	}
 
-	purple_connection_error_reason (gc, reason,
+	purple_connection_error (gc, reason,
 		purple_ssl_strerror(ssl_error));
 }
 
@@ -648,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/connection.h	Mon Oct 31 01:25:36 2011 +0000
@@ -59,8 +59,6 @@
 
 /**
  * Possible errors that can cause a connection to be closed.
- *
- *  @since 2.3.0
  */
 typedef enum
 {
@@ -128,7 +126,7 @@
 	/** Some other error occurred which fits into none of the other
 	 *  categories.
 	 */
-	/* purple_connection_error_reason() in connection.c uses the fact that
+	/* purple_connection_error() in connection.c uses the fact that
 	 * this is the last member of the enum when sanity-checking; if other
 	 * reasons are added after it, the check must be updated.
 	 */
@@ -194,16 +192,6 @@
 	void (*notice)(PurpleConnection *gc, const char *text);
 
 	/**
-	 * Called when an error causes a connection to be disconnected.
-	 * Called before #disconnected.
-	 * @param text  a localized error message.
-	 * @see #purple_connection_error
-	 * @deprecated in favour of
-	 *             #PurpleConnectionUiOps.report_disconnect_reason.
-	 */
-	void (*report_disconnect)(PurpleConnection *gc, const char *text);
-
-	/**
 	 * Called when libpurple discovers that the computer's network
 	 * connection is active.  On Linux, this uses Network Manager if
 	 * available; on Windows, it uses Win32's network change notification
@@ -219,21 +207,17 @@
 
 	/**
 	 * Called when an error causes a connection to be disconnected.
-	 *  Called before #disconnected.  This op is intended to replace
-	 *  #report_disconnect.  If both are implemented, this will be called
-	 *  first; however, there's no real reason to implement both.
+	 * Called before #disconnected.
 	 *
-	 *  @param reason  why the connection ended, if known, or
-	 *                 #PURPLE_CONNECTION_ERROR_OTHER_ERROR, if not.
-	 *  @param text  a localized message describing the disconnection
-	 *               in more detail to the user.
-	 *  @see #purple_connection_error_reason
-	 *
-	 *  @since 2.3.0
+	 * @param reason  why the connection ended, if known, or
+	 *                #PURPLE_CONNECTION_ERROR_OTHER_ERROR, if not.
+	 * @param text  a localized message describing the disconnection
+	 *              in more detail to the user.
+	 * @see #purple_connection_error
 	 */
-	void (*report_disconnect_reason)(PurpleConnection *gc,
-	                                 PurpleConnectionError reason,
-	                                 const char *text);
+	void (*report_disconnect)(PurpleConnection *gc,
+	                          PurpleConnectionError reason,
+	                          const char *text);
 
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
@@ -251,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
@@ -264,7 +247,7 @@
 	/** Wants to Die state.  This is set when the user chooses to log out, or
 	 * when the protocol is disconnected and should not be automatically
 	 * reconnected (incorrect password, etc.).  prpls should rely on
-	 * purple_connection_error_reason() to set this for them rather than
+	 * purple_connection_error() to set this for them rather than
 	 * setting it themselves.
 	 * @see purple_connection_error_is_fatal
 	 */
@@ -284,63 +267,6 @@
 /**************************************************************************/
 /*@{*/
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_CONNECTION_C_)
-/**
- * This function should only be called by purple_account_connect()
- * in account.c.  If you're trying to sign on an account, use that
- * function instead.
- *
- * Creates a connection to the specified account and either connects
- * or attempts to register a new account.  If you are logging in,
- * the connection uses the current active status for this account.
- * So if you want to sign on as "away," for example, you need to
- * have called purple_account_set_status(account, "away").
- * (And this will call purple_account_connect() automatically).
- *
- * @param account  The account the connection should be connecting to.
- * @param regist   Whether we are registering a new account or just
- *                 trying to do a normal signon.
- * @param password The password to use.
- *
- * @deprecated As this is internal, we should make it private in 3.0.0.
- */
-void purple_connection_new(PurpleAccount *account, gboolean regist,
-									const char *password);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_CONNECTION_C_)
-/**
- * This function should only be called by purple_account_unregister()
- * in account.c.
- *
- * Tries to unregister the account on the server. If the account is not
- * connected, also creates a new connection.
- *
- * @param account  The account to unregister
- * @param password The password to use.
- * @param cb Optional callback to be called when unregistration is complete
- * @param user_data user data to pass to the callback
- *
- * @deprecated As this is internal, we should make it private in 3.0.0.
- */
-void purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_CONNECTION_C_)
-/**
- * Disconnects and destroys a PurpleConnection.
- *
- * This function should only be called by purple_account_disconnect()
- * in account.c.  If you're trying to sign off an account, use that
- * function instead.
- *
- * @param gc The purple connection to destroy.
- *
- * @deprecated As this is internal, we should make it private in 3.0.0.
- */
-void purple_connection_destroy(PurpleConnection *gc);
-#endif
-
 /**
  * Sets the connection state.  PRPLs should call this and pass in
  * the state #PURPLE_CONNECTED when the account is completely
@@ -354,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.
@@ -374,8 +308,6 @@
  *
  * @param connection The PurpleConnection.
  * @param proto_data The protocol data to set for the connection.
- *
- * @since 2.6.0
  */
 void purple_connection_set_protocol_data(PurpleConnection *connection, void *proto_data);
 
@@ -389,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.
@@ -411,8 +352,6 @@
  * @param gc The connection.
  *
  * @return The protocol plugin.
- *
- * @since 2.4.0
  */
 PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc);
 
@@ -440,8 +379,6 @@
  * @param connection The PurpleConnection.
  *
  * @return The protocol data for the connection.
- *
- * @since 2.6.0
  */
 void *purple_connection_get_protocol_data(const PurpleConnection *connection);
 
@@ -465,21 +402,6 @@
 void purple_connection_notice(PurpleConnection *gc, const char *text);
 
 /**
- * Closes a connection with an error.
- *
- * @param gc     The connection.
- * @param reason The error text, which may not be @c NULL.
- * @deprecated in favour of #purple_connection_error_reason.  Calling
- *  @c purple_connection_error(gc, text) is equivalent to calling
- *  @c purple_connection_error_reason(gc, reason, text) where @c reason is
- *  #PURPLE_CONNECTION_ERROR_OTHER_ERROR if @c gc->wants_to_die is @c TRUE, and
- *  #PURPLE_CONNECTION_ERROR_NETWORK_ERROR if not.  (This is to keep
- *  auto-reconnection behaviour the same when using old prpls which don't use
- *  reasons yet.)
- */
-void purple_connection_error(PurpleConnection *gc, const char *reason);
-
-/**
  * Closes a connection with an error and a human-readable description of the
  * error.  It also sets @c gc->wants_to_die to the value of
  * #purple_connection_error_is_fatal(@a reason), mainly for
@@ -488,20 +410,16 @@
  * @param gc          the connection which is closing.
  * @param reason      why the connection is closing.
  * @param description a non-@c NULL localized description of the error.
- *
- * @since 2.3.0
  */
 void
-purple_connection_error_reason (PurpleConnection *gc,
-                                PurpleConnectionError reason,
-                                const char *description);
+purple_connection_error(PurpleConnection *gc,
+                        PurpleConnectionError reason,
+                        const char *description);
 
 /**
  * Closes a connection due to an SSL error; this is basically a shortcut to
  * turning the #PurpleSslErrorType into a #PurpleConnectionError and a
- * human-readable string and then calling purple_connection_error_reason().
- *
- * @since 2.3.0
+ * human-readable string and then calling purple_connection_error().
  */
 void
 purple_connection_ssl_error (PurpleConnection *gc,
@@ -524,12 +442,18 @@
  *
  * @return @c TRUE if the account should not be automatically reconnected, and
  *         @c FALSE otherwise.
- *
- * @since 2.3.0
  */
 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/conversation.c	Mon Oct 31 01:25:36 2011 +0000
@@ -35,6 +35,131 @@
 
 #define SEND_TYPED_TIMEOUT_SECONDS 5
 
+/**
+ * Data specific to Chats.
+ */
+struct _PurpleConvChat
+{
+	PurpleConversation *conv;          /**< The parent conversation.      */
+
+	GList *in_room;                  /**< The users in the room.
+	                                  *   @deprecated Will be removed in 3.0.0
+									  */
+	GList *ignored;                  /**< Ignored users.                */
+	char  *who;                      /**< The person who set the topic. */
+	char  *topic;                    /**< The topic.                    */
+	int    id;                       /**< The chat ID.                  */
+	char *nick;                      /**< Your nick in this chat.       */
+
+	gboolean left;                   /**< We left the chat and kept the window open */
+	GHashTable *users;               /**< Hash table of the users in the room. */
+};
+
+/**
+ * Data specific to Instant Messages.
+ */
+struct _PurpleConvIm
+{
+	PurpleConversation *conv;            /**< The parent conversation.     */
+
+	PurpleTypingState typing_state;      /**< The current typing state.    */
+	guint  typing_timeout;             /**< The typing timer handle.     */
+	time_t type_again;                 /**< The type again time.         */
+	guint  send_typed_timeout;         /**< The type again timer handle. */
+
+	PurpleBuddyIcon *icon;               /**< The buddy icon.              */
+};
+
+/**
+ * Data for "Chat Buddies"
+ */
+struct _PurpleConvChatBuddy
+{
+	/** The chat participant's name in the chat. */
+	char *name;
+
+	/** The chat participant's alias, if known; @a NULL otherwise. */
+	char *alias;
+
+	/**
+	 * A string by which this buddy will be sorted, or @c NULL if the
+	 * buddy should be sorted by its @c name.  (This is currently always
+	 * @c NULL.
+	 */
+	char *alias_key;
+
+	/**
+	 * @a TRUE if this chat participant is on the buddy list;
+	 * @a FALSE otherwise.
+	 */
+	gboolean buddy;
+
+	/**
+	 * A bitwise OR of flags for this participant, such as whether they
+	 * are a channel operator.
+	 */
+	PurpleConvChatBuddyFlags flags;
+
+	/**
+	 * A hash table of attributes about the user, such as real name,
+	 * user\@host, etc.
+	 */
+	GHashTable *attributes;
+
+	/** The UI can put whatever it wants here. */
+	gpointer ui_data;
+};
+
+/**
+ * A core representation of a conversation between two or more people.
+ *
+ * The conversation can be an IM or a chat.
+ */
+struct _PurpleConversation
+{
+	PurpleConversationType type;  /**< The type of conversation.          */
+
+	PurpleAccount *account;       /**< The user using this conversation.  */
+
+
+	char *name;                 /**< The name of the conversation.      */
+	char *title;                /**< The window title.                  */
+
+	gboolean logging;           /**< The status of logging.             */
+
+	GList *logs;                /**< This conversation's logs           */
+
+	union
+	{
+		PurpleConvIm   *im;       /**< IM-specific data.                  */
+		PurpleConvChat *chat;     /**< Chat-specific data.                */
+		void *misc;               /**< Misc. data.                        */
+
+	} u;
+
+	PurpleConversationUiOps *ui_ops;           /**< UI-specific operations. */
+	void *ui_data;                           /**< UI-specific data.       */
+
+	GHashTable *data;                        /**< Plugin-specific data.   */
+
+	PurpleConnectionFlags features; /**< The supported features */
+	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;
 static GList *chats = NULL;
@@ -116,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) {
@@ -146,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);
@@ -262,7 +387,7 @@
 		if (gc)
 			me = purple_connection_get_display_name(gc);
 		if (!me)
-			me = conv->account->username;
+			me = purple_account_get_username(conv->account);
 		who = me;
 	}
 
@@ -381,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)
 	{
@@ -416,7 +541,7 @@
 
 		chats = g_list_prepend(chats, conv);
 
-		if ((disp = purple_connection_get_display_name(account->gc)))
+		if ((disp = purple_connection_get_display_name(purple_account_get_connection(account))))
 			purple_conv_chat_set_nick(conv->u.chat, disp);
 		else
 			purple_conv_chat_set_nick(conv->u.chat,
@@ -469,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)
@@ -694,7 +819,7 @@
 }
 
 PurpleConnection *
-purple_conversation_get_gc(const PurpleConversation *conv)
+purple_conversation_get_connection(const PurpleConversation *conv)
 {
 	PurpleAccount *account;
 
@@ -705,7 +830,7 @@
 	if (account == NULL)
 		return NULL;
 
-	return account->gc;
+	return purple_account_get_connection(account);
 }
 
 void
@@ -990,7 +1115,7 @@
 							purple_account_get_username(account));
 
 				if (purple_account_get_alias(account) != NULL)
-					alias = account->alias;
+					alias = purple_account_get_alias(account);
 				else if (b != NULL && !purple_strequal(purple_buddy_get_name(b), purple_buddy_get_contact_alias(b)))
 					alias = purple_buddy_get_contact_alias(b);
 				else if (purple_connection_get_display_name(gc) != NULL)
@@ -1379,16 +1504,6 @@
 }
 
 GList *
-purple_conv_chat_set_users(PurpleConvChat *chat, GList *users)
-{
-	g_return_val_if_fail(chat != NULL, NULL);
-
-	chat->in_room = users;
-
-	return users;
-}
-
-GList *
 purple_conv_chat_get_users(const PurpleConvChat *chat)
 {
 	g_return_val_if_fail(chat != NULL, NULL);
@@ -1544,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. */
@@ -1660,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);
@@ -1687,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);
 			}
 		}
@@ -1761,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);
@@ -1785,7 +1900,7 @@
 		}
 	} 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);
 	}
 
@@ -1834,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);
 			}
 
@@ -1880,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);
@@ -1911,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);
 			}
 
@@ -2065,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;
 	}
 
@@ -2093,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,
@@ -2194,14 +2309,51 @@
 	g_free(cb);
 }
 
+void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data)
+{
+	g_return_if_fail(cb != NULL);
+
+	cb->ui_data = ui_data;
+}
+
+gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *cb)
+{
+	g_return_val_if_fail(cb != NULL, NULL);
+
+	return cb->ui_data;
+}
+
 const char *
-purple_conv_chat_cb_get_name(PurpleConvChatBuddy *cb)
+purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb)
+{
+	g_return_val_if_fail(cb != NULL, NULL);
+
+	return cb->alias;
+}
+
+const char *
+purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb)
 {
 	g_return_val_if_fail(cb != NULL, NULL);
 
 	return cb->name;
 }
 
+PurpleConvChatBuddyFlags
+purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb)
+{
+	g_return_val_if_fail(cb != NULL, PURPLE_CBFLAGS_NONE);
+
+	return cb->flags;
+}
+
+gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb)
+{
+	g_return_val_if_fail(cb != NULL, FALSE);
+
+	return cb->buddy;
+}
+
 const char *
 purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key)
 {
@@ -2299,30 +2451,57 @@
 	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);
+
+	conv->ui_data = ui_data;
+}
+
+gpointer purple_conversation_get_ui_data(const PurpleConversation *conv)
+{
+	g_return_val_if_fail(conv != NULL, NULL);
+
+	return conv->ui_data;
+}
+
+
 gboolean
 purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline,
 				const gchar *markup, gchar **error)
--- a/libpurple/conversation.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/conversation.h	Mon Oct 31 01:25:36 2011 +0000
@@ -125,7 +125,7 @@
 	PURPLE_MESSAGE_IMAGES      = 0x1000, /**< Message contains images  */
 	PURPLE_MESSAGE_NOTIFY      = 0x2000, /**< Message is a notification */
 	PURPLE_MESSAGE_NO_LINKIFY  = 0x4000, /**< Message should not be auto-
-										   linkified @since 2.1.0 */
+										   linkified */
 	PURPLE_MESSAGE_INVISIBLE   = 0x8000  /**< Message should not be displayed */
 } PurpleMessageFlags;
 
@@ -140,7 +140,7 @@
 	PURPLE_CBFLAGS_OP            = 0x0004, /**< Channel Op or Moderator      */
 	PURPLE_CBFLAGS_FOUNDER       = 0x0008, /**< Channel Founder              */
 	PURPLE_CBFLAGS_TYPING        = 0x0010, /**< Currently typing             */
-	PURPLE_CBFLAGS_AWAY          = 0x0020  /**< Currently away. @since 2.8.0 */
+	PURPLE_CBFLAGS_AWAY          = 0x0020  /**< Currently away.              */
 
 } PurpleConvChatBuddyFlags;
 
@@ -249,120 +249,6 @@
 	void (*_purple_reserved4)(void);
 };
 
-/**
- * Data specific to Instant Messages.
- */
-struct _PurpleConvIm
-{
-	PurpleConversation *conv;            /**< The parent conversation.     */
-
-	PurpleTypingState typing_state;      /**< The current typing state.    */
-	guint  typing_timeout;             /**< The typing timer handle.     */
-	time_t type_again;                 /**< The type again time.         */
-	guint  send_typed_timeout;         /**< The type again timer handle. */
-
-	PurpleBuddyIcon *icon;               /**< The buddy icon.              */
-};
-
-/**
- * Data specific to Chats.
- */
-struct _PurpleConvChat
-{
-	PurpleConversation *conv;          /**< The parent conversation.      */
-
-	GList *in_room;                  /**< The users in the room.
-	                                  *   @deprecated Will be removed in 3.0.0
-									  */
-	GList *ignored;                  /**< Ignored users.                */
-	char  *who;                      /**< The person who set the topic. */
-	char  *topic;                    /**< The topic.                    */
-	int    id;                       /**< The chat ID.                  */
-	char *nick;                      /**< Your nick in this chat.       */
-
-	gboolean left;                   /**< We left the chat and kept the window open */
-	GHashTable *users;               /**< Hash table of the users in the room.
-	                                  *   @since 2.9.0
-	                                  */
-};
-
-/**
- * Data for "Chat Buddies"
- */
-struct _PurpleConvChatBuddy
-{
-	char *name;                      /**< The chat participant's name in the chat. */
-	char *alias;                     /**< The chat participant's alias, if known;
-	                                  *   @a NULL otherwise.
-	                                  */
-	char *alias_key;                 /**< A string by which this buddy will be sorted,
-	                                  *   or @c NULL if the buddy should be sorted by
-	                                  *   its @c name.  (This is currently always @c
-	                                  *   NULL.)
-	                                  */
-	gboolean buddy;                  /**< @a TRUE if this chat participant is on the
-	                                  *   buddy list; @a FALSE otherwise.
-	                                  */
-	PurpleConvChatBuddyFlags flags;  /**< A bitwise OR of flags for this participant,
-	                                  *   such as whether they are a channel operator.
-	                                  */
-	GHashTable *attributes;          /**< A hash table of attributes about the user, such as
-                                    *   real name, user@host, etc.
-                                    */
-	gpointer ui_data;                /** < The UI can put whatever it wants here. */
-};
-
-/**
- * Description of a conversation message
- *
- * @since 2.2.0
- */
-struct _PurpleConvMessage
-{
-	char *who;
-	char *what;
-	PurpleMessageFlags flags;
-	time_t when;
-	PurpleConversation *conv;  /**< @since 2.3.0 */
-	char *alias;               /**< @since 2.3.0 */
-};
-
-/**
- * A core representation of a conversation between two or more people.
- *
- * The conversation can be an IM or a chat.
- */
-struct _PurpleConversation
-{
-	PurpleConversationType type;  /**< The type of conversation.          */
-
-	PurpleAccount *account;       /**< The user using this conversation.  */
-
-
-	char *name;                 /**< The name of the conversation.      */
-	char *title;                /**< The window title.                  */
-
-	gboolean logging;           /**< The status of logging.             */
-
-	GList *logs;                /**< This conversation's logs           */
-
-	union
-	{
-		PurpleConvIm   *im;       /**< IM-specific data.                  */
-		PurpleConvChat *chat;     /**< Chat-specific data.                */
-		void *misc;             /**< Misc. data.                        */
-
-	} u;
-
-	PurpleConversationUiOps *ui_ops;           /**< UI-specific operations. */
-	void *ui_data;                           /**< UI-specific data.       */
-
-	GHashTable *data;                        /**< Plugin-specific data.   */
-
-	PurpleConnectionFlags features; /**< The supported features */
-	GList *message_history;         /**< Message history, as a GList of PurpleConvMessage's */
-};
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -469,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.
@@ -744,8 +628,6 @@
  * @return  A GList of PurpleConvMessage's. The must not modify the list or the data within.
  *          The list contains the newest message at the beginning, and the oldest message at
  *          the end.
- *
- * @since 2.2.0
  */
 GList *purple_conversation_get_message_history(PurpleConversation *conv);
 
@@ -753,8 +635,6 @@
  * Clear the message history of a conversation.
  *
  * @param conv  The conversation
- *
- * @since 2.2.0
  */
 void purple_conversation_clear_message_history(PurpleConversation *conv);
 
@@ -764,10 +644,8 @@
  * @param msg   A PurpleConvMessage
  *
  * @return   The name of the sender of the message
- *
- * @since 2.2.0
  */
-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
@@ -775,10 +653,8 @@
  * @param msg   A PurpleConvMessage
  *
  * @return   The name of the sender of the message
- *
- * @since 2.2.0
  */
-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
@@ -786,10 +662,8 @@
  * @param msg   A PurpleConvMessage
  *
  * @return   The message flags
- *
- * @since 2.2.0
  */
-PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg);
+PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg);
 
 /**
  * Get the timestamp of a PurpleConvMessage
@@ -797,10 +671,45 @@
  * @param msg   A PurpleConvMessage
  *
  * @return   The timestamp of the message
+ */
+time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg);
+
+/**
+ * Get the alias from a PurpleConvMessage
  *
- * @since 2.2.0
+ * @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
  */
-time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg);
+PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg);
+
+/**
+ * Set the UI data associated with this conversation.
+ *
+ * @param conv			The conversation.
+ * @param ui_data		A pointer to associate with this conversation.
+ */
+void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data);
+
+/**
+ * Get the UI data associated with this conversation.
+ *
+ * @param conv			The conversation.
+ *
+ * @return The UI data associated with this conversation.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libpurple core.
+ */
+gpointer purple_conversation_get_ui_data(const PurpleConversation *conv);
 
 /*@}*/
 
@@ -1061,22 +970,6 @@
 PurpleConversation *purple_conv_chat_get_conversation(const PurpleConvChat *chat);
 
 /**
- * Sets the list of users in the chat room.
- *
- * @note Calling this function will not update the display of the users.
- *       Please use purple_conv_chat_add_user(), purple_conv_chat_add_users(),
- *       purple_conv_chat_remove_user(), and purple_conv_chat_remove_users() instead.
- *
- * @param chat  The chat.
- * @param users The list of users.
- *
- * @return The list passed.
- *
- * @deprecated This function will be removed in 3.0.0.  You shouldn't be using it anyway.
- */
-GList *purple_conv_chat_set_users(PurpleConvChat *chat, GList *users);
-
-/**
  * Returns a list of users in the chat room.  The members of the list
  * are PurpleConvChatBuddy objects.
  *
@@ -1362,8 +1255,6 @@
  * @param message  The message to send with the invitation.
  * @param confirm  Prompt before sending the invitation. The user is always
  *                 prompted if either \a user or \a message is @c NULL.
- *
- * @since 2.6.0
  */
 void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user,
 		const char *message, gboolean confirm);
@@ -1400,13 +1291,59 @@
 PurpleConvChatBuddy *purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name);
 
 /**
+ * Set the UI data associated with this chat buddy.
+ *
+ * @param cb			The chat buddy
+ * @param ui_data		A pointer to associate with this chat buddy.
+ */
+void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data);
+
+/**
+ * Get the UI data associated with this chat buddy.
+ *
+ * @param cb			The chat buddy.
+ *
+ * @return The UI data associated with this chat buddy.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libpurple core.
+ */
+gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *conv);
+
+/**
+ * Get the alias of a chat buddy
+ *
+ * @param cb    The chat buddy.
+ *
+ * @return The alias of the chat buddy.
+ */
+const char *purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb);
+
+/**
  * Get the name of a chat buddy
  *
  * @param cb    The chat buddy.
  *
  * @return The name of the chat buddy.
  */
-const char *purple_conv_chat_cb_get_name(PurpleConvChatBuddy *cb);
+const char *purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb);
+
+/**
+ * Get the flags of a chat buddy.
+ *
+ * @param cb	The chat buddy.
+ *
+ * @return The flags of the chat buddy.
+ */
+PurpleConvChatBuddyFlags purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb);
+
+/**
+ * Indicates if this chat buddy is on the buddy list.
+ *
+ * @param cb	The chat buddy.
+ *
+ * @return TRUE if the chat buddy is on the buddy list.
+ */
+gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb);
 
 /**
  * Destroys a chat buddy
@@ -1423,8 +1360,6 @@
  * @return  A list of PurpleMenuAction items, harvested by the
  *          chat-extended-menu signal. The list and the menuaction
  *          items should be freed by the caller.
- *
- * @since 2.1.0
  */
 GList * purple_conversation_get_extended_menu(PurpleConversation *conv);
 
@@ -1438,8 +1373,6 @@
  *                message, if not @c NULL. It must be freed by the caller with g_free().
  *
  * @return  @c TRUE if the command was executed successfully, @c FALSE otherwise.
- *
- * @since 2.1.0
  */
 gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error);
 
--- a/libpurple/core.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/core.c	Mon Oct 31 01:25:36 2011 +0000
@@ -371,386 +371,6 @@
 	return is_single_instance;
 }
 
-static gboolean
-move_and_symlink_dir(const char *path, const char *basename, const char *old_base, const char *new_base, const char *relative)
-{
-	char *new_name = g_build_filename(new_base, basename, NULL);
-#ifndef _WIN32
-	char *old_name;
-#endif
-	if (g_rename(path, new_name))
-	{
-		purple_debug_error("core", "Error renaming %s to %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-		                   path, new_name, g_strerror(errno));
-		g_free(new_name);
-		return FALSE;
-	}
-	g_free(new_name);
-
-#ifndef _WIN32
-	/* NOTE: This new_name is relative. */
-	new_name = g_build_filename(relative, basename, NULL);
-	old_name = g_build_filename(old_base, basename, NULL);
-	if (symlink(new_name, old_name))
-	{
-		purple_debug_warning("core", "Error symlinking %s to %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-		                     old_name, new_name, g_strerror(errno));
-	}
-	g_free(old_name);
-	g_free(new_name);
-#endif
-
-	return TRUE;
-}
-
-gboolean
-purple_core_migrate(void)
-{
-	const char *user_dir = purple_user_dir();
-	char *old_user_dir = g_strconcat(purple_home_dir(),
-	                                 G_DIR_SEPARATOR_S ".gaim", NULL);
-	char *status_file;
-	FILE *fp;
-	GDir *dir;
-	GError *err;
-	const char *entry;
-#ifndef _WIN32
-	char *logs_dir;
-#endif
-	char *old_icons_dir;
-
-	if (!g_file_test(old_user_dir, G_FILE_TEST_EXISTS))
-	{
-		/* ~/.gaim doesn't exist, so there's nothing to migrate. */
-		g_free(old_user_dir);
-		return TRUE;
-	}
-
-	status_file = g_strconcat(user_dir, G_DIR_SEPARATOR_S "migrating", NULL);
-
-	if (g_file_test(user_dir, G_FILE_TEST_EXISTS))
-	{
-		/* If we're here, we have both ~/.gaim and .purple. */
-
-		if (!g_file_test(status_file, G_FILE_TEST_EXISTS))
-		{
-			/* There's no "migrating" status file,
-			 * so ~/.purple is all up to date. */
-			g_free(status_file);
-			g_free(old_user_dir);
-			return TRUE;
-		}
-	}
-
-	/* If we're here, it's time to migrate from ~/.gaim to ~/.purple. */
-
-        /* Ensure the user directory exists */
-	if (!g_file_test(user_dir, G_FILE_TEST_IS_DIR))
-	{
-		if (g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
-		{
-			purple_debug_error("core", "Error creating directory %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-			                   user_dir, g_strerror(errno));
-			g_free(status_file);
-			g_free(old_user_dir);
-			return FALSE;
-		}
-	}
-
-	/* This writes ~/.purple/migrating, which allows us to detect
-	 * incomplete migrations and properly retry. */
-	if (!(fp = g_fopen(status_file, "w")))
-	{
-		purple_debug_error("core", "Error opening file %s for writing: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-		                   status_file, g_strerror(errno));
-		g_free(status_file);
-		g_free(old_user_dir);
-		return FALSE;
-	}
-	fclose(fp);
-
-	/* Open ~/.gaim so we can loop over its contents. */
-	err = NULL;
-	if (!(dir = g_dir_open(old_user_dir, 0, &err)))
-	{
-		purple_debug_error("core", "Error opening directory %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-		                   status_file,
-		                   (err ? err->message : "Unknown error"));
-		if (err)
-			g_error_free(err);
-		g_free(status_file);
-		g_free(old_user_dir);
-		return FALSE;
-	}
-
-	/* Loop over the contents of ~/.gaim */
-	while ((entry = g_dir_read_name(dir)))
-	{
-		char *name = g_build_filename(old_user_dir, entry, NULL);
-
-#ifndef _WIN32
-		/* Deal with symlinks... */
-		if (g_file_test(name, G_FILE_TEST_IS_SYMLINK))
-		{
-			/* We're only going to duplicate a logs symlink. */
-			if (purple_strequal(entry, "logs"))
-			{
-				char *link;
-				err = NULL;
-
-				if ((link = g_file_read_link(name, &err)) == NULL)
-				{
-					char *name_utf8 = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
-					purple_debug_error("core", "Error reading symlink %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-					                   name_utf8 ? name_utf8 : name, err->message);
-					g_free(name_utf8);
-					g_error_free(err);
-					g_free(name);
-					g_dir_close(dir);
-					g_free(status_file);
-					g_free(old_user_dir);
-					return FALSE;
-				}
-
-				logs_dir = g_build_filename(user_dir, "logs", NULL);
-
-				if (purple_strequal(link, "../.purple/logs") ||
-				    purple_strequal(link, logs_dir))
-				{
-					/* If the symlink points to the new directory, we're
-					 * likely just trying again after a failed migration,
-					 * so there's no need to fail here. */
-					g_free(link);
-					g_free(logs_dir);
-					continue;
-				}
-
-				/* In case we are trying again after a failed migration, we need
-				 * to unlink any existing symlink.  If it's a directory, this
-				 * will fail, and so will the symlink below, which is good
-				 * because the user should sort things out. */
-				g_unlink(logs_dir);
-
-				/* Relative links will most likely still be
-				 * valid from ~/.purple, though it's not
-				 * guaranteed.  Oh well. */
-				if (symlink(link, logs_dir))
-				{
-					purple_debug_error("core", "Error symlinking %s to %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-					                   logs_dir, link, g_strerror(errno));
-					g_free(link);
-					g_free(name);
-					g_free(logs_dir);
-					g_dir_close(dir);
-					g_free(status_file);
-					g_free(old_user_dir);
-					return FALSE;
-				}
-
-				g_free(link);
-				g_free(logs_dir);
-				continue;
-			}
-
-			/* Ignore all other symlinks. */
-			continue;
-		}
-#endif
-
-		/* Deal with directories... */
-		if (g_file_test(name, G_FILE_TEST_IS_DIR))
-		{
-			if (purple_strequal(entry, "icons"))
-			{
-				/* This is a special case for the Album plugin, which
-				 * stores data in the icons folder.  We're not copying
-				 * the icons directory over because previous bugs
-				 * meant that it filled up with junk for many users.
-				 * This is a great time to purge it. */
-
-				GDir *icons_dir;
-				char *new_icons_dir;
-				const char *icons_entry;
-
-				err = NULL;
-				if (!(icons_dir = g_dir_open(name, 0, &err)))
-				{
-					purple_debug_error("core", "Error opening directory %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-					                   name,
-					                   (err ? err->message : "Unknown error"));
-					if (err)
-						g_error_free(err);
-					g_free(name);
-					g_dir_close(dir);
-					g_free(status_file);
-					g_free(old_user_dir);
-					return FALSE;
-				}
-
-				new_icons_dir = g_build_filename(user_dir, "icons", NULL);
-			        /* Ensure the new icon directory exists */
-				if (!g_file_test(new_icons_dir, G_FILE_TEST_IS_DIR))
-				{
-					if (g_mkdir(new_icons_dir, S_IRUSR | S_IWUSR | S_IXUSR) == -1)
-					{
-						purple_debug_error("core", "Error creating directory %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-						                   new_icons_dir, g_strerror(errno));
-						g_free(new_icons_dir);
-						g_dir_close(icons_dir);
-						g_free(name);
-						g_dir_close(dir);
-						g_free(status_file);
-						g_free(old_user_dir);
-						return FALSE;
-					}
-				}
-
-				while ((icons_entry = g_dir_read_name(icons_dir)))
-				{
-					char *icons_name = g_build_filename(name, icons_entry, NULL);
-
-					if (g_file_test(icons_name, G_FILE_TEST_IS_DIR))
-					{
-						if (!move_and_symlink_dir(icons_name, icons_entry,
-						                          name, new_icons_dir, "../../.purple/icons"))
-						{
-							g_free(icons_name);
-							g_free(new_icons_dir);
-							g_dir_close(icons_dir);
-							g_free(name);
-							g_dir_close(dir);
-							g_free(status_file);
-							g_free(old_user_dir);
-							return FALSE;
-						}
-					}
-					g_free(icons_name);
-				}
-
-				g_dir_close(icons_dir);
-			}
-			else if (purple_strequal(entry, "plugins"))
-			{
-				/* Do nothing, because we broke plugin compatibility.
-				 * This means that the plugins directory gets left behind. */
-			}
-			else
-			{
-				/* All other directories are moved and symlinked. */
-				if (!move_and_symlink_dir(name, entry, old_user_dir, user_dir, "../.purple"))
-				{
-					g_free(name);
-					g_dir_close(dir);
-					g_free(status_file);
-					g_free(old_user_dir);
-					return FALSE;
-				}
-			}
-		}
-		else if (g_file_test(name, G_FILE_TEST_IS_REGULAR))
-		{
-			/* Regular files are copied. */
-
-			char *new_name;
-			FILE *new_file;
-
-			if (!(fp = g_fopen(name, "rb")))
-			{
-				purple_debug_error("core", "Error opening file %s for reading: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-				                   name, g_strerror(errno));
-				g_free(name);
-				g_dir_close(dir);
-				g_free(status_file);
-				g_free(old_user_dir);
-				return FALSE;
-			}
-
-			new_name = g_build_filename(user_dir, entry, NULL);
-			if (!(new_file = g_fopen(new_name, "wb")))
-			{
-				purple_debug_error("core", "Error opening file %s for writing: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-				                   new_name, g_strerror(errno));
-				fclose(fp);
-				g_free(new_name);
-				g_free(name);
-				g_dir_close(dir);
-				g_free(status_file);
-				g_free(old_user_dir);
-				return FALSE;
-			}
-
-			while (!feof(fp))
-			{
-				unsigned char buf[256];
-				size_t size;
-
-				size = fread(buf, 1, sizeof(buf), fp);
-				if (size != sizeof(buf) && !feof(fp))
-				{
-					purple_debug_error("core", "Error reading %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-					                   name, g_strerror(errno));
-					fclose(new_file);
-					fclose(fp);
-					g_free(new_name);
-					g_free(name);
-					g_dir_close(dir);
-					g_free(status_file);
-					g_free(old_user_dir);
-					return FALSE;
-				}
-
-				if (!fwrite(buf, size, 1, new_file) && ferror(new_file) != 0)
-				{
-					purple_debug_error("core", "Error writing %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-					                   new_name, g_strerror(errno));
-					fclose(new_file);
-					fclose(fp);
-					g_free(new_name);
-					g_free(name);
-					g_dir_close(dir);
-					g_free(status_file);
-					g_free(old_user_dir);
-					return FALSE;
-				}
-			}
-
-			if (fclose(new_file))
-			{
-				purple_debug_error("core", "Error writing: %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-				                   new_name, g_strerror(errno));
-			}
-			if (fclose(fp))
-			{
-				purple_debug_warning("core", "Error closing %s: %s\n",
-				                     name, g_strerror(errno));
-			}
-			g_free(new_name);
-		}
-		else
-			purple_debug_warning("core", "Not a regular file or directory: %s\n", name);
-
-		g_free(name);
-	}
-
-	/* The migration was successful, so delete the status file. */
-	if (g_unlink(status_file))
-	{
-		purple_debug_error("core", "Error unlinking file %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n",
-		                   status_file, g_strerror(errno));
-		g_free(status_file);
-		return FALSE;
-	}
-
-	old_icons_dir = g_build_filename(old_user_dir, "icons", NULL);
-	_purple_buddy_icon_set_old_icons_dir(old_icons_dir);
-	g_free(old_icons_dir);
-
-	g_free(old_user_dir);
-
-	g_free(status_file);
-	return TRUE;
-}
-
 GHashTable* purple_core_get_ui_info() {
 	PurpleCoreUiOps *ops = purple_core_get_ui_ops();
 
--- a/libpurple/core.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/core.h	Mon Oct 31 01:25:36 2011 +0000
@@ -156,17 +156,6 @@
 PurpleCoreUiOps *purple_core_get_ui_ops(void);
 
 /**
- * Migrates from <tt>.gaim</tt> to <tt>.purple</tt>.
- *
- * UIs <strong>must not</strong> call this if they have been told to use a
- * custom user directory.
- *
- * @return A boolean indicating success or migration failure. On failure,
- *         the application must display an error to the user and then exit.
- */
-gboolean purple_core_migrate(void);
-
-/**
  * Ensures that only one instance is running.  If libpurple is built with D-Bus
  * support, this checks if another process owns the libpurple bus name and if
  * so whether that process is using the same configuration directory as this
@@ -174,8 +163,6 @@
  *
  * @return @c TRUE if this is the first instance of libpurple running;
  *         @c FALSE if there is another instance running.
- *
- * @since 2.1.0
  */
 gboolean purple_core_ensure_single_instance(void);
 
@@ -207,8 +194,6 @@
  * @return A GHashTable with strings for keys and values.  This
  * hash table must not be freed and should not be modified.
  *
- * @since 2.1.0
- *
  */
 GHashTable* purple_core_get_ui_info(void);
 
--- a/libpurple/dbus-analyze-functions.py	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dbus-analyze-functions.py	Mon Oct 31 01:25:36 2011 +0000
@@ -29,7 +29,11 @@
     # Similar to the above:
     "purple_account_set_register_callback",
     "purple_account_unregister",
-    "purple_connection_new_unregister",
+
+    # Similar to the above, again
+    "purple_menu_action_new",
+    "purple_menu_action_set_callback",
+    "purple_menu_action_get_callback",
 
     # These functions are excluded because they involve setting arbitrary
     # data via pointers for protocols and UIs.  This just won't work.
@@ -491,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))
@@ -503,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dbus-bindings.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dbus-server.c	Mon Oct 31 01:25:36 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;
 }
 
@@ -711,7 +699,7 @@
 			g_return_val_if_fail(ptr, TRUE);
 		}
 
-		switch (purple_values[i]->type)
+		switch (purple_value_get_type(purple_values[i]))
 		{
 		case PURPLE_TYPE_INT:
 		case PURPLE_TYPE_ENUM:
--- a/libpurple/dbus-server.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dbus-server.h	Mon Oct 31 01:25:36 2011 +0000
@@ -173,8 +173,6 @@
 
 /**
  * Determines whether this instance owns the DBus service name
- *
- * @since 2.1.0
  */
 gboolean purple_dbus_is_owner(void);
 
--- a/libpurple/dbus-useful.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dbus-useful.c	Mon Oct 31 01:25:36 2011 +0000
@@ -25,7 +25,7 @@
 		if (who && strcmp(purple_normalize(NULL, purple_account_get_username(account)), who))
 			continue;
 
-		if (protocol_id && strcmp(account->protocol_id, protocol_id))
+		if (protocol_id && strcmp(purple_account_get_protocol_id(account), protocol_id))
 			continue;
 
 		if (account_test && !account_test(account))
--- a/libpurple/debug.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/debug.c	Mon Oct 31 01:25:36 2011 +0000
@@ -224,12 +224,5 @@
 		purple_debug_set_verbose(TRUE);
 
 	purple_prefs_add_none("/purple/debug");
-
-	/*
-	 * This pref is obsolete and no longer referenced anywhere. It only
-	 * survives here because it would be an API break if we removed it.
-	 * Remove this when we get to 3.0.0 :)
-	 */
-	purple_prefs_add_bool("/purple/debug/timestamps", TRUE);
 }
 
--- a/libpurple/debug.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/debug.h	Mon Oct 31 01:25:36 2011 +0000
@@ -161,8 +161,6 @@
  * plugins.
  *
  * @param verbose TRUE to enable verbose debugging or FALSE to disable it.
- *
- * @since 2.6.0
  */
 void purple_debug_set_verbose(gboolean verbose);
 
@@ -170,8 +168,6 @@
  * Check if verbose logging is enabled.
  *
  * @return TRUE if verbose debugging is enabled, FALSE if it is not.
- *
- * @since 2.6.0
  */
 gboolean purple_debug_is_verbose(void);
 
@@ -183,8 +179,6 @@
  * @param unsafe TRUE to enable debug logging of messages that could
  *        potentially contain passwords and other sensitive information.
  *        FALSE to disable it.
- *
- * @since 2.6.0
  */
 void purple_debug_set_unsafe(gboolean unsafe);
 
@@ -194,8 +188,6 @@
  * @return TRUE if the debug logging of all messages is enabled, FALSE
  *         if messages that could potentially contain passwords and other
  *         sensitive information are not logged.
- *
- * @since 2.6.0
  */
 gboolean purple_debug_is_unsafe(void);
 
--- a/libpurple/dnsquery.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dnsquery.c	Mon Oct 31 01:25:36 2011 +0000
@@ -297,6 +297,10 @@
 		}
 		rc = read(child_in, &dns_params, sizeof(dns_params_t));
 		if (rc < 0) {
+			if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+				/* Try again */
+				continue;
+			}
 			fprintf(stderr, "dns[%d]: Error: Could not read dns_params: "
 					"%s\n", getpid(), strerror(errno));
 			break;
@@ -910,7 +914,7 @@
 }
 
 PurpleDnsQueryData *
-purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port,
+purple_dnsquery_a(PurpleAccount *account, const char *hostname, int port,
 				PurpleDnsQueryConnectFunction callback, gpointer data)
 {
 	PurpleDnsQueryData *query_data;
@@ -940,13 +944,6 @@
 	return query_data;
 }
 
-PurpleDnsQueryData *
-purple_dnsquery_a(const char *hostname, int port,
-				PurpleDnsQueryConnectFunction callback, gpointer data)
-{
-	return purple_dnsquery_a_account(NULL, hostname, port, callback, data);
-}
-
 void
 purple_dnsquery_destroy(PurpleDnsQueryData *query_data)
 {
--- a/libpurple/dnsquery.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dnsquery.h	Mon Oct 31 01:25:36 2011 +0000
@@ -88,7 +88,7 @@
 /**
  * Perform an asynchronous DNS query.
  *
- * @param account the account that the query is being done for (or NULL)
+ * @param account  The account that the query is being done for (or NULL)
  * @param hostname The hostname to resolve.
  * @param port     A port number which is stored in the struct sockaddr.
  * @param callback The callback function to call after resolving.
@@ -98,27 +98,8 @@
  *         a data structure that can be used to cancel the pending
  *         DNS query, if needed.
  *
- * @since 2.8.0
  */
-PurpleDnsQueryData *purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data);
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSQUERY_C_)
-/**
- * Perform an asynchronous DNS query.
- *
- * @param hostname The hostname to resolve.
- * @param port     A port number which is stored in the struct sockaddr.
- * @param callback The callback function to call after resolving.
- * @param data     Extra data to pass to the callback function.
- *
- * @return NULL if there was an error, otherwise return a reference to
- *         a data structure that can be used to cancel the pending
- *         DNS query, if needed.
- *
- * @deprecated Use purple_dnsquery_a_account instead
- */
-PurpleDnsQueryData *purple_dnsquery_a(const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data);
-#endif
+PurpleDnsQueryData *purple_dnsquery_a(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data);
 
 /**
  * Cancel a DNS query and destroy the associated data structure.
--- a/libpurple/dnssrv.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dnssrv.c	Mon Oct 31 01:25:36 2011 +0000
@@ -725,15 +725,7 @@
 #endif
 
 PurpleSrvTxtQueryData *
-purple_srv_resolve(const char *protocol, const char *transport,
-	const char *domain, PurpleSrvCallback cb, gpointer extradata)
-{
-	return purple_srv_resolve_account(NULL, protocol, transport, domain,
-			cb, extradata);
-}
-
-PurpleSrvTxtQueryData *
-purple_srv_resolve_account(PurpleAccount *account, const char *protocol,
+purple_srv_resolve(PurpleAccount *account, const char *protocol,
 	const char *transport, const char *domain, PurpleSrvCallback cb,
 	gpointer extradata)
 {
@@ -798,6 +790,12 @@
 		return NULL;
 	}
 
+	/*
+	 * TODO: We should put a cap on the number of forked processes that we
+	 *       allow at any given time.  If we get too many requests they
+	 *       should be put into a queue and handled later.  (This is what
+	 *       we do for A record lookups.)
+	 */
 	pid = fork();
 	if (pid == -1) {
 		purple_debug_error("dnssrv", "Could not create process!\n");
@@ -863,13 +861,7 @@
 #endif
 }
 
-PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner,
-	const char *domain, PurpleTxtCallback cb, gpointer extradata)
-{
-	return purple_txt_resolve_account(NULL, owner, domain, cb, extradata);
-}
-
-PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account,
+PurpleSrvTxtQueryData *purple_txt_resolve(PurpleAccount *account,
 	const char *owner, const char *domain, PurpleTxtCallback cb,
 	gpointer extradata)
 {
@@ -929,6 +921,12 @@
 		return NULL;
 	}
 
+	/*
+	 * TODO: We should put a cap on the number of forked processes that we
+	 *       allow at any given time.  If we get too many requests they
+	 *       should be put into a queue and handled later.  (This is what
+	 *       we do for A record lookups.)
+	 */
 	pid = fork();
 	if (pid == -1) {
 		purple_debug_error("dnssrv", "Could not create process!\n");
@@ -994,18 +992,6 @@
 #endif
 }
 
-void
-purple_txt_cancel(PurpleSrvTxtQueryData *query_data)
-{
-	purple_srv_txt_query_destroy(query_data);
-}
-
-void
-purple_srv_cancel(PurpleSrvTxtQueryData *query_data)
-{
-	purple_srv_txt_query_destroy(query_data);
-}
-
 const gchar *
 purple_txt_response_get_content(PurpleTxtResponse *resp)
 {
--- a/libpurple/dnssrv.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/dnssrv.h	Mon Oct 31 01:25:36 2011 +0000
@@ -32,10 +32,6 @@
 typedef struct _PurpleSrvResponse PurpleSrvResponse;
 typedef struct _PurpleTxtResponse PurpleTxtResponse;
 
-/* For compatibility, should be removed for 3.0.0
- */
-typedef struct _PurpleSrvTxtQueryData PurpleSrvQueryData;
-
 #include <glib.h>
 
 enum PurpleDnsType {
@@ -74,7 +70,7 @@
 
 	/** Called just before @a query_data is freed; this should cancel any
 	 *  further use of @a query_data the UI would make. Unneeded if
-	 *  #resolve_host is not implemented.
+	 *  #resolve is not implemented.
 	 */
 	void (*destroy)(PurpleSrvTxtQueryData *query_data);
 
@@ -103,86 +99,40 @@
 /**
  * Queries an SRV record.
  *
- * @param account the account that the query is being done for (or NULL)
- * @param protocol Name of the protocol (e.g. "sip")
+ * @param account   The account that the query is being done for (or NULL)
+ * @param protocol  Name of the protocol (e.g. "sip")
  * @param transport Name of the transport ("tcp" or "udp")
- * @param domain Domain name to query (e.g. "blubb.com")
- * @param cb A callback which will be called with the results
+ * @param domain    Domain name to query (e.g. "blubb.com")
+ * @param cb        A callback which will be called with the results
  * @param extradata Extra data to be passed to the callback
  *
- * @since 2.8.0
+ * @return NULL if there was an error, otherwise return a reference to
+ *         a data structure that can be used to cancel the pending
+ *         DNS query, if needed.
  */
-PurpleSrvTxtQueryData *purple_srv_resolve_account(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata);
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSSRV_C_)
-/**
- * Queries an SRV record.
- *
- * @param protocol Name of the protocol (e.g. "sip")
- * @param transport Name of the transport ("tcp" or "udp")
- * @param domain Domain name to query (e.g. "blubb.com")
- * @param cb A callback which will be called with the results
- * @param extradata Extra data to be passed to the callback
- *
- * @deprecated Use purple_srv_resolve_account instead
- */
-PurpleSrvTxtQueryData *purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata);
-#endif
-
-/**
- * Cancel an SRV or DNS query.
- *
- * @param query_data The request to cancel.
- *
- * @deprecated Use purple_srv_txt_query_destroy instead
- */
-void purple_srv_cancel(PurpleSrvTxtQueryData *query_data);
+PurpleSrvTxtQueryData *purple_srv_resolve(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata);
 
 /**
  * Queries an TXT record.
  *
- * @param account the account that the query is being done for (or NULL)
- * @param owner Name of the protocol (e.g. "_xmppconnect")
- * @param domain Domain name to query (e.g. "blubb.com")
- * @param cb A callback which will be called with the results
+ * @param account   The account that the query is being done for (or NULL)
+ * @param owner     Name of the protocol (e.g. "_xmppconnect")
+ * @param domain    Domain name to query (e.g. "blubb.com")
+ * @param cb        A callback which will be called with the results
  * @param extradata Extra data to be passed to the callback
  *
- * @since 2.8.0
+ * @return NULL if there was an error, otherwise return a reference to
+ *         a data structure that can be used to cancel the pending
+ *         DNS query, if needed.
  */
-PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata);
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSSRV_C_)
-/**
- * Queries an TXT record.
- *
- * @param owner Name of the protocol (e.g. "_xmppconnect")
- * @param domain Domain name to query (e.g. "blubb.com")
- * @param cb A callback which will be called with the results
- * @param extradata Extra data to be passed to the callback
- *
- * @deprecated Use purple_txt_resolve_account instead
- *
- * @since 2.6.0
- */
-PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata);
-#endif
-
-/**
- * Cancel an TXT DNS query.
- *
- * @param query_data The request to cancel.
- * @since 2.6.0
- *
- * @deprecated Use purple_srv_txt_query_destroy instead
- */
-void purple_txt_cancel(PurpleSrvTxtQueryData *query_data);
+PurpleSrvTxtQueryData *purple_txt_resolve(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata);
 
 /**
  * Get the value of the current TXT record.
  *
  * @param response  The TXT response record
- * @returns The value of the current TXT record.
- * @since 2.6.0
+ *
+ * @return The value of the current TXT record.
  */
 const gchar *purple_txt_response_get_content(PurpleTxtResponse *response);
 
@@ -190,7 +140,6 @@
  * Destroy a TXT DNS response object.
  *
  * @param response The PurpleTxtResponse to destroy.
- * @since 2.6.0
  */
 void purple_txt_response_destroy(PurpleTxtResponse *response);
 
@@ -220,7 +169,7 @@
 PurpleSrvTxtQueryUiOps *purple_srv_txt_query_get_ui_ops(void);
 
 /**
- * Get the query from a PurpleDnsQueryData
+ * Get the query from a PurpleSrvTxtQueryData
  *
  * @param query_data The SRV/TXT query
  * @return The query.
@@ -228,7 +177,7 @@
 char *purple_srv_txt_query_get_query(PurpleSrvTxtQueryData *query_data);
 
 /**
- * Get the type from a PurpleDnsQueryData (TXT or SRV)
+ * Get the type from a PurpleSrvTxtQueryData (TXT or SRV)
  *
  * @param query_data The query
  * @return The query.
@@ -240,3 +189,4 @@
 #endif
 
 #endif /* _PURPLE_DNSSRV_H */
+
--- a/libpurple/eventloop.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/eventloop.h	Mon Oct 31 01:25:36 2011 +0000
@@ -145,7 +145,6 @@
 	 * #timeout_add.
 	 *
 	 * @see purple_timeout_add_seconds()
-	 * @since 2.1.0
 	 **/
 	guint (*timeout_add_seconds)(guint interval, GSourceFunc function,
 	                             gpointer data);
@@ -192,8 +191,6 @@
  * @param data		data to pass to @a function.
  * @return A handle to the timer which can be passed to
  *         purple_timeout_remove() to remove the timer.
- *
- * @since 2.1.0
  */
 guint purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data);
 
--- a/libpurple/example/nullclient.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/example/nullclient.c	Mon Oct 31 01:25:36 2011 +0000
@@ -237,7 +237,7 @@
 signed_on(PurpleConnection *gc, gpointer null)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	printf("Account connected: %s %s\n", account->username, account->protocol_id);
+	printf("Account connected: %s %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
 }
 
 static void
--- a/libpurple/ft.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/ft.c	Mon Oct 31 01:25:36 2011 +0000
@@ -220,7 +220,7 @@
 		purple_xfer_destroy(xfer);
 }
 
-static void
+void
 purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status)
 {
 	g_return_if_fail(xfer != NULL);
@@ -490,7 +490,7 @@
 purple_xfer_ask_recv(PurpleXfer *xfer)
 {
 	char *buf, *size_buf;
-	size_t size;
+	goffset size;
 	gconstpointer thumb;
 	gsize thumb_size;
 
@@ -720,6 +720,20 @@
 	purple_xfer_unref(xfer);
 }
 
+int purple_xfer_get_fd(PurpleXfer *xfer)
+{
+	g_return_val_if_fail(xfer != NULL, 0);
+
+	return xfer->fd;
+}
+
+int purple_xfer_get_watcher(PurpleXfer *xfer)
+{
+	g_return_val_if_fail(xfer != NULL, 0);
+
+	return xfer->watcher;
+}
+
 PurpleXferType
 purple_xfer_get_type(const PurpleXfer *xfer)
 {
@@ -751,9 +765,8 @@
 	return xfer->status;
 }
 
-/* FIXME: Rename with cancelled for 3.0.0. */
 gboolean
-purple_xfer_is_canceled(const PurpleXfer *xfer)
+purple_xfer_is_cancelled(const PurpleXfer *xfer)
 {
 	g_return_val_if_fail(xfer != NULL, TRUE);
 
@@ -788,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);
@@ -796,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);
@@ -804,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);
@@ -864,6 +877,20 @@
 	return xfer->end_time;
 }
 
+void purple_xfer_set_fd(PurpleXfer *xfer, int fd)
+{
+	g_return_if_fail(xfer != NULL);
+
+	xfer->fd = fd;
+}
+
+void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher)
+{
+	g_return_if_fail(xfer != NULL);
+
+	xfer->watcher = watcher;
+}
+
 void
 purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed)
 {
@@ -938,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);
 
@@ -947,7 +974,15 @@
 }
 
 void
-purple_xfer_set_bytes_sent(PurpleXfer *xfer, size_t bytes_sent)
+purple_xfer_set_local_port(PurpleXfer *xfer, unsigned int local_port)
+{
+	g_return_if_fail(xfer != NULL);
+
+	xfer->local_port = local_port;
+}
+
+void
+purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent)
 {
 	g_return_if_fail(xfer != NULL);
 
@@ -1404,13 +1439,6 @@
 
 	purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_STARTED);
 
-	/*
-	 * FIXME 3.0.0 -- there's too much broken code depending on fd == 0
-	 * meaning "don't use a real fd"
-	 */
-	if (fd == 0)
-		fd = -1;
-
 	if (type == PURPLE_XFER_RECEIVE) {
 		cond = PURPLE_INPUT_READ;
 
@@ -1701,6 +1729,37 @@
 	}
 }
 
+void
+purple_xfer_set_protocol_data(PurpleXfer *xfer, gpointer proto_data)
+{
+	g_return_if_fail(xfer != NULL);
+
+	xfer->proto_data = proto_data;
+}
+
+gpointer
+purple_xfer_get_protocol_data(const PurpleXfer *xfer)
+{
+	g_return_val_if_fail(xfer != NULL, NULL);
+
+	return xfer->proto_data;
+}
+
+void purple_xfer_set_ui_data(PurpleXfer *xfer, gpointer ui_data)
+{
+	g_return_if_fail(xfer != NULL);
+
+	xfer->ui_data = ui_data;
+}
+
+gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer)
+{
+	g_return_val_if_fail(xfer != NULL, NULL);
+
+	return xfer->ui_data;
+}
+
+
 /**************************************************************************
  * File Transfer Subsystem API
  **************************************************************************/
--- a/libpurple/ft.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/ft.h	Mon Oct 31 01:25:36 2011 +0000
@@ -87,7 +87,6 @@
 	 *
 	 * @return size if the write was successful, or a value between 0 and
 	 *         size on error.
-	 * @since 2.6.0
 	 */
 	gssize (*ui_write)(PurpleXfer *xfer, const guchar *buffer, gssize size);
 
@@ -102,7 +101,6 @@
 	 * @returns The amount of data in the buffer, 0 if nothing is available,
 	 *          and a negative value if an error occurred and the transfer
 	 *          should be cancelled (libpurple will cancel).
-	 * @since 2.6.0
 	 */
 	gssize (*ui_read)(PurpleXfer *xfer, guchar **buffer, gssize size);
 
@@ -115,8 +113,6 @@
 	 * @param xfer    The file transfer structure
 	 * @param buffer  A pointer to the beginning of the unwritten data.
 	 * @param size    The amount of unwritten data.
-	 *
-	 * @since 2.6.0
 	 */
 	void (*data_not_sent)(PurpleXfer *xfer, const guchar *buffer, gsize size);
 
@@ -144,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.       */
 
@@ -155,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.    */
 
@@ -185,7 +181,7 @@
 	PurpleXferUiOps *ui_ops;            /**< UI-specific operations. */
 	void *ui_data;                    /**< UI-specific data.       */
 
-	void *data;                       /**< prpl-specific data.     */
+	void *proto_data;                 /**< prpl-specific data.     */
 };
 
 #ifdef __cplusplus
@@ -266,6 +262,24 @@
 void purple_xfer_request_denied(PurpleXfer *xfer);
 
 /**
+ * Returns the socket file descriptor.
+ *
+ * @param xfer The file transfer.
+ *
+ * @return The socket file descriptor.
+ */
+int purple_xfer_get_fd(PurpleXfer *xfer);
+
+/**
+ * Returns the Watcher for the transfer.
+ *
+ * @param xfer The file transfer.
+ *
+ * @return The watcher.
+ */
+int purple_xfer_get_watcher(PurpleXfer *xfer);
+
+/**
  * Returns the type of file transfer.
  *
  * @param xfer The file transfer.
@@ -289,8 +303,6 @@
  * @param xfer The file transfer.
  *
  * @return The name of the remote user.
- *
- * @since 2.1.0
  */
 const char *purple_xfer_get_remote_user(const PurpleXfer *xfer);
 
@@ -309,9 +321,8 @@
  * @param xfer The file transfer.
  *
  * @return Whether or not the transfer was cancelled.
- * FIXME: This should be renamed using cancelled for 3.0.0.
  */
-gboolean purple_xfer_is_canceled(const PurpleXfer *xfer);
+gboolean purple_xfer_is_cancelled(const PurpleXfer *xfer);
 
 /**
  * Returns the completed state for a file transfer.
@@ -347,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.
@@ -356,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.
@@ -365,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.
@@ -411,7 +422,6 @@
  * @param xfer  The file transfer.
  *
  * @return The time when the transfer started.
- * @since 2.4.0
  */
 time_t purple_xfer_get_start_time(const PurpleXfer *xfer);
 
@@ -421,11 +431,26 @@
  * @param xfer  The file transfer.
  *
  * @return The time when the transfer ended.
- * @since 2.4.0
  */
 time_t purple_xfer_get_end_time(const PurpleXfer *xfer);
 
 /**
+ * Sets the socket file descriptor.
+ *
+ * @param xfer      The file transfer.
+ * @param fd        The file descriptor.
+ */
+void purple_xfer_set_fd(PurpleXfer *xfer, int fd);
+
+/**
+ * Sets the watcher for the file transfer.
+ *
+ * @param xfer      The file transfer.
+ * @param watcher   The watcher.
+ */
+void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher);
+
+/**
  * Sets the completed state for the file transfer.
  *
  * @param xfer      The file transfer.
@@ -434,6 +459,14 @@
 void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed);
 
 /**
+ * Sets the current status for the file transfer.
+ *
+ * @param xfer      The file transfer.
+ * @param status    The current status.
+ */
+void purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status);
+
+/**
  * Sets the filename for the file transfer.
  *
  * @param xfer     The file transfer.
@@ -463,7 +496,15 @@
  * @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.
+ *
+ * @param xfer          The file transfer.
+ * @param local_port    The local port.
+ */
+void purple_xfer_set_local_port(PurpleXfer *xfer, unsigned int local_port);
 
 /**
  * Sets the current working position in the active file transfer.  This
@@ -478,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.
@@ -596,11 +637,8 @@
  * file receive transfer. On send, @a fd must be specified, and
  * @a ip and @a port are ignored.
  *
- * Prior to libpurple 2.6.0, passing '0' to @a fd was special-cased to
- * allow the protocol plugin to facilitate the file transfer itself. As of
- * 2.6.0, this is supported (for backward compatibility), but will be
- * removed in libpurple 3.0.0. If a prpl detects that the running libpurple
- * is running 2.6.0 or higher, it should use the invalid fd '-1'.
+ * Passing @a fd as '-1' is a special-case and indicates to the
+ * protocol plugin to facilitate the file transfer itself.
  *
  * @param xfer The file transfer.
  * @param fd   The file descriptor for the socket.
@@ -677,8 +715,6 @@
  * read/write/data_not_sent UI ops.
  *
  * @param xfer The file transfer which is ready.
- *
- * @since 2.6.0
  */
 void purple_xfer_ui_ready(PurpleXfer *xfer);
 
@@ -688,8 +724,6 @@
  * ops and cannot/does not provide a raw fd to the core.
  *
  * @param xfer The file transfer which is ready.
- *
- * @since 2.6.0
  */
 void purple_xfer_prpl_ready(PurpleXfer *xfer);
 
@@ -700,7 +734,6 @@
  * @param len  If not @c NULL, the length of the thumbnail data returned
  *             will be set in the location pointed to by this.
  * @return The thumbnail data, or NULL if there is no thumbnail
- * @since 2.7.0
  */
 gconstpointer purple_xfer_get_thumbnail(const PurpleXfer *xfer, gsize *len);
 
@@ -709,7 +742,6 @@
  *
  * @param xfer The file transfer to get the mimetype for
  * @return The mimetype of the thumbnail, or @c NULL if not thumbnail is set
- * @since 2.7.0
  */
 const gchar *purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer);
 
@@ -721,7 +753,6 @@
  * @param thumbnail A pointer to the thumbnail data, this will be copied
  * @param size The size in bytes of the passed in thumbnail data
  * @param mimetype The mimetype of the generated thumbnail
- * @since 2.7.0
  */
 void purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
 	gsize size, const gchar *mimetype);
@@ -733,10 +764,44 @@
  * @param xfer The file transfer to create a thumbnail for
  * @param formats A comma-separated list of mimetypes for image formats
  *	 	  the protocols can use for thumbnails.
- * @since 2.7.0
  */
 void purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats);
 
+/**
+ * Sets the protocol data for a file transfer.
+ *
+ * @param xfer			The file transfer.
+ * @param proto_data	The protocol data to set for the file transfer.
+ */
+void purple_xfer_set_protocol_data(PurpleXfer *xfer, gpointer proto_data);
+ 
+/**
+ * Gets the protocol data for a file transfer.
+ *
+ * @param xfer			The file transfer.
+ *
+ * @return The protocol data for the file transfer.
+ */
+gpointer purple_xfer_get_protocol_data(const PurpleXfer *xfer);
+
+/**
+ * Set the UI data associated with this file transfer.
+ *
+ * @param xfer			The file transfer.
+ * @param ui_data		A pointer to associate with this file transfer.
+ */
+void purple_xfer_set_ui_data(PurpleXfer *xfer, gpointer ui_data);
+
+/**
+ * Get the UI data associated with this file transfer.
+ *
+ * @param xfer			The file transfer.
+ *
+ * @return The UI data associated with this file transfer.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libpurple core.
+ */
+gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer);
 
 /*@}*/
 
@@ -783,3 +848,4 @@
 #endif
 
 #endif /* _PURPLE_FT_H_ */
+
--- a/libpurple/gaim-compat.h	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2317 +0,0 @@
-/**
- * @file gaim-compat.h Gaim Compat macros
- * @ingroup core
- */
-
-/* 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
- */
-#ifndef _GAIM_COMPAT_H_
-#define _GAIM_COMPAT_H_
-
-#include <glib.h>
-
-/* from account.h */
-#define GaimAccountUiOps PurpleAccountUiOps
-#define GaimAccount PurpleAccount
-
-#define GaimFilterAccountFunc PurpleFilterAccountFunc
-#define GaimAccountRequestAuthorizationCb PurpleAccountRequestAuthorizationCb
-
-#define gaim_account_new           purple_account_new
-#define gaim_account_destroy       purple_account_destroy
-#define gaim_account_connect       purple_account_connect
-#define gaim_account_register      purple_account_register
-#define gaim_account_disconnect    purple_account_disconnect
-#define gaim_account_notify_added  purple_account_notify_added
-#define gaim_account_request_add   purple_account_request_add
-#define gaim_account_request_close   purple_account_request_close
-
-#define gaim_account_request_authorization     purple_account_request_authorization
-#define gaim_account_request_change_password   purple_account_request_change_password
-#define gaim_account_request_change_user_info  purple_account_request_change_user_info
-
-#define gaim_account_set_username            purple_account_set_username
-#define gaim_account_set_password            purple_account_set_password
-#define gaim_account_set_alias               purple_account_set_alias
-#define gaim_account_set_user_info           purple_account_set_user_info
-#define gaim_account_set_buddy_icon_path     purple_account_set_buddy_icon_path
-#define gaim_account_set_protocol_id         purple_account_set_protocol_id
-#define gaim_account_set_connection          purple_account_set_connection
-#define gaim_account_set_remember_password   purple_account_set_remember_password
-#define gaim_account_set_check_mail          purple_account_set_check_mail
-#define gaim_account_set_enabled             purple_account_set_enabled
-#define gaim_account_set_proxy_info          purple_account_set_proxy_info
-#define gaim_account_set_status_types        purple_account_set_status_types
-#define gaim_account_set_status              purple_account_set_status
-#define gaim_account_set_status_list         purple_account_set_status_list
-
-#define gaim_account_clear_settings   purple_account_clear_settings
-
-#define gaim_account_set_int    purple_account_set_int
-#define gaim_account_set_string purple_account_set_string
-#define gaim_account_set_bool   purple_account_set_bool
-
-#define gaim_account_set_ui_int     purple_account_set_ui_int
-#define gaim_account_set_ui_string  purple_account_set_ui_string
-#define gaim_account_set_ui_bool    purple_account_set_ui_bool
-
-#define gaim_account_is_connected     purple_account_is_connected
-#define gaim_account_is_connecting    purple_account_is_connecting
-#define gaim_account_is_disconnected  purple_account_is_disconnected
-
-#define gaim_account_get_username           purple_account_get_username
-#define gaim_account_get_password           purple_account_get_password
-#define gaim_account_get_alias              purple_account_get_alias
-#define gaim_account_get_user_info          purple_account_get_user_info
-#define gaim_account_get_buddy_icon_path    purple_account_get_buddy_icon_path
-#define gaim_account_get_protocol_id        purple_account_get_protocol_id
-#define gaim_account_get_protocol_name      purple_account_get_protocol_name
-#define gaim_account_get_connection         purple_account_get_connection
-#define gaim_account_get_remember_password  purple_account_get_remember_password
-#define gaim_account_get_check_mail         purple_account_get_check_mail
-#define gaim_account_get_enabled            purple_account_get_enabled
-#define gaim_account_get_proxy_info         purple_account_get_proxy_info
-#define gaim_account_get_active_status      purple_account_get_active_status
-#define gaim_account_get_status             purple_account_get_status
-#define gaim_account_get_status_type        purple_account_get_status_type
-#define gaim_account_get_status_type_with_primitive \
-	purple_account_get_status_type_with_primitive
-
-#define gaim_account_get_presence       purple_account_get_presence
-#define gaim_account_is_status_active   purple_account_is_status_active
-#define gaim_account_get_status_types   purple_account_get_status_types
-
-#define gaim_account_get_int            purple_account_get_int
-#define gaim_account_get_string         purple_account_get_string
-#define gaim_account_get_bool           purple_account_get_bool
-
-#define gaim_account_get_ui_int     purple_account_get_ui_int
-#define gaim_account_get_ui_string  purple_account_get_ui_string
-#define gaim_account_get_ui_bool    purple_account_get_ui_bool
-
-
-#define gaim_account_get_log      purple_account_get_log
-#define gaim_account_destroy_log  purple_account_destroy_log
-
-#define gaim_account_add_buddy       purple_account_add_buddy
-#define gaim_account_add_buddies     purple_account_add_buddies
-#define gaim_account_remove_buddy    purple_account_remove_buddy
-#define gaim_account_remove_buddies  purple_account_remove_buddies
-
-#define gaim_account_remove_group  purple_account_remove_group
-
-#define gaim_account_change_password  purple_account_change_password
-
-#define gaim_account_supports_offline_message  purple_account_supports_offline_message
-
-#define gaim_accounts_add      purple_accounts_add
-#define gaim_accounts_remove   purple_accounts_remove
-#define gaim_accounts_delete   purple_accounts_delete
-#define gaim_accounts_reorder  purple_accounts_reorder
-
-#define gaim_accounts_get_all         purple_accounts_get_all
-#define gaim_accounts_get_all_active  purple_accounts_get_all_active
-
-#define gaim_accounts_find   purple_accounts_find
-
-#define gaim_accounts_restore_current_statuses  purple_accounts_restore_current_statuses
-
-#define gaim_accounts_set_ui_ops  purple_accounts_set_ui_ops
-#define gaim_accounts_get_ui_ops  purple_accounts_get_ui_ops
-
-#define gaim_accounts_get_handle  purple_accounts_get_handle
-
-#define gaim_accounts_init    purple_accounts_init
-#define gaim_accounts_uninit  purple_accounts_uninit
-
-/* from accountopt.h */
-
-#define GaimAccountOption     PurpleAccountOption
-#define GaimAccountUserSplit  PurpleAccountUserSplit
-
-#define gaim_account_option_new         purple_account_option_new
-#define gaim_account_option_bool_new    purple_account_option_bool_new
-#define gaim_account_option_int_new     purple_account_option_int_new
-#define gaim_account_option_string_new  purple_account_option_string_new
-#define gaim_account_option_list_new    purple_account_option_list_new
-
-#define gaim_account_option_destroy  purple_account_option_destroy
-
-#define gaim_account_option_set_default_bool    purple_account_option_set_default_bool
-#define gaim_account_option_set_default_int     purple_account_option_set_default_int
-#define gaim_account_option_set_default_string  purple_account_option_set_default_string
-
-#define gaim_account_option_set_masked  purple_account_option_set_masked
-
-#define gaim_account_option_set_list  purple_account_option_set_list
-
-#define gaim_account_option_add_list_item  purple_account_option_add_list_item
-
-#define gaim_account_option_get_type     purple_account_option_get_type
-#define gaim_account_option_get_text     purple_account_option_get_text
-#define gaim_account_option_get_setting  purple_account_option_get_setting
-
-#define gaim_account_option_get_default_bool        purple_account_option_get_default_bool
-#define gaim_account_option_get_default_int         purple_account_option_get_default_int
-#define gaim_account_option_get_default_string      purple_account_option_get_default_string
-#define gaim_account_option_get_default_list_value  purple_account_option_get_default_list_value
-
-#define gaim_account_option_get_masked  purple_account_option_get_masked
-#define gaim_account_option_get_list    purple_account_option_get_list
-
-#define gaim_account_user_split_new      purple_account_user_split_new
-#define gaim_account_user_split_destroy  purple_account_user_split_destroy
-
-#define gaim_account_user_split_get_text           purple_account_user_split_get_text
-#define gaim_account_user_split_get_default_value  purple_account_user_split_get_default_value
-#define gaim_account_user_split_get_separator      purple_account_user_split_get_separator
-
-/* from blist.h */
-
-#define GaimBuddyList    PurpleBuddyList
-#define GaimBlistUiOps   PurpleBlistUiOps
-#define GaimBlistNode    PurpleBlistNode
-
-#define GaimChat     PurpleChat
-#define GaimGroup    PurpleGroup
-#define GaimContact  PurpleContact
-#define GaimBuddy    PurpleBuddy
-
-#define GAIM_BLIST_GROUP_NODE     PURPLE_BLIST_GROUP_NODE
-#define GAIM_BLIST_CONTACT_NODE   PURPLE_BLIST_CONTACT_NODE
-#define GAIM_BLIST_BUDDY_NODE     PURPLE_BLIST_BUDDY_NODE
-#define GAIM_BLIST_CHAT_NODE      PURPLE_BLIST_CHAT_NODE
-#define GAIM_BLIST_OTHER_NODE     PURPLE_BLIST_OTHER_NODE
-#define GaimBlistNodeType         PurpleBlistNodeType
-
-#define GAIM_BLIST_NODE_IS_CHAT       PURPLE_BLIST_NODE_IS_CHAT
-#define GAIM_BLIST_NODE_IS_BUDDY      PURPLE_BLIST_NODE_IS_BUDDY
-#define GAIM_BLIST_NODE_IS_CONTACT    PURPLE_BLIST_NODE_IS_CONTACT
-#define GAIM_BLIST_NODE_IS_GROUP      PURPLE_BLIST_NODE_IS_GROUP
-
-#define GAIM_BUDDY_IS_ONLINE PURPLE_BUDDY_IS_ONLINE
-
-#define GAIM_BLIST_NODE_FLAG_NO_SAVE  PURPLE_BLIST_NODE_FLAG_NO_SAVE
-#define GaimBlistNodeFlags            PurpleBlistNodeFlags
-
-#define GAIM_BLIST_NODE_HAS_FLAG     PURPLE_BLIST_NODE_HAS_FLAG
-#define GAIM_BLIST_NODE_SHOULD_SAVE  PURPLE_BLIST_NODE_SHOULD_SAVE
-
-#define GAIM_BLIST_NODE_NAME   PURPLE_BLIST_NODE_NAME
-
-
-#define gaim_blist_new  purple_blist_new
-#define gaim_set_blist  purple_set_blist
-#define gaim_get_blist  purple_get_blist
-
-#define gaim_blist_get_root   purple_blist_get_root
-#define gaim_blist_node_next  purple_blist_node_next
-
-#define gaim_blist_show  purple_blist_show
-
-#define gaim_blist_destroy  purple_blist_destroy
-
-#define gaim_blist_set_visible  purple_blist_set_visible
-
-#define gaim_blist_update_buddy_status  purple_blist_update_buddy_status
-#define gaim_blist_update_buddy_icon    purple_blist_update_buddy_icon
-
-
-#define gaim_blist_alias_contact       purple_blist_alias_contact
-#define gaim_blist_alias_buddy         purple_blist_alias_buddy
-#define gaim_blist_server_alias_buddy  purple_blist_server_alias_buddy
-#define gaim_blist_alias_chat          purple_blist_alias_chat
-
-#define gaim_blist_rename_buddy  purple_blist_rename_buddy
-#define gaim_blist_rename_group  purple_blist_rename_group
-
-#define gaim_chat_new        purple_chat_new
-#define gaim_blist_add_chat  purple_blist_add_chat
-
-#define gaim_buddy_new           purple_buddy_new
-#define gaim_buddy_set_icon      purple_buddy_set_icon
-#define gaim_buddy_get_account   purple_buddy_get_account
-#define gaim_buddy_get_name      purple_buddy_get_name
-#define gaim_buddy_get_icon      purple_buddy_get_icon
-#define gaim_buddy_get_contact   purple_buddy_get_contact
-#define gaim_buddy_get_presence  purple_buddy_get_presence
-
-#define gaim_blist_add_buddy  purple_blist_add_buddy
-
-#define gaim_group_new  purple_group_new
-
-#define gaim_blist_add_group  purple_blist_add_group
-
-#define gaim_contact_new  purple_contact_new
-
-#define gaim_blist_add_contact    purple_blist_add_contact
-#define gaim_blist_merge_contact  purple_blist_merge_contact
-
-#define gaim_contact_get_priority_buddy  purple_contact_get_priority_buddy
-#define gaim_contact_set_alias           purple_contact_set_alias
-#define gaim_contact_get_alias           purple_contact_get_alias
-#define gaim_contact_on_account          purple_contact_on_account
-
-#define gaim_contact_invalidate_priority_buddy  purple_contact_invalidate_priority_buddy
-
-#define gaim_blist_remove_buddy    purple_blist_remove_buddy
-#define gaim_blist_remove_contact  purple_blist_remove_contact
-#define gaim_blist_remove_chat     purple_blist_remove_chat
-#define gaim_blist_remove_group    purple_blist_remove_group
-
-#define gaim_buddy_get_alias_only     purple_buddy_get_alias_only
-#define gaim_buddy_get_server_alias   purple_buddy_get_server_alias
-#define gaim_buddy_get_contact_alias  purple_buddy_get_contact_alias
-#define gaim_buddy_get_local_alias    purple_buddy_get_local_alias
-#define gaim_buddy_get_alias          purple_buddy_get_alias
-
-#define gaim_chat_get_name  purple_chat_get_name
-
-#define gaim_find_buddy           purple_find_buddy
-#define gaim_find_buddy_in_group  purple_find_buddy_in_group
-#define gaim_find_buddies         purple_find_buddies
-
-#define gaim_find_group  purple_find_group
-
-#define gaim_blist_find_chat  purple_blist_find_chat
-
-#define gaim_chat_get_group   purple_chat_get_group
-#define gaim_buddy_get_group  purple_buddy_get_group
-
-#define gaim_group_get_accounts  purple_group_get_accounts
-#define gaim_group_on_account    purple_group_on_account
-
-#define gaim_blist_add_account     purple_blist_add_account
-#define gaim_blist_remove_account  purple_blist_remove_account
-
-#define gaim_blist_get_group_size          purple_blist_get_group_size
-#define gaim_blist_get_group_online_count  purple_blist_get_group_online_count
-
-#define gaim_blist_load           purple_blist_load
-#define gaim_blist_schedule_save  purple_blist_schedule_save
-
-#define gaim_blist_request_add_buddy  purple_blist_request_add_buddy
-#define gaim_blist_request_add_chat   purple_blist_request_add_chat
-#define gaim_blist_request_add_group  purple_blist_request_add_group
-
-#define gaim_blist_node_set_bool    purple_blist_node_set_bool
-#define gaim_blist_node_get_bool    purple_blist_node_get_bool
-#define gaim_blist_node_set_int     purple_blist_node_set_int
-#define gaim_blist_node_get_int     purple_blist_node_get_int
-#define gaim_blist_node_set_string  purple_blist_node_set_string
-#define gaim_blist_node_get_string  purple_blist_node_get_string
-
-#define gaim_blist_node_remove_setting  purple_blist_node_remove_setting
-
-#define gaim_blist_node_set_flags  purple_blist_node_set_flags
-#define gaim_blist_node_get_flags  purple_blist_node_get_flags
-
-#define gaim_blist_node_get_extended_menu  purple_blist_node_get_extended_menu
-
-#define gaim_blist_set_ui_ops  purple_blist_set_ui_ops
-#define gaim_blist_get_ui_ops  purple_blist_get_ui_ops
-
-#define gaim_blist_get_handle  purple_blist_get_handle
-
-#define gaim_blist_init    purple_blist_init
-#define gaim_blist_uninit  purple_blist_uninit
-
-
-#define GaimBuddyIcon  PurpleBuddyIcon
-
-#define gaim_buddy_icon_new(account, username, icon_data, icon_len)\
-        purple_buddy_icon_new(account, username, g_memdup(icon_data, icon_len), icon_len)
-#define gaim_buddy_icon_ref      purple_buddy_icon_ref
-#define gaim_buddy_icon_unref    purple_buddy_icon_unref
-#define gaim_buddy_icon_update   purple_buddy_icon_update
-
-#define gaim_buddy_icon_set_data(icon, data, len) \
-        purple_buddy_icon_set_data(icon, g_memdup(data, len), len, NULL);
-
-#define gaim_buddy_icon_get_account   purple_buddy_icon_get_account
-#define gaim_buddy_icon_get_username  purple_buddy_icon_get_username
-#define gaim_buddy_icon_get_data      purple_buddy_icon_get_data
-#define gaim_buddy_icon_get_type      purple_buddy_icon_get_extension
-
-#define gaim_buddy_icons_set_for_user(icon, data, len) \
-        purple_buddy_icons_set_for_user(icon, g_memdup(data, len), len, NULL)
-#define gaim_buddy_icons_set_caching    purple_buddy_icons_set_caching
-#define gaim_buddy_icons_is_caching     purple_buddy_icons_is_caching
-#define gaim_buddy_icons_set_cache_dir  purple_buddy_icons_set_cache_dir
-#define gaim_buddy_icons_get_cache_dir  purple_buddy_icons_get_cache_dir
-#define gaim_buddy_icons_get_handle     purple_buddy_icons_get_handle
-
-#define gaim_buddy_icons_init    purple_buddy_icons_init
-#define gaim_buddy_icons_uninit  purple_buddy_icons_uninit
-
-#define gaim_buddy_icon_get_scale_size  purple_buddy_icon_get_scale_size
-
-/* from cipher.h */
-
-#define GAIM_CIPHER          PURPLE_CIPHER
-#define GAIM_CIPHER_OPS      PURPLE_CIPHER_OPS
-#define GAIM_CIPHER_CONTEXT  PURPLE_CIPHER_CONTEXT
-
-#define GaimCipher         PurpleCipher
-#define GaimCipherOps      PurpleCipherOps
-#define GaimCipherContext  PurpleCipherContext
-
-#define GAIM_CIPHER_CAPS_SET_OPT  PURPLE_CIPHER_CAPS_SET_OPT
-#define GAIM_CIPHER_CAPS_GET_OPT  PURPLE_CIPHER_CAPS_GET_OPT
-#define GAIM_CIPHER_CAPS_INIT     PURPLE_CIPHER_CAPS_INIT
-#define GAIM_CIPHER_CAPS_RESET    PURPLE_CIPHER_CAPS_RESET
-#define GAIM_CIPHER_CAPS_UNINIT   PURPLE_CIPHER_CAPS_UNINIT
-#define GAIM_CIPHER_CAPS_SET_IV   PURPLE_CIPHER_CAPS_SET_IV
-#define GAIM_CIPHER_CAPS_APPEND   PURPLE_CIPHER_CAPS_APPEND
-#define GAIM_CIPHER_CAPS_DIGEST   PURPLE_CIPHER_CAPS_DIGEST
-#define GAIM_CIPHER_CAPS_ENCRYPT  PURPLE_CIPHER_CAPS_ENCRYPT
-#define GAIM_CIPHER_CAPS_DECRYPT  PURPLE_CIPHER_CAPS_DECRYPT
-#define GAIM_CIPHER_CAPS_SET_SALT  PURPLE_CIPHER_CAPS_SET_SALT
-#define GAIM_CIPHER_CAPS_GET_SALT_SIZE  PURPLE_CIPHER_CAPS_GET_SALT_SIZE
-#define GAIM_CIPHER_CAPS_SET_KEY        PURPLE_CIPHER_CAPS_SET_KEY
-#define GAIM_CIPHER_CAPS_GET_KEY_SIZE   PURPLE_CIPHER_CAPS_GET_KEY_SIZE
-#define GAIM_CIPHER_CAPS_UNKNOWN        PURPLE_CIPHER_CAPS_UNKNOWN
-
-#define gaim_cipher_get_name          purple_cipher_get_name
-#define gaim_cipher_get_capabilities  purple_cipher_get_capabilities
-#define gaim_cipher_digest_region     purple_cipher_digest_region
-
-#define gaim_ciphers_find_cipher        purple_ciphers_find_cipher
-#define gaim_ciphers_register_cipher    purple_ciphers_register_cipher
-#define gaim_ciphers_unregister_cipher  purple_ciphers_unregister_cipher
-#define gaim_ciphers_get_ciphers        purple_ciphers_get_ciphers
-
-#define gaim_ciphers_get_handle  purple_ciphers_get_handle
-#define gaim_ciphers_init        purple_ciphers_init
-#define gaim_ciphers_uninit      purple_ciphers_uninit
-
-#define gaim_cipher_context_set_option  purple_cipher_context_set_option
-#define gaim_cipher_context_get_option  purple_cipher_context_get_option
-
-#define gaim_cipher_context_new            purple_cipher_context_new
-#define gaim_cipher_context_new_by_name    purple_cipher_context_new_by_name
-#define gaim_cipher_context_reset          purple_cipher_context_reset
-#define gaim_cipher_context_destroy        purple_cipher_context_destroy
-#define gaim_cipher_context_set_iv         purple_cipher_context_set_iv
-#define gaim_cipher_context_append         purple_cipher_context_append
-#define gaim_cipher_context_digest         purple_cipher_context_digest
-#define gaim_cipher_context_digest_to_str  purple_cipher_context_digest_to_str
-#define gaim_cipher_context_encrypt        purple_cipher_context_encrypt
-#define gaim_cipher_context_decrypt        purple_cipher_context_decrypt
-#define gaim_cipher_context_set_salt       purple_cipher_context_set_salt
-#define gaim_cipher_context_get_salt_size  purple_cipher_context_get_salt_size
-#define gaim_cipher_context_set_key        purple_cipher_context_set_key
-#define gaim_cipher_context_get_key_size   purple_cipher_context_get_key_size
-#define gaim_cipher_context_set_data       purple_cipher_context_set_data
-#define gaim_cipher_context_get_data       purple_cipher_context_get_data
-
-#define gaim_cipher_http_digest_calculate_session_key \
-	purple_cipher_http_digest_calculate_session_key
-
-#define gaim_cipher_http_digest_calculate_response \
-	purple_cipher_http_digest_calculate_response
-
-/* from circbuffer.h */
-
-#define GaimCircBuffer  PurpleCircBuffer
-
-#define gaim_circ_buffer_new           purple_circ_buffer_new
-#define gaim_circ_buffer_destroy       purple_circ_buffer_destroy
-#define gaim_circ_buffer_append        purple_circ_buffer_append
-#define gaim_circ_buffer_get_max_read  purple_circ_buffer_get_max_read
-#define gaim_circ_buffer_mark_read     purple_circ_buffer_mark_read
-
-/* from cmds.h */
-
-#define GaimCmdPriority  PurpleCmdPriority
-#define GaimCmdFlag      PurpleCmdFlag
-#define GaimCmdStatus    PurpleCmdStatus
-#define GaimCmdRet       PurpleCmdRet
-
-#define GAIM_CMD_STATUS_OK            PURPLE_CMD_STATUS_OK
-#define GAIM_CMD_STATUS_FAILED        PURPLE_CMD_STATUS_FAILED
-#define GAIM_CMD_STATUS_NOT_FOUND     PURPLE_CMD_STATUS_NOT_FOUND
-#define GAIM_CMD_STATUS_WRONG_ARGS    PURPLE_CMD_STATUS_WRONG_ARGS
-#define GAIM_CMD_STATUS_WRONG_PRPL    PURPLE_CMD_STATUS_WRONG_PRPL
-#define GAIM_CMD_STATUS_WRONG_TYPE    PURPLE_CMD_STATUS_WRONG_TYPE
-
-#define GAIM_CMD_FUNC  PURPLE_CMD_FUNC
-
-#define GAIM_CMD_RET_OK			PURPLE_CMD_RET_OK
-#define GAIM_CMD_RET_FAILED		PURPLE_CMD_RET_FAILED
-#define GAIM_CMD_RET_CONTINUE	PURPLE_CMD_RET_CONTINUE
-
-#define GAIM_CMD_P_VERY_LOW		PURPLE_CMD_P_VERY_LOW
-#define GAIM_CMD_P_LOW			PURPLE_CMD_P_LOW
-#define GAIM_CMD_P_DEFAULT		PURPLE_CMD_P_DEFAULT
-#define GAIM_CMD_P_PRPL			PURPLE_CMD_P_PRPL
-#define GAIM_CMD_P_PLUGIN		PURPLE_CMD_P_PLUGIN
-#define GAIM_CMD_P_ALIAS		PURPLE_CMD_P_ALIAS
-#define GAIM_CMD_P_HIGH			PURPLE_CMD_P_HIGH
-#define GAIM_CMD_P_VERY_HIGH	PURPLE_CMD_P_VERY_HIGH
-
-#define GAIM_CMD_FLAG_IM		PURPLE_CMD_FLAG_IM
-#define GAIM_CMD_FLAG_CHAT		PURPLE_CMD_FLAG_CHAT
-#define GAIM_CMD_FLAG_PRPL_ONLY	PURPLE_CMD_FLAG_PRPL_ONLY
-#define GAIM_CMD_FLAG_ALLOW_WRONG_ARGS	PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS
-
-
-#define GaimCmdFunc  PurpleCmdFunc
-
-#define GaimCmdId  PurpleCmdId
-
-#define gaim_cmd_register    purple_cmd_register
-#define gaim_cmd_unregister  purple_cmd_unregister
-#define gaim_cmd_do_command  purple_cmd_do_command
-#define gaim_cmd_list        purple_cmd_list
-#define gaim_cmd_help        purple_cmd_help
-
-/* from connection.h */
-
-#define GaimConnection  PurpleConnection
-
-#define GAIM_CONNECTION_HTML              PURPLE_CONNECTION_HTML
-#define GAIM_CONNECTION_NO_BGCOLOR        PURPLE_CONNECTION_NO_BGCOLOR
-#define GAIM_CONNECTION_AUTO_RESP         PURPLE_CONNECTION_AUTO_RESP
-#define GAIM_CONNECTION_FORMATTING_WBFO   PURPLE_CONNECTION_FORMATTING_WBFO
-#define GAIM_CONNECTION_NO_NEWLINES       PURPLE_CONNECTION_NO_NEWLINES
-#define GAIM_CONNECTION_NO_FONTSIZE       PURPLE_CONNECTION_NO_FONTSIZE
-#define GAIM_CONNECTION_NO_URLDESC        PURPLE_CONNECTION_NO_URLDESC
-#define GAIM_CONNECTION_NO_IMAGES         PURPLE_CONNECTION_NO_IMAGES
-
-#define GaimConnectionFlags  PurpleConnectionFlags
-
-#define GAIM_DISCONNECTED  PURPLE_DISCONNECTED
-#define GAIM_CONNECTED     PURPLE_CONNECTED
-#define GAIM_CONNECTING    PURPLE_CONNECTING
-
-#define GaimConnectionState  PurpleConnectionState
-
-#define GaimConnectionUiOps  PurpleConnectionUiOps
-
-#define gaim_connection_new      purple_connection_new
-#define gaim_connection_destroy  purple_connection_destroy
-
-#define gaim_connection_set_state         purple_connection_set_state
-#define gaim_connection_set_account       purple_connection_set_account
-#define gaim_connection_set_display_name  purple_connection_set_display_name
-#define gaim_connection_get_state         purple_connection_get_state
-
-#define GAIM_CONNECTION_IS_CONNECTED  PURPLE_CONNECTION_IS_CONNECTED
-
-#define gaim_connection_get_account       purple_connection_get_account
-#define gaim_connection_get_password      purple_connection_get_password
-#define gaim_connection_get_display_name  purple_connection_get_display_name
-
-#define gaim_connection_update_progress  purple_connection_update_progress
-
-#define gaim_connection_notice  purple_connection_notice
-#define gaim_connection_error   purple_connection_error
-
-#define gaim_connections_disconnect_all  purple_connections_disconnect_all
-
-#define gaim_connections_get_all         purple_connections_get_all
-#define gaim_connections_get_connecting  purple_connections_get_connecting
-
-#define GAIM_CONNECTION_IS_VALID  PURPLE_CONNECTION_IS_VALID
-
-#define gaim_connections_set_ui_ops  purple_connections_set_ui_ops
-#define gaim_connections_get_ui_ops  purple_connections_get_ui_ops
-
-#define gaim_connections_init    purple_connections_init
-#define gaim_connections_uninit  purple_connections_uninit
-#define gaim_connections_get_handle  purple_connections_get_handle
-
-
-/* from conversation.h */
-
-#define GaimConversationUiOps  PurpleConversationUiOps
-#define GaimConversation       PurpleConversation
-#define GaimConvIm             PurpleConvIm
-#define GaimConvChat           PurpleConvChat
-#define GaimConvChatBuddy      PurpleConvChatBuddy
-
-#define GAIM_CONV_TYPE_UNKNOWN  PURPLE_CONV_TYPE_UNKNOWN
-#define GAIM_CONV_TYPE_IM       PURPLE_CONV_TYPE_IM
-#define GAIM_CONV_TYPE_CHAT     PURPLE_CONV_TYPE_CHAT
-#define GAIM_CONV_TYPE_MISC     PURPLE_CONV_TYPE_MISC
-#define GAIM_CONV_TYPE_ANY      PURPLE_CONV_TYPE_ANY
-
-#define GaimConversationType  PurpleConversationType
-
-#define GAIM_CONV_UPDATE_ADD       PURPLE_CONV_UPDATE_ADD
-#define GAIM_CONV_UPDATE_REMOVE    PURPLE_CONV_UPDATE_REMOVE
-#define GAIM_CONV_UPDATE_ACCOUNT   PURPLE_CONV_UPDATE_ACCOUNT
-#define GAIM_CONV_UPDATE_TYPING    PURPLE_CONV_UPDATE_TYPING
-#define GAIM_CONV_UPDATE_UNSEEN    PURPLE_CONV_UPDATE_UNSEEN
-#define GAIM_CONV_UPDATE_LOGGING   PURPLE_CONV_UPDATE_LOGGING
-#define GAIM_CONV_UPDATE_TOPIC     PURPLE_CONV_UPDATE_TOPIC
-#define GAIM_CONV_ACCOUNT_ONLINE   PURPLE_CONV_ACCOUNT_ONLINE
-#define GAIM_CONV_ACCOUNT_OFFLINE  PURPLE_CONV_ACCOUNT_OFFLINE
-#define GAIM_CONV_UPDATE_AWAY      PURPLE_CONV_UPDATE_AWAY
-#define GAIM_CONV_UPDATE_ICON      PURPLE_CONV_UPDATE_ICON
-#define GAIM_CONV_UPDATE_TITLE     PURPLE_CONV_UPDATE_TITLE
-#define GAIM_CONV_UPDATE_CHATLEFT  PURPLE_CONV_UPDATE_CHATLEFT
-#define GAIM_CONV_UPDATE_FEATURES  PURPLE_CONV_UPDATE_FEATURES
-
-#define GaimConvUpdateType  PurpleConvUpdateType
-
-#define GAIM_NOT_TYPING  PURPLE_NOT_TYPING
-#define GAIM_TYPING      PURPLE_TYPING
-#define GAIM_TYPED       PURPLE_TYPED
-
-#define GaimTypingState  PurpleTypingState
-
-#define GAIM_MESSAGE_SEND         PURPLE_MESSAGE_SEND
-#define GAIM_MESSAGE_RECV         PURPLE_MESSAGE_RECV
-#define GAIM_MESSAGE_SYSTEM       PURPLE_MESSAGE_SYSTEM
-#define GAIM_MESSAGE_AUTO_RESP    PURPLE_MESSAGE_AUTO_RESP
-#define GAIM_MESSAGE_ACTIVE_ONLY  PURPLE_MESSAGE_ACTIVE_ONLY
-#define GAIM_MESSAGE_NICK         PURPLE_MESSAGE_NICK
-#define GAIM_MESSAGE_NO_LOG       PURPLE_MESSAGE_NO_LOG
-#define GAIM_MESSAGE_WHISPER      PURPLE_MESSAGE_WHISPER
-#define GAIM_MESSAGE_ERROR        PURPLE_MESSAGE_ERROR
-#define GAIM_MESSAGE_DELAYED      PURPLE_MESSAGE_DELAYED
-#define GAIM_MESSAGE_RAW          PURPLE_MESSAGE_RAW
-#define GAIM_MESSAGE_IMAGES       PURPLE_MESSAGE_IMAGES
-
-#define GaimMessageFlags  PurpleMessageFlags
-
-#define GAIM_CBFLAGS_NONE     PURPLE_CBFLAGS_NONE
-#define GAIM_CBFLAGS_VOICE    PURPLE_CBFLAGS_VOICE
-#define GAIM_CBFLAGS_HALFOP   PURPLE_CBFLAGS_HALFOP
-#define GAIM_CBFLAGS_OP       PURPLE_CBFLAGS_OP
-#define GAIM_CBFLAGS_FOUNDER  PURPLE_CBFLAGS_FOUNDER
-#define GAIM_CBFLAGS_TYPING   PURPLE_CBFLAGS_TYPING
-
-#define GaimConvChatBuddyFlags  PurpleConvChatBuddyFlags
-
-#define gaim_conversations_set_ui_ops  purple_conversations_set_ui_ops
-
-#define gaim_conversation_new          purple_conversation_new
-#define gaim_conversation_destroy      purple_conversation_destroy
-#define gaim_conversation_present      purple_conversation_present
-#define gaim_conversation_get_type     purple_conversation_get_type
-#define gaim_conversation_set_ui_ops   purple_conversation_set_ui_ops
-#define gaim_conversation_get_ui_ops   purple_conversation_get_ui_ops
-#define gaim_conversation_set_account  purple_conversation_set_account
-#define gaim_conversation_get_account  purple_conversation_get_account
-#define gaim_conversation_get_gc       purple_conversation_get_gc
-#define gaim_conversation_set_title    purple_conversation_set_title
-#define gaim_conversation_get_title    purple_conversation_get_title
-#define gaim_conversation_autoset_title  purple_conversation_autoset_title
-#define gaim_conversation_set_name       purple_conversation_set_name
-#define gaim_conversation_get_name       purple_conversation_get_name
-#define gaim_conversation_set_logging    purple_conversation_set_logging
-#define gaim_conversation_is_logging     purple_conversation_is_logging
-#define gaim_conversation_close_logs     purple_conversation_close_logs
-#define gaim_conversation_get_im_data    purple_conversation_get_im_data
-
-#define GAIM_CONV_IM    PURPLE_CONV_IM
-
-#define gaim_conversation_get_chat_data  purple_conversation_get_chat_data
-
-#define GAIM_CONV_CHAT  PURPLE_CONV_CHAT
-
-#define gaim_conversation_set_data       purple_conversation_set_data
-#define gaim_conversation_get_data       purple_conversation_get_data
-
-#define gaim_get_conversations  purple_get_conversations
-#define gaim_get_ims            purple_get_ims
-#define gaim_get_chats          purple_get_chats
-
-#define gaim_find_conversation_with_account \
-	purple_find_conversation_with_account
-
-#define gaim_conversation_write         purple_conversation_write
-#define gaim_conversation_set_features  purple_conversation_set_features
-#define gaim_conversation_get_features  purple_conversation_get_features
-#define gaim_conversation_has_focus     purple_conversation_has_focus
-#define gaim_conversation_update        purple_conversation_update
-#define gaim_conversation_foreach       purple_conversation_foreach
-
-#define gaim_conv_im_get_conversation  purple_conv_im_get_conversation
-#define gaim_conv_im_set_icon          purple_conv_im_set_icon
-#define gaim_conv_im_get_icon          purple_conv_im_get_icon
-#define gaim_conv_im_set_typing_state  purple_conv_im_set_typing_state
-#define gaim_conv_im_get_typing_state  purple_conv_im_get_typing_state
-
-#define gaim_conv_im_start_typing_timeout  purple_conv_im_start_typing_timeout
-#define gaim_conv_im_stop_typing_timeout   purple_conv_im_stop_typing_timeout
-#define gaim_conv_im_get_typing_timeout    purple_conv_im_get_typing_timeout
-#define gaim_conv_im_set_type_again        purple_conv_im_set_type_again
-#define gaim_conv_im_get_type_again        purple_conv_im_get_type_again
-
-#define gaim_conv_im_start_send_typed_timeout \
-	purple_conv_im_start_send_typed_timeout
-
-#define gaim_conv_im_stop_send_typed_timeout \
-	purple_conv_im_stop_send_typed_timeout
-
-#define gaim_conv_im_get_send_typed_timeout \
-	purple_conv_im_get_send_typed_timeout
-
-#define gaim_conv_present_error     purple_conv_present_error
-#define gaim_conv_send_confirm      purple_conv_send_confirm
-
-#define gaim_conv_im_update_typing    purple_conv_im_update_typing
-#define gaim_conv_im_write            purple_conv_im_write
-#define gaim_conv_im_send             purple_conv_im_send
-#define gaim_conv_im_send_with_flags  purple_conv_im_send_with_flags
-
-#define gaim_conv_custom_smiley_add    purple_conv_custom_smiley_add
-#define gaim_conv_custom_smiley_write  purple_conv_custom_smiley_write
-#define gaim_conv_custom_smiley_close  purple_conv_custom_smiley_close
-
-#define gaim_conv_chat_get_conversation  purple_conv_chat_get_conversation
-#define gaim_conv_chat_set_users         purple_conv_chat_set_users
-#define gaim_conv_chat_get_users         purple_conv_chat_get_users
-#define gaim_conv_chat_ignore            purple_conv_chat_ignore
-#define gaim_conv_chat_unignore          purple_conv_chat_unignore
-#define gaim_conv_chat_set_ignored       purple_conv_chat_set_ignored
-#define gaim_conv_chat_get_ignored       purple_conv_chat_get_ignored
-#define gaim_conv_chat_get_ignored_user  purple_conv_chat_get_ignored_user
-#define gaim_conv_chat_is_user_ignored   purple_conv_chat_is_user_ignored
-#define gaim_conv_chat_set_topic         purple_conv_chat_set_topic
-#define gaim_conv_chat_get_topic         purple_conv_chat_get_topic
-#define gaim_conv_chat_set_id            purple_conv_chat_set_id
-#define gaim_conv_chat_get_id            purple_conv_chat_get_id
-#define gaim_conv_chat_write             purple_conv_chat_write
-#define gaim_conv_chat_send              purple_conv_chat_send
-#define gaim_conv_chat_send_with_flags   purple_conv_chat_send_with_flags
-#define gaim_conv_chat_add_user          purple_conv_chat_add_user
-#define gaim_conv_chat_add_users         purple_conv_chat_add_users
-#define gaim_conv_chat_rename_user       purple_conv_chat_rename_user
-#define gaim_conv_chat_remove_user       purple_conv_chat_remove_user
-#define gaim_conv_chat_remove_users      purple_conv_chat_remove_users
-#define gaim_conv_chat_find_user         purple_conv_chat_find_user
-#define gaim_conv_chat_user_set_flags    purple_conv_chat_user_set_flags
-#define gaim_conv_chat_user_get_flags    purple_conv_chat_user_get_flags
-#define gaim_conv_chat_clear_users       purple_conv_chat_clear_users
-#define gaim_conv_chat_set_nick          purple_conv_chat_set_nick
-#define gaim_conv_chat_get_nick          purple_conv_chat_get_nick
-#define gaim_conv_chat_left              purple_conv_chat_left
-#define gaim_conv_chat_has_left          purple_conv_chat_has_left
-
-#define gaim_find_chat                   purple_find_chat
-
-#define gaim_conv_chat_cb_new            purple_conv_chat_cb_new
-#define gaim_conv_chat_cb_find           purple_conv_chat_cb_find
-#define gaim_conv_chat_cb_get_name       purple_conv_chat_cb_get_name
-#define gaim_conv_chat_cb_destroy        purple_conv_chat_cb_destroy
-
-#define gaim_conversations_get_handle    purple_conversations_get_handle
-#define gaim_conversations_init          purple_conversations_init
-#define gaim_conversations_uninit        purple_conversations_uninit
-
-/* from core.h */
-
-#define GaimCore  PurpleCore
-
-#define GaimCoreUiOps  PurpleCoreUiOps
-
-#define gaim_core_init  purple_core_init
-#define gaim_core_quit  purple_core_quit
-
-#define gaim_core_quit_cb      purple_core_quit_cb
-#define gaim_core_get_version  purple_core_get_version
-#define gaim_core_get_ui       purple_core_get_ui
-#define gaim_get_core          purple_get_core
-#define gaim_core_set_ui_ops   purple_core_set_ui_ops
-#define gaim_core_get_ui_ops   purple_core_get_ui_ops
-
-/* from debug.h */
-
-#define GAIM_DEBUG_ALL      PURPLE_DEBUG_ALL
-#define GAIM_DEBUG_MISC     PURPLE_DEBUG_MISC
-#define GAIM_DEBUG_INFO     PURPLE_DEBUG_INFO
-#define GAIM_DEBUG_WARNING  PURPLE_DEBUG_WARNING
-#define GAIM_DEBUG_ERROR    PURPLE_DEBUG_ERROR
-#define GAIM_DEBUG_FATAL    PURPLE_DEBUG_FATAL
-
-#define GaimDebugLevel  PurpleDebugLevel
-
-#define GaimDebugUiOps  PurpleDebugUiOps
-
-
-#define gaim_debug          purple_debug
-#define gaim_debug_misc     purple_debug_misc
-#define gaim_debug_info     purple_debug_info
-#define gaim_debug_warning  purple_debug_warning
-#define gaim_debug_error    purple_debug_error
-#define gaim_debug_fatal    purple_debug_fatal
-
-#define gaim_debug_set_enabled  purple_debug_set_enabled
-#define gaim_debug_is_enabled   purple_debug_is_enabled
-
-#define gaim_debug_set_ui_ops  purple_debug_set_ui_ops
-#define gaim_debug_get_ui_ops  purple_debug_get_ui_ops
-
-#define gaim_debug_init  purple_debug_init
-
-/* from desktopitem.h */
-
-#define GAIM_DESKTOP_ITEM_TYPE_NULL          PURPLE_DESKTOP_ITEM_TYPE_NULL
-#define GAIM_DESKTOP_ITEM_TYPE_OTHER         PURPLE_DESKTOP_ITEM_TYPE_OTHER
-#define GAIM_DESKTOP_ITEM_TYPE_APPLICATION   PURPLE_DESKTOP_ITEM_TYPE_APPLICATION
-#define GAIM_DESKTOP_ITEM_TYPE_LINK          PURPLE_DESKTOP_ITEM_TYPE_LINK
-#define GAIM_DESKTOP_ITEM_TYPE_FSDEVICE      PURPLE_DESKTOP_ITEM_TYPE_FSDEVICE
-#define GAIM_DESKTOP_ITEM_TYPE_MIME_TYPE     PURPLE_DESKTOP_ITEM_TYPE_MIME_TYPE
-#define GAIM_DESKTOP_ITEM_TYPE_DIRECTORY     PURPLE_DESKTOP_ITEM_TYPE_DIRECTORY
-#define GAIM_DESKTOP_ITEM_TYPE_SERVICE       PURPLE_DESKTOP_ITEM_TYPE_SERVICE
-#define GAIM_DESKTOP_ITEM_TYPE_SERVICE_TYPE  PURPLE_DESKTOP_ITEM_TYPE_SERVICE_TYPE
-
-#define GaimDesktopItemType  PurpleDesktopItemType
-
-#define GaimDesktopItem  PurpleDesktopItem
-
-#define GAIM_TYPE_DESKTOP_ITEM         PURPLE_TYPE_DESKTOP_ITEM
-#define gaim_desktop_item_get_type     purple_desktop_item_get_type
-
-/* standard */
-/* ugh, i'm just copying these as strings, rather than pidginifying them */
-#define GAIM_DESKTOP_ITEM_ENCODING	"Encoding" /* string */
-#define GAIM_DESKTOP_ITEM_VERSION	"Version"  /* numeric */
-#define GAIM_DESKTOP_ITEM_NAME		"Name" /* localestring */
-#define GAIM_DESKTOP_ITEM_GENERIC_NAME	"GenericName" /* localestring */
-#define GAIM_DESKTOP_ITEM_TYPE		"Type" /* string */
-#define GAIM_DESKTOP_ITEM_FILE_PATTERN "FilePattern" /* regexp(s) */
-#define GAIM_DESKTOP_ITEM_TRY_EXEC	"TryExec" /* string */
-#define GAIM_DESKTOP_ITEM_NO_DISPLAY	"NoDisplay" /* boolean */
-#define GAIM_DESKTOP_ITEM_COMMENT	"Comment" /* localestring */
-#define GAIM_DESKTOP_ITEM_EXEC		"Exec" /* string */
-#define GAIM_DESKTOP_ITEM_ACTIONS	"Actions" /* strings */
-#define GAIM_DESKTOP_ITEM_ICON		"Icon" /* string */
-#define GAIM_DESKTOP_ITEM_MINI_ICON	"MiniIcon" /* string */
-#define GAIM_DESKTOP_ITEM_HIDDEN	"Hidden" /* boolean */
-#define GAIM_DESKTOP_ITEM_PATH		"Path" /* string */
-#define GAIM_DESKTOP_ITEM_TERMINAL	"Terminal" /* boolean */
-#define GAIM_DESKTOP_ITEM_TERMINAL_OPTIONS "TerminalOptions" /* string */
-#define GAIM_DESKTOP_ITEM_SWALLOW_TITLE "SwallowTitle" /* string */
-#define GAIM_DESKTOP_ITEM_SWALLOW_EXEC	"SwallowExec" /* string */
-#define GAIM_DESKTOP_ITEM_MIME_TYPE	"MimeType" /* regexp(s) */
-#define GAIM_DESKTOP_ITEM_PATTERNS	"Patterns" /* regexp(s) */
-#define GAIM_DESKTOP_ITEM_DEFAULT_APP	"DefaultApp" /* string */
-#define GAIM_DESKTOP_ITEM_DEV		"Dev" /* string */
-#define GAIM_DESKTOP_ITEM_FS_TYPE	"FSType" /* string */
-#define GAIM_DESKTOP_ITEM_MOUNT_POINT	"MountPoint" /* string */
-#define GAIM_DESKTOP_ITEM_READ_ONLY	"ReadOnly" /* boolean */
-#define GAIM_DESKTOP_ITEM_UNMOUNT_ICON "UnmountIcon" /* string */
-#define GAIM_DESKTOP_ITEM_SORT_ORDER	"SortOrder" /* strings */
-#define GAIM_DESKTOP_ITEM_URL		"URL" /* string */
-#define GAIM_DESKTOP_ITEM_DOC_PATH	"X-GNOME-DocPath" /* string */
-
-#define gaim_desktop_item_new_from_file   purple_desktop_item_new_from_file
-#define gaim_desktop_item_get_entry_type  purple_desktop_item_get_entry_type
-#define gaim_desktop_item_get_string      purple_desktop_item_get_string
-#define gaim_desktop_item_copy            purple_desktop_item_copy
-#define gaim_desktop_item_unref           purple_desktop_item_unref
-
-/* from dnsquery.h */
-
-#define GaimDnsQueryData  PurpleDnsQueryData
-#define GaimDnsQueryConnectFunction  PurpleDnsQueryConnectFunction
-
-#define gaim_dnsquery_a        		purple_dnsquery_a
-#define gaim_dnsquery_destroy  		purple_dnsquery_destroy
-#define gaim_dnsquery_init     		purple_dnsquery_init
-#define gaim_dnsquery_uninit   		purple_dnsquery_uninit
-#define gaim_dnsquery_set_ui_ops	purple_dnsquery_set_ui_ops
-#define gaim_dnsquery_get_host 		purple_dnsquery_get_host
-#define gaim_dnsquery_get_port 		purple_dnsquery_get_port
-
-/* from dnssrv.h */
-
-#define GaimSrvResponse   PurpleSrvResponse
-#define GaimSrvQueryData  PurpleSrvTxtQueryData
-#define GaimSrvCallback   PurpleSrvCallback
-
-#define gaim_srv_resolve  purple_srv_resolve
-#define gaim_srv_cancel   purple_srv_cancel
-
-/* from eventloop.h */
-
-#define GAIM_INPUT_READ   PURPLE_INPUT_READ
-#define GAIM_INPUT_WRITE  PURPLE_INPUT_WRITE
-
-#define GaimInputCondition  PurpleInputCondition
-#define GaimInputFunction   PurpleInputFunction
-#define GaimEventLoopUiOps  PurpleEventLoopUiOps
-
-#define gaim_timeout_add     purple_timeout_add
-#define gaim_timeout_remove  purple_timeout_remove
-#define gaim_input_add       purple_input_add
-#define gaim_input_remove    purple_input_remove
-
-#define gaim_eventloop_set_ui_ops  purple_eventloop_set_ui_ops
-#define gaim_eventloop_get_ui_ops  purple_eventloop_get_ui_ops
-
-/* from ft.h */
-
-#define GaimXfer  PurpleXfer
-
-#define GAIM_XFER_UNKNOWN  PURPLE_XFER_UNKNOWN
-#define GAIM_XFER_SEND     PURPLE_XFER_SEND
-#define GAIM_XFER_RECEIVE  PURPLE_XFER_RECEIVE
-
-#define GaimXferType  PurpleXferType
-
-#define GAIM_XFER_STATUS_UNKNOWN        PURPLE_XFER_STATUS_UNKNOWN
-#define GAIM_XFER_STATUS_NOT_STARTED    PURPLE_XFER_STATUS_NOT_STARTED
-#define GAIM_XFER_STATUS_ACCEPTED       PURPLE_XFER_STATUS_ACCEPTED
-#define GAIM_XFER_STATUS_STARTED        PURPLE_XFER_STATUS_STARTED
-#define GAIM_XFER_STATUS_DONE           PURPLE_XFER_STATUS_DONE
-#define GAIM_XFER_STATUS_CANCEL_LOCAL   PURPLE_XFER_STATUS_CANCEL_LOCAL
-#define GAIM_XFER_STATUS_CANCEL_REMOTE  PURPLE_XFER_STATUS_CANCEL_REMOTE
-
-#define GaimXferStatusType  PurpleXferStatusType
-
-#define GaimXferUiOps  PurpleXferUiOps
-
-#define gaim_xfer_new                  purple_xfer_new
-#define gaim_xfer_ref                  purple_xfer_ref
-#define gaim_xfer_unref                purple_xfer_unref
-#define gaim_xfer_request              purple_xfer_request
-#define gaim_xfer_request_accepted     purple_xfer_request_accepted
-#define gaim_xfer_request_denied       purple_xfer_request_denied
-#define gaim_xfer_get_type             purple_xfer_get_type
-#define gaim_xfer_get_account          purple_xfer_get_account
-#define gaim_xfer_get_status           purple_xfer_get_status
-#define gaim_xfer_is_canceled          purple_xfer_is_canceled
-#define gaim_xfer_is_completed         purple_xfer_is_completed
-#define gaim_xfer_get_filename         purple_xfer_get_filename
-#define gaim_xfer_get_local_filename   purple_xfer_get_local_filename
-#define gaim_xfer_get_bytes_sent       purple_xfer_get_bytes_sent
-#define gaim_xfer_get_bytes_remaining  purple_xfer_get_bytes_remaining
-#define gaim_xfer_get_size             purple_xfer_get_size
-#define gaim_xfer_get_progress         purple_xfer_get_progress
-#define gaim_xfer_get_local_port       purple_xfer_get_local_port
-#define gaim_xfer_get_remote_ip        purple_xfer_get_remote_ip
-#define gaim_xfer_get_remote_port      purple_xfer_get_remote_port
-#define gaim_xfer_set_completed        purple_xfer_set_completed
-#define gaim_xfer_set_message          purple_xfer_set_message
-#define gaim_xfer_set_filename         purple_xfer_set_filename
-#define gaim_xfer_set_local_filename   purple_xfer_set_local_filename
-#define gaim_xfer_set_size             purple_xfer_set_size
-#define gaim_xfer_set_bytes_sent       purple_xfer_set_bytes_sent
-#define gaim_xfer_get_ui_ops           purple_xfer_get_ui_ops
-#define gaim_xfer_set_read_fnc         purple_xfer_set_read_fnc
-#define gaim_xfer_set_write_fnc        purple_xfer_set_write_fnc
-#define gaim_xfer_set_ack_fnc          purple_xfer_set_ack_fnc
-#define gaim_xfer_set_request_denied_fnc  purple_xfer_set_request_denied_fnc
-#define gaim_xfer_set_init_fnc         purple_xfer_set_init_fnc
-#define gaim_xfer_set_start_fnc        purple_xfer_set_start_fnc
-#define gaim_xfer_set_end_fnc          purple_xfer_set_end_fnc
-#define gaim_xfer_set_cancel_send_fnc  purple_xfer_set_cancel_send_fnc
-#define gaim_xfer_set_cancel_recv_fnc  purple_xfer_set_cancel_recv_fnc
-
-#define gaim_xfer_read                purple_xfer_read
-#define gaim_xfer_write               purple_xfer_write
-#define gaim_xfer_start               purple_xfer_start
-#define gaim_xfer_end                 purple_xfer_end
-#define gaim_xfer_add                 purple_xfer_add
-#define gaim_xfer_cancel_local        purple_xfer_cancel_local
-#define gaim_xfer_cancel_remote       purple_xfer_cancel_remote
-#define gaim_xfer_error               purple_xfer_error
-#define gaim_xfer_update_progress     purple_xfer_update_progress
-#define gaim_xfer_conversation_write  purple_xfer_conversation_write
-
-#define gaim_xfers_get_handle  purple_xfers_get_handle
-#define gaim_xfers_init        purple_xfers_init
-#define gaim_xfers_uninit      purple_xfers_uninit
-#define gaim_xfers_set_ui_ops  purple_xfers_set_ui_ops
-#define gaim_xfers_get_ui_ops  purple_xfers_get_ui_ops
-
-/* from gaim-client.h */
-
-#define gaim_init  purple_init
-
-/* from idle.h */
-
-#define GaimIdleUiOps  PurpleIdleUiOps
-
-#define gaim_idle_touch       purple_idle_touch
-#define gaim_idle_set         purple_idle_set
-#define gaim_idle_set_ui_ops  purple_idle_set_ui_ops
-#define gaim_idle_get_ui_ops  purple_idle_get_ui_ops
-#define gaim_idle_init        purple_idle_init
-#define gaim_idle_uninit      purple_idle_uninit
-
-/* from imgstore.h */
-
-#define GaimStoredImage  PurpleStoredImage
-
-#define gaim_imgstore_add(data, size, filename) \
-        purple_imgstore_add_with_id(g_memdup(data, size), size, filename)
-#define gaim_imgstore_get           purple_imgstore_find_by_id
-#define gaim_imgstore_get_data      purple_imgstore_get_data
-#define gaim_imgstore_get_size      purple_imgstore_get_size
-#define gaim_imgstore_get_filename  purple_imgstore_get_filename
-#define gaim_imgstore_ref           purple_imgstore_ref_by_id
-#define gaim_imgstore_unref         purple_imgstore_unref_by_id
-
-
-/* from log.h */
-
-#define GaimLog                  PurpleLog
-#define GaimLogLogger            PurpleLogLogger
-#define GaimLogCommonLoggerData  PurpleLogCommonLoggerData
-#define GaimLogSet               PurpleLogSet
-
-#define GAIM_LOG_IM      PURPLE_LOG_IM
-#define GAIM_LOG_CHAT    PURPLE_LOG_CHAT
-#define GAIM_LOG_SYSTEM  PURPLE_LOG_SYSTEM
-
-#define GaimLogType  PurpleLogType
-
-#define GAIM_LOG_READ_NO_NEWLINE  PURPLE_LOG_READ_NO_NEWLINE
-
-#define GaimLogReadFlags  PurpleLogReadFlags
-
-#define GaimLogSetCallback  PurpleLogSetCallback
-
-#define gaim_log_new    purple_log_new
-#define gaim_log_free   purple_log_free
-#define gaim_log_write  purple_log_write
-#define gaim_log_read   purple_log_read
-
-#define gaim_log_get_logs         purple_log_get_logs
-#define gaim_log_get_log_sets     purple_log_get_log_sets
-#define gaim_log_get_system_logs  purple_log_get_system_logs
-#define gaim_log_get_size         purple_log_get_size
-#define gaim_log_get_total_size   purple_log_get_total_size
-#define gaim_log_get_log_dir      purple_log_get_log_dir
-#define gaim_log_compare          purple_log_compare
-#define gaim_log_set_compare      purple_log_set_compare
-#define gaim_log_set_free         purple_log_set_free
-
-#define gaim_log_common_writer       purple_log_common_writer
-#define gaim_log_common_lister       purple_log_common_lister
-#define gaim_log_common_total_sizer  purple_log_common_total_sizer
-#define gaim_log_common_sizer        purple_log_common_sizer
-
-#define gaim_log_logger_new     purple_log_logger_new
-#define gaim_log_logger_free    purple_log_logger_free
-#define gaim_log_logger_add     purple_log_logger_add
-#define gaim_log_logger_remove  purple_log_logger_remove
-#define gaim_log_logger_set     purple_log_logger_set
-#define gaim_log_logger_get     purple_log_logger_get
-
-#define gaim_log_logger_get_options  purple_log_logger_get_options
-
-#define gaim_log_init        purple_log_init
-#define gaim_log_get_handle  purple_log_get_handle
-#define gaim_log_uninit      purple_log_uninit
-
-/* from mime.h */
-
-#define GaimMimeDocument  PurpleMimeDocument
-#define GaimMimePart      PurpleMimePart
-
-#define gaim_mime_document_new         purple_mime_document_new
-#define gaim_mime_document_free        purple_mime_document_free
-#define gaim_mime_document_parse       purple_mime_document_parse
-#define gaim_mime_document_parsen      purple_mime_document_parsen
-#define gaim_mime_document_write       purple_mime_document_write
-#define gaim_mime_document_get_fields  purple_mime_document_get_fields
-#define gaim_mime_document_get_field   purple_mime_document_get_field
-#define gaim_mime_document_set_field   purple_mime_document_set_field
-#define gaim_mime_document_get_parts   purple_mime_document_get_parts
-
-#define gaim_mime_part_new                purple_mime_part_new
-#define gaim_mime_part_get_fields         purple_mime_part_get_fields
-#define gaim_mime_part_get_field          purple_mime_part_get_field
-#define gaim_mime_part_get_field_decoded  purple_mime_part_get_field_decoded
-#define gaim_mime_part_set_field          purple_mime_part_set_field
-#define gaim_mime_part_get_data           purple_mime_part_get_data
-#define gaim_mime_part_get_data_decoded   purple_mime_part_get_data_decoded
-#define gaim_mime_part_get_length         purple_mime_part_get_length
-#define gaim_mime_part_set_data           purple_mime_part_set_data
-
-
-/* from network.h */
-
-#define GaimNetworkListenData  PurpleNetworkListenData
-
-#define GaimNetworkListenCallback  PurpleNetworkListenCallback
-
-#define gaim_network_ip_atoi              purple_network_ip_atoi
-#define gaim_network_set_public_ip        purple_network_set_public_ip
-#define gaim_network_get_public_ip        purple_network_get_public_ip
-#define gaim_network_get_local_system_ip  purple_network_get_local_system_ip
-#define gaim_network_get_my_ip            purple_network_get_my_ip
-
-#define gaim_network_listen            purple_network_listen
-#define gaim_network_listen_range      purple_network_listen_range
-#define gaim_network_listen_cancel     purple_network_listen_cancel
-#define gaim_network_get_port_from_fd  purple_network_get_port_from_fd
-
-#define gaim_network_is_available  purple_network_is_available
-
-#define gaim_network_init    purple_network_init
-#define gaim_network_uninit  purple_network_uninit
-
-/* from notify.h */
-
-
-#define GaimNotifyUserInfoEntry  PurpleNotifyUserInfoEntry
-#define GaimNotifyUserInfo       PurpleNotifyUserInfo
-
-#define GaimNotifyCloseCallback  PurpleNotifyCloseCallback
-
-#define GAIM_NOTIFY_MESSAGE        PURPLE_NOTIFY_MESSAGE
-#define GAIM_NOTIFY_EMAIL          PURPLE_NOTIFY_EMAIL
-#define GAIM_NOTIFY_EMAILS         PURPLE_NOTIFY_EMAILS
-#define GAIM_NOTIFY_FORMATTED      PURPLE_NOTIFY_FORMATTED
-#define GAIM_NOTIFY_SEARCHRESULTS  PURPLE_NOTIFY_SEARCHRESULTS
-#define GAIM_NOTIFY_USERINFO       PURPLE_NOTIFY_USERINFO
-#define GAIM_NOTIFY_URI            PURPLE_NOTIFY_URI
-
-#define GaimNotifyType  PurpleNotifyType
-
-#define GAIM_NOTIFY_MSG_ERROR    PURPLE_NOTIFY_MSG_ERROR
-#define GAIM_NOTIFY_MSG_WARNING  PURPLE_NOTIFY_MSG_WARNING
-#define GAIM_NOTIFY_MSG_INFO     PURPLE_NOTIFY_MSG_INFO
-
-#define GaimNotifyMsgType  PurpleNotifyMsgType
-
-#define GAIM_NOTIFY_BUTTON_LABELED   PURPLE_NOTIFY_BUTTON_LABELED
-#define GAIM_NOTIFY_BUTTON_CONTINUE  PURPLE_NOTIFY_BUTTON_CONTINUE
-#define GAIM_NOTIFY_BUTTON_ADD       PURPLE_NOTIFY_BUTTON_ADD
-#define GAIM_NOTIFY_BUTTON_INFO      PURPLE_NOTIFY_BUTTON_INFO
-#define GAIM_NOTIFY_BUTTON_IM        PURPLE_NOTIFY_BUTTON_IM
-#define GAIM_NOTIFY_BUTTON_JOIN      PURPLE_NOTIFY_BUTTON_JOIN
-#define GAIM_NOTIFY_BUTTON_INVITE    PURPLE_NOTIFY_BUTTON_INVITE
-
-#define GaimNotifySearchButtonType  PurpleNotifySearchButtonType
-
-#define GaimNotifySearchResults  PurpleNotifySearchResults
-
-#define GAIM_NOTIFY_USER_INFO_ENTRY_PAIR            PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR
-#define GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK   PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK
-#define GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER  PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
-
-#define GaimNotifyUserInfoEntryType  PurpleNotifyUserInfoEntryType
-
-#define GaimNotifySearchColumn           PurpleNotifySearchColumn
-#define GaimNotifySearchResultsCallback  PurpleNotifySearchResultsCallback
-#define GaimNotifySearchButton           PurpleNotifySearchButton
-
-#define GaimNotifyUiOps  PurpleNotifyUiOps
-
-#define gaim_notify_searchresults                     purple_notify_searchresults
-#define gaim_notify_searchresults_free                purple_notify_searchresults_free
-#define gaim_notify_searchresults_new_rows            purple_notify_searchresults_new_rows
-#define gaim_notify_searchresults_button_add          purple_notify_searchresults_button_add
-#define gaim_notify_searchresults_button_add_labeled  purple_notify_searchresults_button_add_labeled
-#define gaim_notify_searchresults_new                 purple_notify_searchresults_new
-#define gaim_notify_searchresults_column_new          purple_notify_searchresults_column_new
-#define gaim_notify_searchresults_column_add          purple_notify_searchresults_column_add
-#define gaim_notify_searchresults_row_add             purple_notify_searchresults_row_add
-#define gaim_notify_searchresults_get_rows_count      purple_notify_searchresults_get_rows_count
-#define gaim_notify_searchresults_get_columns_count   purple_notify_searchresults_get_columns_count
-#define gaim_notify_searchresults_row_get             purple_notify_searchresults_row_get
-#define gaim_notify_searchresults_column_get_title    purple_notify_searchresults_column_get_title
-
-#define gaim_notify_message    purple_notify_message
-#define gaim_notify_email      purple_notify_email
-#define gaim_notify_emails     purple_notify_emails
-#define gaim_notify_formatted  purple_notify_formatted
-#define gaim_notify_userinfo   purple_notify_userinfo
-
-#define gaim_notify_user_info_new                    purple_notify_user_info_new
-#define gaim_notify_user_info_destroy                purple_notify_user_info_destroy
-#define gaim_notify_user_info_get_entries            purple_notify_user_info_get_entries
-#define gaim_notify_user_info_get_text_with_newline  purple_notify_user_info_get_text_with_newline
-#define gaim_notify_user_info_add_pair               purple_notify_user_info_add_pair
-#define gaim_notify_user_info_prepend_pair           purple_notify_user_info_prepend_pair
-#define gaim_notify_user_info_remove_entry           purple_notify_user_info_remove_entry
-#define gaim_notify_user_info_entry_new              purple_notify_user_info_entry_new
-#define gaim_notify_user_info_add_section_break      purple_notify_user_info_add_section_break
-#define gaim_notify_user_info_add_section_header     purple_notify_user_info_add_section_header
-#define gaim_notify_user_info_remove_last_item       purple_notify_user_info_remove_last_item
-#define gaim_notify_user_info_entry_get_label        purple_notify_user_info_entry_get_label
-#define gaim_notify_user_info_entry_set_label        purple_notify_user_info_entry_set_label
-#define gaim_notify_user_info_entry_get_value        purple_notify_user_info_entry_get_value
-#define gaim_notify_user_info_entry_set_value        purple_notify_user_info_entry_set_value
-#define gaim_notify_user_info_entry_get_type         purple_notify_user_info_entry_get_type
-#define gaim_notify_user_info_entry_set_type         purple_notify_user_info_entry_set_type
-
-#define gaim_notify_uri                purple_notify_uri
-#define gaim_notify_close              purple_notify_close
-#define gaim_notify_close_with_handle  purple_notify_close_with_handle
-
-#define gaim_notify_info     purple_notify_info
-#define gaim_notify_warning  purple_notify_warning
-#define gaim_notify_error    purple_notify_error
-
-#define gaim_notify_set_ui_ops  purple_notify_set_ui_ops
-#define gaim_notify_get_ui_ops  purple_notify_get_ui_ops
-
-#define gaim_notify_get_handle  purple_notify_get_handle
-
-#define gaim_notify_init    purple_notify_init
-#define gaim_notify_uninit  purple_notify_uninit
-
-/* from ntlm.h */
-
-#define gaim_ntlm_gen_type1    purple_ntlm_gen_type1
-#define gaim_ntlm_parse_type2  purple_ntlm_parse_type2
-#define gaim_ntlm_gen_type3    purple_ntlm_gen_type3
-
-/* from plugin.h */
-
-#ifdef GAIM_PLUGINS
-#ifndef PURPLE_PLUGINS
-#define PURPLE_PLUGINS
-#endif
-#endif
-
-#define GaimPlugin            PurplePlugin
-#define GaimPluginInfo        PurplePluginInfo
-#define GaimPluginUiInfo      PurplePluginUiInfo
-#define GaimPluginLoaderInfo  PurplePluginLoaderInfo
-#define GaimPluginAction      PurplePluginAction
-#define GaimPluginPriority    PurplePluginPriority
-
-#define GAIM_PLUGIN_UNKNOWN   PURPLE_PLUGIN_UNKNOWN
-#define GAIM_PLUGIN_STANDARD  PURPLE_PLUGIN_STANDARD
-#define GAIM_PLUGIN_LOADER    PURPLE_PLUGIN_LOADER
-#define GAIM_PLUGIN_PROTOCOL  PURPLE_PLUGIN_PROTOCOL
-
-#define GaimPluginType        PurplePluginType
-
-#define GAIM_PRIORITY_DEFAULT  PURPLE_PRIORITY_DEFAULT
-#define GAIM_PRIORITY_HIGHEST  PURPLE_PRIORITY_HIGHEST
-#define GAIM_PRIORITY_LOWEST   PURPLE_PRIORITY_LOWEST
-
-#define GAIM_PLUGIN_FLAG_INVISIBLE  PURPLE_PLUGIN_FLAG_INVISIBLE
-
-#define GAIM_PLUGIN_MAGIC  PURPLE_PLUGIN_MAGIC
-
-#define GAIM_PLUGIN_LOADER_INFO     PURPLE_PLUGIN_LOADER_INFO
-#define GAIM_PLUGIN_HAS_PREF_FRAME  PURPLE_PLUGIN_HAS_PREF_FRAME
-#define GAIM_PLUGIN_UI_INFO         PURPLE_PLUGIN_UI_INFO
-
-#define GAIM_PLUGIN_HAS_ACTIONS  PURPLE_PLUGIN_HAS_ACTIONS
-#define GAIM_PLUGIN_ACTIONS      PURPLE_PLUGIN_ACTIONS
-
-#define GAIM_INIT_PLUGIN  PURPLE_INIT_PLUGIN
-
-#define gaim_plugin_new              purple_plugin_new
-#define gaim_plugin_probe            purple_plugin_probe
-#define gaim_plugin_register         purple_plugin_register
-#define gaim_plugin_load             purple_plugin_load
-#define gaim_plugin_unload           purple_plugin_unload
-#define gaim_plugin_reload           purple_plugin_reload
-#define gaim_plugin_destroy          purple_plugin_destroy
-#define gaim_plugin_is_loaded        purple_plugin_is_loaded
-#define gaim_plugin_is_unloadable    purple_plugin_is_unloadable
-#define gaim_plugin_get_id           purple_plugin_get_id
-#define gaim_plugin_get_name         purple_plugin_get_name
-#define gaim_plugin_get_version      purple_plugin_get_version
-#define gaim_plugin_get_summary      purple_plugin_get_summary
-#define gaim_plugin_get_description  purple_plugin_get_description
-#define gaim_plugin_get_author       purple_plugin_get_author
-#define gaim_plugin_get_homepage     purple_plugin_get_homepage
-
-#define gaim_plugin_ipc_register        purple_plugin_ipc_register
-#define gaim_plugin_ipc_unregister      purple_plugin_ipc_unregister
-#define gaim_plugin_ipc_unregister_all  purple_plugin_ipc_unregister_all
-#define gaim_plugin_ipc_get_params      purple_plugin_ipc_get_params
-#define gaim_plugin_ipc_call            purple_plugin_ipc_call
-
-#define gaim_plugins_add_search_path  purple_plugins_add_search_path
-#define gaim_plugins_unload_all       purple_plugins_unload_all
-#define gaim_plugins_destroy_all      purple_plugins_destroy_all
-#define gaim_plugins_save_loaded      purple_plugins_save_loaded
-#define gaim_plugins_load_saved       purple_plugins_load_saved
-#define gaim_plugins_probe            purple_plugins_probe
-#define gaim_plugins_enabled          purple_plugins_enabled
-
-#define gaim_plugins_register_probe_notify_cb     purple_plugins_register_probe_notify_cb
-#define gaim_plugins_unregister_probe_notify_cb   purple_plugins_unregister_probe_notify_cb
-#define gaim_plugins_register_load_notify_cb      purple_plugins_register_load_notify_cb
-#define gaim_plugins_unregister_load_notify_cb    purple_plugins_unregister_load_notify_cb
-#define gaim_plugins_register_unload_notify_cb    purple_plugins_register_unload_notify_cb
-#define gaim_plugins_unregister_unload_notify_cb  purple_plugins_unregister_unload_notify_cb
-
-#define gaim_plugins_find_with_name      purple_plugins_find_with_name
-#define gaim_plugins_find_with_filename  purple_plugins_find_with_filename
-#define gaim_plugins_find_with_basename  purple_plugins_find_with_basename
-#define gaim_plugins_find_with_id        purple_plugins_find_with_id
-
-#define gaim_plugins_get_loaded     purple_plugins_get_loaded
-#define gaim_plugins_get_protocols  purple_plugins_get_protocols
-#define gaim_plugins_get_all        purple_plugins_get_all
-
-#define gaim_plugins_get_handle  purple_plugins_get_handle
-#define gaim_plugins_init        purple_plugins_init
-#define gaim_plugins_uninit      purple_plugins_uninit
-
-#define gaim_plugin_action_new   purple_plugin_action_new
-#define gaim_plugin_action_free  purple_plugin_action_free
-
-/* pluginpref.h */
-
-#define GaimPluginPrefFrame  PurplePluginPrefFrame
-#define GaimPluginPref       PurplePluginPref
-
-#define GAIM_STRING_FORMAT_TYPE_NONE       PURPLE_STRING_FORMAT_TYPE_NONE
-#define GAIM_STRING_FORMAT_TYPE_MULTILINE  PURPLE_STRING_FORMAT_TYPE_MULTILINE
-#define GAIM_STRING_FORMAT_TYPE_HTML       PURPLE_STRING_FORMAT_TYPE_HTML
-
-#define GaimStringFormatType  PurpleStringFormatType
-
-#define GAIM_PLUGIN_PREF_NONE           PURPLE_PLUGIN_PREF_NONE
-#define GAIM_PLUGIN_PREF_CHOICE         PURPLE_PLUGIN_PREF_CHOICE
-#define GAIM_PLUGIN_PREF_INFO           PURPLE_PLUGIN_PREF_INFO
-#define GAIM_PLUGIN_PREF_STRING_FORMAT  PURPLE_PLUGIN_PREF_STRING_FORMAT
-
-#define GaimPluginPrefType  PurplePluginPrefType
-
-#define gaim_plugin_pref_frame_new        purple_plugin_pref_frame_new
-#define gaim_plugin_pref_frame_destroy    purple_plugin_pref_frame_destroy
-#define gaim_plugin_pref_frame_add        purple_plugin_pref_frame_add
-#define gaim_plugin_pref_frame_get_prefs  purple_plugin_pref_frame_get_prefs
-
-#define gaim_plugin_pref_new                      purple_plugin_pref_new
-#define gaim_plugin_pref_new_with_name            purple_plugin_pref_new_with_name
-#define gaim_plugin_pref_new_with_label           purple_plugin_pref_new_with_label
-#define gaim_plugin_pref_new_with_name_and_label  purple_plugin_pref_new_with_name_and_label
-#define gaim_plugin_pref_destroy                  purple_plugin_pref_destroy
-#define gaim_plugin_pref_set_name                 purple_plugin_pref_set_name
-#define gaim_plugin_pref_get_name                 purple_plugin_pref_get_name
-#define gaim_plugin_pref_set_label                purple_plugin_pref_set_label
-#define gaim_plugin_pref_get_label                purple_plugin_pref_get_label
-#define gaim_plugin_pref_set_bounds               purple_plugin_pref_set_bounds
-#define gaim_plugin_pref_get_bounds               purple_plugin_pref_get_bounds
-#define gaim_plugin_pref_set_type                 purple_plugin_pref_set_type
-#define gaim_plugin_pref_get_type                 purple_plugin_pref_get_type
-#define gaim_plugin_pref_add_choice               purple_plugin_pref_add_choice
-#define gaim_plugin_pref_get_choices              purple_plugin_pref_get_choices
-#define gaim_plugin_pref_set_max_length           purple_plugin_pref_set_max_length
-#define gaim_plugin_pref_get_max_length           purple_plugin_pref_get_max_length
-#define gaim_plugin_pref_set_masked               purple_plugin_pref_set_masked
-#define gaim_plugin_pref_get_masked               purple_plugin_pref_get_masked
-#define gaim_plugin_pref_set_format_type          purple_plugin_pref_set_format_type
-#define gaim_plugin_pref_get_format_type          purple_plugin_pref_get_format_type
-
-/* from pounce.h */
-
-#define GaimPounce  PurplePounce
-
-#define GAIM_POUNCE_NONE              PURPLE_POUNCE_NONE
-#define GAIM_POUNCE_SIGNON            PURPLE_POUNCE_SIGNON
-#define GAIM_POUNCE_SIGNOFF           PURPLE_POUNCE_SIGNOFF
-#define GAIM_POUNCE_AWAY              PURPLE_POUNCE_AWAY
-#define GAIM_POUNCE_AWAY_RETURN       PURPLE_POUNCE_AWAY_RETURN
-#define GAIM_POUNCE_IDLE              PURPLE_POUNCE_IDLE
-#define GAIM_POUNCE_IDLE_RETURN       PURPLE_POUNCE_IDLE_RETURN
-#define GAIM_POUNCE_TYPING            PURPLE_POUNCE_TYPING
-#define GAIM_POUNCE_TYPED             PURPLE_POUNCE_TYPED
-#define GAIM_POUNCE_TYPING_STOPPED    PURPLE_POUNCE_TYPING_STOPPED
-#define GAIM_POUNCE_MESSAGE_RECEIVED  PURPLE_POUNCE_MESSAGE_RECEIVED
-#define GaimPounceEvent  PurplePounceEvent
-
-#define GAIM_POUNCE_OPTION_NONE  PURPLE_POUNCE_OPTION_NONE
-#define GAIM_POUNCE_OPTION_AWAY  PURPLE_POUNCE_OPTION_AWAY
-#define GaimPounceOption  PurplePounceOption
-
-#define GaimPounceCb  PurplePounceCb
-
-#define gaim_pounce_new                     purple_pounce_new
-#define gaim_pounce_destroy                 purple_pounce_destroy
-#define gaim_pounce_destroy_all_by_account  purple_pounce_destroy_all_by_account
-#define gaim_pounce_set_events              purple_pounce_set_events
-#define gaim_pounce_set_options             purple_pounce_set_options
-#define gaim_pounce_set_pouncer             purple_pounce_set_pouncer
-#define gaim_pounce_set_pouncee             purple_pounce_set_pouncee
-#define gaim_pounce_set_save                purple_pounce_set_save
-#define gaim_pounce_action_register         purple_pounce_action_register
-#define gaim_pounce_action_set_enabled      purple_pounce_action_set_enabled
-#define gaim_pounce_action_set_attribute    purple_pounce_action_set_attribute
-#define gaim_pounce_set_data                purple_pounce_set_data
-#define gaim_pounce_get_events              purple_pounce_get_events
-#define gaim_pounce_get_options             purple_pounce_get_options
-#define gaim_pounce_get_pouncer             purple_pounce_get_pouncer
-#define gaim_pounce_get_pouncee             purple_pounce_get_pouncee
-#define gaim_pounce_get_save                purple_pounce_get_save
-#define gaim_pounce_action_is_enabled       purple_pounce_action_is_enabled
-#define gaim_pounce_action_get_attribute    purple_pounce_action_get_attribute
-#define gaim_pounce_get_data                purple_pounce_get_data
-#define gaim_pounce_execute                 purple_pounce_execute
-
-#define gaim_find_pounce                 purple_find_pounce
-#define gaim_pounces_load                purple_pounces_load
-#define gaim_pounces_register_handler    purple_pounces_register_handler
-#define gaim_pounces_unregister_handler  purple_pounces_unregister_handler
-#define gaim_pounces_get_all             purple_pounces_get_all
-#define gaim_pounces_get_handle          purple_pounces_get_handle
-#define gaim_pounces_init                purple_pounces_init
-#define gaim_pounces_uninit              purple_pounces_uninit
-
-/* from prefs.h */
-
-
-#define GAIM_PREF_NONE         PURPLE_PREF_NONE
-#define GAIM_PREF_BOOLEAN      PURPLE_PREF_BOOLEAN
-#define GAIM_PREF_INT          PURPLE_PREF_INT
-#define GAIM_PREF_STRING       PURPLE_PREF_STRING
-#define GAIM_PREF_STRING_LIST  PURPLE_PREF_STRING_LIST
-#define GAIM_PREF_PATH         PURPLE_PREF_PATH
-#define GAIM_PREF_PATH_LIST    PURPLE_PREF_PATH_LIST
-#define GaimPrefType  PurplePrefType
-
-#define GaimPrefCallback  PurplePrefCallback
-
-#define gaim_prefs_get_handle             purple_prefs_get_handle
-#define gaim_prefs_init                   purple_prefs_init
-#define gaim_prefs_uninit                 purple_prefs_uninit
-#define gaim_prefs_add_none               purple_prefs_add_none
-#define gaim_prefs_add_bool               purple_prefs_add_bool
-#define gaim_prefs_add_int                purple_prefs_add_int
-#define gaim_prefs_add_string             purple_prefs_add_string
-#define gaim_prefs_add_string_list        purple_prefs_add_string_list
-#define gaim_prefs_add_path               purple_prefs_add_path
-#define gaim_prefs_add_path_list          purple_prefs_add_path_list
-#define gaim_prefs_remove                 purple_prefs_remove
-#define gaim_prefs_rename                 purple_prefs_rename
-#define gaim_prefs_rename_boolean_toggle  purple_prefs_rename_boolean_toggle
-#define gaim_prefs_destroy                purple_prefs_destroy
-#define gaim_prefs_set_generic            purple_prefs_set_generic
-#define gaim_prefs_set_bool               purple_prefs_set_bool
-#define gaim_prefs_set_int                purple_prefs_set_int
-#define gaim_prefs_set_string             purple_prefs_set_string
-#define gaim_prefs_set_string_list        purple_prefs_set_string_list
-#define gaim_prefs_set_path               purple_prefs_set_path
-#define gaim_prefs_set_path_list          purple_prefs_set_path_list
-#define gaim_prefs_exists                 purple_prefs_exists
-#define gaim_prefs_get_type               purple_prefs_get_type
-#define gaim_prefs_get_bool               purple_prefs_get_bool
-#define gaim_prefs_get_int                purple_prefs_get_int
-#define gaim_prefs_get_string             purple_prefs_get_string
-#define gaim_prefs_get_string_list        purple_prefs_get_string_list
-#define gaim_prefs_get_path               purple_prefs_get_path
-#define gaim_prefs_get_path_list          purple_prefs_get_path_list
-#define gaim_prefs_connect_callback       purple_prefs_connect_callback
-#define gaim_prefs_disconnect_callback    purple_prefs_disconnect_callback
-#define gaim_prefs_disconnect_by_handle   purple_prefs_disconnect_by_handle
-#define gaim_prefs_trigger_callback       purple_prefs_trigger_callback
-#define gaim_prefs_load                   purple_prefs_load
-#define gaim_prefs_update_old             purple_prefs_update_old
-
-/* from privacy.h */
-
-#define GAIM_PRIVACY_ALLOW_ALL        PURPLE_PRIVACY_ALLOW_ALL
-#define GAIM_PRIVACY_DENY_ALL         PURPLE_PRIVACY_DENY_ALL
-#define GAIM_PRIVACY_ALLOW_USERS      PURPLE_PRIVACY_ALLOW_USERS
-#define GAIM_PRIVACY_DENY_USERS       PURPLE_PRIVACY_DENY_USERS
-#define GAIM_PRIVACY_ALLOW_BUDDYLIST  PURPLE_PRIVACY_ALLOW_BUDDYLIST
-#define GaimPrivacyType  PurplePrivacyType
-
-#define GaimPrivacyUiOps  PurplePrivacyUiOps
-
-#define gaim_privacy_permit_add     purple_privacy_permit_add
-#define gaim_privacy_permit_remove  purple_privacy_permit_remove
-#define gaim_privacy_deny_add       purple_privacy_deny_add
-#define gaim_privacy_deny_remove    purple_privacy_deny_remove
-#define gaim_privacy_allow          purple_privacy_allow
-#define gaim_privacy_deny           purple_privacy_deny
-#define gaim_privacy_check          purple_privacy_check
-#define gaim_privacy_set_ui_ops     purple_privacy_set_ui_ops
-#define gaim_privacy_get_ui_ops     purple_privacy_get_ui_ops
-#define gaim_privacy_init           purple_privacy_init
-
-/* from proxy.h */
-
-#define GAIM_PROXY_USE_GLOBAL  PURPLE_PROXY_USE_GLOBAL
-#define GAIM_PROXY_NONE        PURPLE_PROXY_NONE
-#define GAIM_PROXY_HTTP        PURPLE_PROXY_HTTP
-#define GAIM_PROXY_SOCKS4      PURPLE_PROXY_SOCKS4
-#define GAIM_PROXY_SOCKS5      PURPLE_PROXY_SOCKS5
-#define GAIM_PROXY_USE_ENVVAR  PURPLE_PROXY_USE_ENVVAR
-#define GaimProxyType  PurpleProxyType
-
-#define GaimProxyInfo  PurpleProxyInfo
-
-#define GaimProxyConnectData      PurpleProxyConnectData
-#define GaimProxyConnectFunction  PurpleProxyConnectFunction
-
-#define gaim_proxy_info_new           purple_proxy_info_new
-#define gaim_proxy_info_destroy       purple_proxy_info_destroy
-#define gaim_proxy_info_set_type      purple_proxy_info_set_type
-#define gaim_proxy_info_set_host      purple_proxy_info_set_host
-#define gaim_proxy_info_set_port      purple_proxy_info_set_port
-#define gaim_proxy_info_set_username  purple_proxy_info_set_username
-#define gaim_proxy_info_set_password  purple_proxy_info_set_password
-#define gaim_proxy_info_get_type      purple_proxy_info_get_type
-#define gaim_proxy_info_get_host      purple_proxy_info_get_host
-#define gaim_proxy_info_get_port      purple_proxy_info_get_port
-#define gaim_proxy_info_get_username  purple_proxy_info_get_username
-#define gaim_proxy_info_get_password  purple_proxy_info_get_password
-
-#define gaim_global_proxy_get_info    purple_global_proxy_get_info
-#define gaim_proxy_get_handle         purple_proxy_get_handle
-#define gaim_proxy_init               purple_proxy_init
-#define gaim_proxy_uninit             purple_proxy_uninit
-#define gaim_proxy_get_setup          purple_proxy_get_setup
-
-#define gaim_proxy_connect                     purple_proxy_connect
-#define gaim_proxy_connect_socks5              purple_proxy_connect_socks5
-#define gaim_proxy_connect_cancel              purple_proxy_connect_cancel
-#define gaim_proxy_connect_cancel_with_handle  purple_proxy_connect_cancel_with_handle
-
-/* from prpl.h */
-
-#define GaimPluginProtocolInfo  PurplePluginProtocolInfo
-
-#define GAIM_ICON_SCALE_DISPLAY  PURPLE_ICON_SCALE_DISPLAY
-#define GAIM_ICON_SCALE_SEND     PURPLE_ICON_SCALE_SEND
-#define GaimIconScaleRules  PurpleIconScaleRules
-
-#define GaimBuddyIconSpec  PurpleBuddyIconSpec
-
-#define GaimProtocolOptions  PurpleProtocolOptions
-
-#define GAIM_IS_PROTOCOL_PLUGIN  PURPLE_IS_PROTOCOL_PLUGIN
-
-#define GAIM_PLUGIN_PROTOCOL_INFO  PURPLE_PLUGIN_PROTOCOL_INFO
-
-#define gaim_prpl_got_account_idle        purple_prpl_got_account_idle
-#define gaim_prpl_got_account_login_time  purple_prpl_got_account_login_time
-#define gaim_prpl_got_account_status      purple_prpl_got_account_status
-#define gaim_prpl_got_user_idle           purple_prpl_got_user_idle
-#define gaim_prpl_got_user_login_time     purple_prpl_got_user_login_time
-#define gaim_prpl_got_user_status         purple_prpl_got_user_status
-#define gaim_prpl_change_account_status   purple_prpl_change_account_status
-#define gaim_prpl_get_statuses            purple_prpl_get_statuses
-
-#define gaim_find_prpl  purple_find_prpl
-
-/* from request.h */
-
-#define GAIM_DEFAULT_ACTION_NONE  PURPLE_DEFAULT_ACTION_NONE
-
-#define GAIM_REQUEST_INPUT   PURPLE_REQUEST_INPUT
-#define GAIM_REQUEST_CHOICE  PURPLE_REQUEST_CHOICE
-#define GAIM_REQUEST_ACTION  PURPLE_REQUEST_ACTION
-#define GAIM_REQUEST_FIELDS  PURPLE_REQUEST_FIELDS
-#define GAIM_REQUEST_FILE    PURPLE_REQUEST_FILE
-#define GAIM_REQUEST_FOLDER  PURPLE_REQUEST_FOLDER
-#define GaimRequestType  PurpleRequestType
-
-#define GAIM_REQUEST_FIELD_NONE     PURPLE_REQUEST_FIELD_NONE
-#define GAIM_REQUEST_FIELD_STRING   PURPLE_REQUEST_FIELD_STRING
-#define GAIM_REQUEST_FIELD_INTEGER  PURPLE_REQUEST_FIELD_INTEGER
-#define GAIM_REQUEST_FIELD_BOOLEAN  PURPLE_REQUEST_FIELD_BOOLEAN
-#define GAIM_REQUEST_FIELD_CHOICE   PURPLE_REQUEST_FIELD_CHOICE
-#define GAIM_REQUEST_FIELD_LIST     PURPLE_REQUEST_FIELD_LIST
-#define GAIM_REQUEST_FIELD_LABEL    PURPLE_REQUEST_FIELD_LABEL
-#define GAIM_REQUEST_FIELD_IMAGE    PURPLE_REQUEST_FIELD_IMAGE
-#define GAIM_REQUEST_FIELD_ACCOUNT  PURPLE_REQUEST_FIELD_ACCOUNT
-#define GaimRequestFieldType  PurpleRequestFieldType
-
-#define GaimRequestFields  PurpleRequestFields
-
-#define GaimRequestFieldGroup  PurpleRequestFieldGroup
-
-#define GaimRequestField  PurpleRequestField
-
-#define GaimRequestUiOps  PurpleRequestUiOps
-
-#define GaimRequestInputCb   PurpleRequestInputCb
-#define GaimRequestActionCb  PurpleRequestActionCb
-#define GaimRequestChoiceCb  PurpleRequestChoiceCb
-#define GaimRequestFieldsCb  PurpleRequestFieldsCb
-#define GaimRequestFileCb    PurpleRequestFileCb
-
-#define gaim_request_fields_new                  purple_request_fields_new
-#define gaim_request_fields_destroy              purple_request_fields_destroy
-#define gaim_request_fields_add_group            purple_request_fields_add_group
-#define gaim_request_fields_get_groups           purple_request_fields_get_groups
-#define gaim_request_fields_exists               purple_request_fields_exists
-#define gaim_request_fields_get_required         purple_request_fields_get_required
-#define gaim_request_fields_is_field_required    purple_request_fields_is_field_required
-#define gaim_request_fields_all_required_filled  purple_request_fields_all_required_filled
-#define gaim_request_fields_get_field            purple_request_fields_get_field
-#define gaim_request_fields_get_string           purple_request_fields_get_string
-#define gaim_request_fields_get_integer          purple_request_fields_get_integer
-#define gaim_request_fields_get_bool             purple_request_fields_get_bool
-#define gaim_request_fields_get_choice           purple_request_fields_get_choice
-#define gaim_request_fields_get_account          purple_request_fields_get_account
-
-#define gaim_request_field_group_new         purple_request_field_group_new
-#define gaim_request_field_group_destroy     purple_request_field_group_destroy
-#define gaim_request_field_group_add_field   purple_request_field_group_add_field
-#define gaim_request_field_group_get_title   purple_request_field_group_get_title
-#define gaim_request_field_group_get_fields  purple_request_field_group_get_fields
-
-#define gaim_request_field_new            purple_request_field_new
-#define gaim_request_field_destroy        purple_request_field_destroy
-#define gaim_request_field_set_label      purple_request_field_set_label
-#define gaim_request_field_set_visible    purple_request_field_set_visible
-#define gaim_request_field_set_type_hint  purple_request_field_set_type_hint
-#define gaim_request_field_set_required   purple_request_field_set_required
-#define gaim_request_field_get_type       purple_request_field_get_type
-#define gaim_request_field_get_id         purple_request_field_get_id
-#define gaim_request_field_get_label      purple_request_field_get_label
-#define gaim_request_field_is_visible     purple_request_field_is_visible
-#define gaim_request_field_get_type_hint  purple_request_field_get_type_hint
-#define gaim_request_field_is_required    purple_request_field_is_required
-
-#define gaim_request_field_string_new           purple_request_field_string_new
-#define gaim_request_field_string_set_default_value \
-	purple_request_field_string_set_default_value
-#define gaim_request_field_string_set_value     purple_request_field_string_set_value
-#define gaim_request_field_string_set_masked    purple_request_field_string_set_masked
-#define gaim_request_field_string_set_editable  purple_request_field_string_set_editable
-#define gaim_request_field_string_get_default_value \
-	purple_request_field_string_get_default_value
-#define gaim_request_field_string_get_value     purple_request_field_string_get_value
-#define gaim_request_field_string_is_multiline  purple_request_field_string_is_multiline
-#define gaim_request_field_string_is_masked     purple_request_field_string_is_masked
-#define gaim_request_field_string_is_editable   purple_request_field_string_is_editable
-
-#define gaim_request_field_int_new        purple_request_field_int_new
-#define gaim_request_field_int_set_default_value \
-	purple_request_field_int_set_default_value
-#define gaim_request_field_int_set_value  purple_request_field_int_set_value
-#define gaim_request_field_int_get_default_value \
-	purple_request_field_int_get_default_value
-#define gaim_request_field_int_get_value  purple_request_field_int_get_value
-
-#define gaim_request_field_bool_new        purple_request_field_bool_new
-#define gaim_request_field_bool_set_default_value \
-	purple_request_field_book_set_default_value
-#define gaim_request_field_bool_set_value  purple_request_field_bool_set_value
-#define gaim_request_field_bool_get_default_value \
-	purple_request_field_bool_get_default_value
-#define gaim_request_field_bool_get_value  purple_request_field_bool_get_value
-
-#define gaim_request_field_choice_new         purple_request_field_choice_new
-#define gaim_request_field_choice_add         purple_request_field_choice_add
-#define gaim_request_field_choice_set_default_value \
-	purple_request_field_choice_set_default_value
-#define gaim_request_field_choice_set_value   purple_request_field_choice_set_value
-#define gaim_request_field_choice_get_default_value \
-	purple_request_field_choice_get_default_value
-#define gaim_request_field_choice_get_value   purple_request_field_choice_get_value
-#define gaim_request_field_choice_get_labels  purple_request_field_choice_get_labels
-
-#define gaim_request_field_list_new               purple_request_field_list_new
-#define gaim_request_field_list_set_multi_select  purple_request_field_list_set_multi_select
-#define gaim_request_field_list_get_multi_select  purple_request_field_list_get_multi_select
-#define gaim_request_field_list_get_data          purple_request_field_list_get_data
-#define gaim_request_field_list_add               purple_request_field_list_add
-#define gaim_request_field_list_add_selected      purple_request_field_list_add_selected
-#define gaim_request_field_list_clear_selected    purple_request_field_list_clear_selected
-#define gaim_request_field_list_set_selected      purple_request_field_list_set_selected
-#define gaim_request_field_list_is_selected       purple_request_field_list_is_selected
-#define gaim_request_field_list_get_selected      purple_request_field_list_get_selected
-#define gaim_request_field_list_get_items         purple_request_field_list_get_items
-
-#define gaim_request_field_label_new  purple_request_field_label_new
-
-#define gaim_request_field_image_new          purple_request_field_image_new
-#define gaim_request_field_image_set_scale    purple_request_field_image_set_scale
-#define gaim_request_field_image_get_buffer   purple_request_field_image_get_buffer
-#define gaim_request_field_image_get_size     purple_request_field_image_get_size
-#define gaim_request_field_image_get_scale_x  purple_request_field_image_get_scale_x
-#define gaim_request_field_image_get_scale_y  purple_request_field_image_get_scale_y
-
-#define gaim_request_field_account_new                purple_request_field_account_new
-#define gaim_request_field_account_set_default_value  purple_request_field_account_set_default_value
-#define gaim_request_field_account_set_value          purple_request_field_account_set_value
-#define gaim_request_field_account_set_show_all       purple_request_field_account_set_show_all
-#define gaim_request_field_account_set_filter         purple_request_field_account_set_filter
-#define gaim_request_field_account_get_default_value  purple_request_field_account_get_default_value
-#define gaim_request_field_account_get_value          purple_request_field_account_get_value
-#define gaim_request_field_account_get_show_all       purple_request_field_account_get_show_all
-#define gaim_request_field_account_get_filter         purple_request_field_account_get_filter
-
-#define gaim_request_input              purple_request_input
-#define gaim_request_choice             purple_request_choice
-#define gaim_request_choice_varg        purple_request_choice_varg
-#define gaim_request_action             purple_request_action
-#define gaim_request_action_varg        purple_request_action_varg
-#define gaim_request_fields(handle, title, primary, secondary, fields, ok_text, ok_cb, cancel_text, cancel_cb, user_data)             purple_request_fields(handle, title, primary, secondary, fields, ok_text, ok_cb, cancel_text, cancel_cb, NULL, NULL, NULL, user_data)
-#define gaim_request_close              purple_request_close
-#define gaim_request_close_with_handle  purple_request_close_with_handle
-
-#define gaim_request_yes_no         purple_request_yes_no
-#define gaim_request_ok_cancel      purple_request_ok_cancel
-#define gaim_request_accept_cancel  purple_request_accept_cancel
-
-#define gaim_request_file    purple_request_file
-#define gaim_request_folder  purple_request_folder
-
-#define gaim_request_set_ui_ops  purple_request_set_ui_ops
-#define gaim_request_get_ui_ops  purple_request_get_ui_ops
-
-/* from roomlist.h */
-
-#define GaimRoomlist       PurpleRoomlist
-#define GaimRoomlistRoom   PurpleRoomlistRoom
-#define GaimRoomlistField  PurpleRoomlistField
-#define GaimRoomlistUiOps  PurpleRoomlistUiOps
-
-#define GAIM_ROOMLIST_ROOMTYPE_CATEGORY  PURPLE_ROOMLIST_ROOMTYPE_CATEGORY
-#define GAIM_ROOMLIST_ROOMTYPE_ROOM      PURPLE_ROOMLIST_ROOMTYPE_ROOM
-#define GaimRoomlistRoomType  PurpleRoomlistRoomType
-
-#define GAIM_ROOMLIST_FIELD_BOOL    PURPLE_ROOMLIST_BOOL
-#define GAIM_ROOMLIST_FIELD_INT     PURPLE_ROOMLIST_INT
-#define GAIM_ROOMLIST_FIELD_STRING  PURPLE_ROOMLIST_STRING
-#define GaimRoomlistFieldType  PurpleRoomlistFieldType
-
-#define gaim_roomlist_show_with_account  purple_roomlist_show_with_account
-#define gaim_roomlist_new                purple_roomlist_new
-#define gaim_roomlist_ref                purple_roomlist_ref
-#define gaim_roomlist_unref              purple_roomlist_unref
-#define gaim_roomlist_set_fields         purple_roomlist_set_fields
-#define gaim_roomlist_set_in_progress    purple_roomlist_set_in_progress
-#define gaim_roomlist_get_in_progress    purple_roomlist_get_in_progress
-#define gaim_roomlist_room_add           purple_roomlist_room_add
-
-#define gaim_roomlist_get_list         purple_roomlist_get_list
-#define gaim_roomlist_cancel_get_list  purple_roomlist_cancel_get_list
-#define gaim_roomlist_expand_category  purple_roomlist_expand_category
-
-#define gaim_roomlist_room_new        purple_roomlist_room_new
-#define gaim_roomlist_room_add_field  purple_roomlist_room_add_field
-#define gaim_roomlist_room_join       purple_roomlist_room_join
-#define gaim_roomlist_field_new       purple_roomlist_field_new
-
-#define gaim_roomlist_set_ui_ops  purple_roomlist_set_ui_ops
-#define gaim_roomlist_get_ui_ops  purple_roomlist_get_ui_ops
-
-/* from savedstatuses.h */
-
-#define GaimSavedStatus     PurpleSavedStatus
-#define GaimSavedStatusSub  PurpleSavedStatusSub
-
-#define gaim_savedstatus_new              purple_savedstatus_new
-#define gaim_savedstatus_set_title        purple_savedstatus_set_title
-#define gaim_savedstatus_set_type         purple_savedstatus_set_type
-#define gaim_savedstatus_set_message      purple_savedstatus_set_message
-#define gaim_savedstatus_set_substatus    purple_savedstatus_set_substatus
-#define gaim_savedstatus_unset_substatus  purple_savedstatus_unset_substatus
-#define gaim_savedstatus_delete           purple_savedstatus_delete
-
-#define gaim_savedstatuses_get_all              purple_savedstatuses_get_all
-#define gaim_savedstatuses_get_popular          purple_savedstatuses_get_popular
-#define gaim_savedstatus_get_current            purple_savedstatus_get_current
-#define gaim_savedstatus_get_default            purple_savedstatus_get_default
-#define gaim_savedstatus_get_idleaway           purple_savedstatus_get_idleaway
-#define gaim_savedstatus_is_idleaway            purple_savedstatus_is_idleaway
-#define gaim_savedstatus_set_idleaway           purple_savedstatus_set_idleaway
-#define gaim_savedstatus_get_startup            purple_savedstatus_get_startup
-#define gaim_savedstatus_find                   purple_savedstatus_find
-#define gaim_savedstatus_find_by_creation_time  purple_savedstatus_find_by_creation_time
-#define gaim_savedstatus_find_transient_by_type_and_message \
-	purple_savedstatus_find_transient_by_type_and_message
-
-#define gaim_savedstatus_is_transient           purple_savedstatus_is_transient
-#define gaim_savedstatus_get_title              purple_savedstatus_get_title
-#define gaim_savedstatus_get_type               purple_savedstatus_get_type
-#define gaim_savedstatus_get_message            purple_savedstatus_get_message
-#define gaim_savedstatus_get_creation_time      purple_savedstatus_get_creation_time
-#define gaim_savedstatus_has_substatuses        purple_savedstatus_has_substatuses
-#define gaim_savedstatus_get_substatus          purple_savedstatus_get_substatus
-#define gaim_savedstatus_substatus_get_type     purple_savedstatus_substatus_get_type
-#define gaim_savedstatus_substatus_get_message  purple_savedstatus_substatus_get_message
-#define gaim_savedstatus_activate               purple_savedstatus_activate
-#define gaim_savedstatus_activate_for_account   purple_savedstatus_activate_for_account
-
-#define gaim_savedstatuses_get_handle  purple_savedstatuses_get_handle
-#define gaim_savedstatuses_init        purple_savedstatuses_init
-#define gaim_savedstatuses_uninit      purple_savedstatuses_uninit
-
-/* from signals.h */
-
-#define GAIM_CALLBACK  PURPLE_CALLBACK
-
-#define GaimCallback           PurpleCallback
-#define GaimSignalMarshalFunc  PurpleSignalMarshalFunc
-
-#define GAIM_SIGNAL_PRIORITY_DEFAULT  PURPLE_SIGNAL_PRIORITY_DEFAULT
-#define GAIM_SIGNAL_PRIORITY_HIGHEST  PURPLE_SIGNAL_PRIORITY_HIGHEST
-#define GAIM_SIGNAL_PRIORITY_LOWEST   PURPLE_SIGNAL_PRIORITY_LOWEST
-
-#define gaim_signal_register    purple_signal_register
-#define gaim_signal_unregister  purple_signal_unregister
-
-#define gaim_signals_unregister_by_instance  purple_signals_unregister_by_instance
-
-#define gaim_signal_get_values              purple_signal_get_values
-#define gaim_signal_connect_priority        purple_signal_connect_priority
-#define gaim_signal_connect                 purple_signal_connect
-#define gaim_signal_connect_priority_vargs  purple_signal_connect_priority_vargs
-#define gaim_signal_connect_vargs           purple_signal_connect_vargs
-#define gaim_signal_disconnect              purple_signal_disconnect
-
-#define gaim_signals_disconnect_by_handle  purple_signals_disconnect_by_handle
-
-#define gaim_signal_emit                 purple_signal_emit
-#define gaim_signal_emit_vargs           purple_signal_emit_vargs
-#define gaim_signal_emit_return_1        purple_signal_emit_vargs
-#define gaim_signal_emit_vargs_return_1  purple_signal_emit_vargs_return_1
-
-#define gaim_signals_init    purple_signals_init
-#define gaim_signals_uninit  purple_signals_uninit
-
-#define gaim_marshal_VOID \
-	purple_marshal_VOID
-#define gaim_marshal_VOID__INT \
-	purple_marshal_VOID__INT
-#define gaim_marshal_VOID__INT_INT \
-	purple_marshal_VOID_INT_INT
-#define gaim_marshal_VOID__POINTER \
-	purple_marshal_VOID__POINTER
-#define gaim_marshal_VOID__POINTER_UINT \
-	purple_marshal_VOID__POINTER_UINT
-#define gaim_marshal_VOID__POINTER_INT_INT \
-	purple_marshal_VOID__POINTER_INT_INT
-#define gaim_marshal_VOID__POINTER_POINTER \
-	purple_marshal_VOID__POINTER_POINTER
-#define gaim_marshal_VOID__POINTER_POINTER_UINT \
-	purple_marshal_VOID__POINTER_POINTER_UINT
-#define gaim_marshal_VOID__POINTER_POINTER_UINT_UINT \
-	purple_marshal_VOID__POINTER_POINTER_UINT_UINT
-#define gaim_marshal_VOID__POINTER_POINTER_POINTER \
-	purple_marshal_VOID__POINTER_POINTER_POINTER
-#define gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER \
-	purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER
-#define gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER \
-	purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER
-#define gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT \
-	purple_marshal_VOID__POINTER_POINTER_POINTER_UINT
-#define gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT \
-	purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT
-#define gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT \
-	purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT
-
-#define gaim_marshal_INT__INT \
-	purple_marshal_INT__INT
-#define gaim_marshal_INT__INT_INT \
-	purple_marshal_INT__INT_INT
-#define gaim_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER \
-	purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER
-
-#define gaim_marshal_BOOLEAN__POINTER \
-	purple_marshal_BOOLEAN__POINTER
-#define gaim_marshal_BOOLEAN__POINTER_POINTER \
-	purple_marshal_BOOLEAN__POINTER_POINTER
-#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER \
-	purple_marshal_BOOLEAN__POINTER_POINTER_POINTER
-#define gaim_marshal_BOOLEAN__POINTER_POINTER_UINT \
-	purple_marshal_BOOLEAN__POINTER_POINTER_UINT
-#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT \
-	purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT
-#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER \
-	purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER
-#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER \
-	purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER
-
-#define gaim_marshal_BOOLEAN__INT_POINTER \
-	purple_marshal_BOOLEAN__INT_POINTER
-
-#define gaim_marshal_POINTER__POINTER_INT \
-	purple_marshal_POINTER__POINTER_INT
-#define gaim_marshal_POINTER__POINTER_INT64 \
-	purple_marshal_POINTER__POINTER_INT64
-#define gaim_marshal_POINTER__POINTER_INT_BOOLEAN \
-	purple_marshal_POINTER__POINTER_INT_BOOLEAN
-#define gaim_marshal_POINTER__POINTER_INT64_BOOLEAN \
-	purple_marshal_POINTER__POINTER_INT64_BOOLEAN
-#define gaim_marshal_POINTER__POINTER_POINTER \
-	purple_marshal_POINTER__POINTER_POINTER
-
-/* from sound.h */
-
-#define GAIM_SOUND_BUDDY_ARRIVE    PURPLE_SOUND_BUDDY_ARRIVE
-#define GAIM_SOUND_BUDDY_LEAVE     PURPLE_SOUND_BUDDY_LEAVE
-#define GAIM_SOUND_RECEIVE         PURPLE_SOUND_RECEIVE
-#define GAIM_SOUND_FIRST_RECEIVE   PURPLE_SOUND_FIRST_RECEIVE
-#define GAIM_SOUND_SEND            PURPLE_SOUND_SEND
-#define GAIM_SOUND_CHAT_JOIN       PURPLE_SOUND_CHAT_JOIN
-#define GAIM_SOUND_CHAT_LEAVE      PURPLE_SOUND_CHAT_LEAVE
-#define GAIM_SOUND_CHAT_YOU_SAY    PURPLE_SOUND_CHAT_YOU_SAY
-#define GAIM_SOUND_CHAT_SAY        PURPLE_SOUND_CHAT_SAY
-#define GAIM_SOUND_POUNCE_DEFAULT  PURPLE_SOUND_POUNCE_DEFAULT
-#define GAIM_SOUND_CHAT_NICK       PURPLE_SOUND_CHAT_NICK
-#define GAIM_NUM_SOUNDS            PURPLE_NUM_SOUNDS
-#define GaimSoundEventID  PurpleSoundEventID
-
-#define GaimSoundUiOps  PurpleSoundUiOps
-
-#define gaim_sound_play_file   purple_sound_play_file
-#define gaim_sound_play_event  purple_sound_play_event
-#define gaim_sound_set_ui_ops  purple_sound_set_ui_ops
-#define gaim_sound_get_ui_ops  purple_sound_get_ui_ops
-#define gaim_sound_init        purple_sound_init
-#define gaim_sound_uninit      purple_sound_uninit
-
-#define gaim_sounds_get_handle  purple_sounds_get_handle
-
-/* from sslconn.h */
-
-#define GAIM_SSL_DEFAULT_PORT  PURPLE_SSL_DEFAULT_PORT
-
-#define GAIM_SSL_HANDSHAKE_FAILED  PURPLE_SSL_HANDSHAKE_FAILED
-#define GAIM_SSL_CONNECT_FAILED    PURPLE_SSL_CONNECT_FAILED
-#define GaimSslErrorType  PurpleSslErrorType
-
-#define GaimSslConnection  PurpleSslConnection
-
-#define GaimSslInputFunction  PurpleSslInputFunction
-#define GaimSslErrorFunction  PurpleSslErrorFunction
-
-#define GaimSslOps  PurpleSslOps
-
-#define gaim_ssl_is_supported  purple_ssl_is_supported
-#define gaim_ssl_connect       purple_ssl_connect
-#define gaim_ssl_connect_fd    purple_ssl_connect_fd
-#define gaim_ssl_input_add     purple_ssl_input_add
-#define gaim_ssl_close         purple_ssl_close
-#define gaim_ssl_read          purple_ssl_read
-#define gaim_ssl_write         purple_ssl_write
-
-#define gaim_ssl_set_ops  purple_ssl_set_ops
-#define gaim_ssl_get_ops  purple_ssl_get_ops
-#define gaim_ssl_init     purple_ssl_init
-#define gaim_ssl_uninit   purple_ssl_uninit
-
-/* from status.h */
-
-#define GaimStatusType  PurpleStatusType
-#define GaimStatusAttr  PurpleStatusAttr
-#define GaimPresence    PurplePresence
-#define GaimStatus      PurpleStatus
-
-#define GAIM_PRESENCE_CONTEXT_UNSET    PURPLE_PRESENCE_CONTEXT_UNSET
-#define GAIM_PRESENCE_CONTEXT_ACCOUNT  PURPLE_PRESENCE_CONTEXT_ACCOUNT
-#define GAIM_PRESENCE_CONTEXT_CONV     PURPLE_PRESENCE_CONTEXT_CONV
-#define GAIM_PRESENCE_CONTEXT_BUDDY    PURPLE_PRESENCE_CONTEXT_BUDDY
-#define GaimPresenceContext  PurplePresenceContext
-
-#define GAIM_STATUS_UNSET           PURPLE_STATUS_UNSET
-#define GAIM_STATUS_OFFLINE         PURPLE_STATUS_OFFLINE
-#define GAIM_STATUS_AVAILABLE       PURPLE_STATUS_AVAILABLE
-#define GAIM_STATUS_UNAVAILABLE     PURPLE_STATUS_UNAVAILABLE
-#define GAIM_STATUS_INVISIBLE       PURPLE_STATUS_INVISIBLE
-#define GAIM_STATUS_AWAY            PURPLE_STATUS_AWAY
-#define GAIM_STATUS_EXTENDED_AWAY   PURPLE_STATUS_EXTENDED_AWAY
-#define GAIM_STATUS_MOBILE          PURPLE_STATUS_MOBILE
-#define GAIM_STATUS_NUM_PRIMITIVES  PURPLE_STATUS_NUM_PRIMITIVES
-#define GaimStatusPrimitive  PurpleStatusPrimitive
-
-#define gaim_primitive_get_id_from_type    purple_primitive_get_id_from_type
-#define gaim_primitive_get_name_from_type  purple_primitive_get_name_from_type
-#define gaim_primitive_get_type_from_id    purple_primitive_get_type_from_id
-
-#define gaim_status_type_new_full          purple_status_type_new_full
-#define gaim_status_type_new               purple_status_type_new
-#define gaim_status_type_new_with_attrs    purple_status_type_new_with_attrs
-#define gaim_status_type_destroy           purple_status_type_destroy
-#define gaim_status_type_set_primary_attr  purple_status_type_set_primary_attr
-#define gaim_status_type_add_attr          purple_status_type_add_attr
-#define gaim_status_type_add_attrs         purple_status_type_add_attrs
-#define gaim_status_type_add_attrs_vargs   purple_status_type_add_attrs_vargs
-#define gaim_status_type_get_primitive     purple_status_type_get_primitive
-#define gaim_status_type_get_id            purple_status_type_get_id
-#define gaim_status_type_get_name          purple_status_type_get_name
-#define gaim_status_type_is_saveable       purple_status_type_is_saveable
-#define gaim_status_type_is_user_settable  purple_status_type_is_user_settable
-#define gaim_status_type_is_independent    purple_status_type_is_independent
-#define gaim_status_type_is_exclusive      purple_status_type_is_exclusive
-#define gaim_status_type_is_available      purple_status_type_is_available
-#define gaim_status_type_get_primary_attr  purple_status_type_get_primary_attr
-#define gaim_status_type_get_attr          purple_status_type_get_attr
-#define gaim_status_type_get_attrs         purple_status_type_get_attrs
-#define gaim_status_type_find_with_id      purple_status_type_find_with_id
-
-#define gaim_status_attr_new        purple_status_attr_new
-#define gaim_status_attr_destroy    purple_status_attr_destroy
-#define gaim_status_attr_get_id     purple_status_attr_get_id
-#define gaim_status_attr_get_name   purple_status_attr_get_name
-#define gaim_status_attr_get_value  purple_status_attr_get_value
-
-#define gaim_status_new                         purple_status_new
-#define gaim_status_destroy                     purple_status_destroy
-#define gaim_status_set_active                  purple_status_set_active
-#define gaim_status_set_active_with_attrs       purple_status_set_active_with_attrs
-#define gaim_status_set_active_with_attrs_list  purple_status_set_active_with_attrs_list
-#define gaim_status_set_attr_boolean            purple_status_set_attr_boolean
-#define gaim_status_set_attr_int                purple_status_set_attr_int
-#define gaim_status_set_attr_string             purple_status_set_attr_string
-#define gaim_status_get_type                    purple_status_get_type
-#define gaim_status_get_presence                purple_status_get_presence
-#define gaim_status_get_id                      purple_status_get_id
-#define gaim_status_get_name                    purple_status_get_name
-#define gaim_status_is_independent              purple_status_is_independent
-#define gaim_status_is_exclusive                purple_status_is_exclusive
-#define gaim_status_is_available                purple_status_is_available
-#define gaim_status_is_active                   purple_status_is_active
-#define gaim_status_is_online                   purple_status_is_online
-#define gaim_status_get_attr_value              purple_status_get_attr_value
-#define gaim_status_get_attr_boolean            purple_status_get_attr_boolean
-#define gaim_status_get_attr_int                purple_status_get_attr_int
-#define gaim_status_get_attr_string             purple_status_get_attr_string
-#define gaim_status_compare                     purple_status_compare
-
-#define gaim_presence_new                purple_presence_new
-#define gaim_presence_new_for_account    purple_presence_new_for_account
-#define gaim_presence_new_for_conv       purple_presence_new_for_conv
-#define gaim_presence_new_for_buddy      purple_presence_new_for_buddy
-#define gaim_presence_destroy            purple_presence_destroy
-#define gaim_presence_add_status         purple_presence_add_status
-#define gaim_presence_add_list           purple_presence_add_list
-#define gaim_presence_set_status_active  purple_presence_set_status_active
-#define gaim_presence_switch_status      purple_presence_switch_status
-#define gaim_presence_set_idle           purple_presence_set_idle
-#define gaim_presence_set_login_time     purple_presence_set_login_time
-#define gaim_presence_get_context        purple_presence_get_context
-#define gaim_presence_get_account        purple_presence_get_account
-#define gaim_presence_get_conversation   purple_presence_get_conversation
-#define gaim_presence_get_chat_user      purple_presence_get_chat_user
-#define gaim_presence_get_statuses       purple_presence_get_statuses
-#define gaim_presence_get_status         purple_presence_get_status
-#define gaim_presence_get_active_status  purple_presence_get_active_status
-#define gaim_presence_is_available       purple_presence_is_available
-#define gaim_presence_is_online          purple_presence_is_online
-#define gaim_presence_is_status_active   purple_presence_is_status_active
-#define gaim_presence_is_status_primitive_active \
-	purple_presence_is_status_primitive_active
-#define gaim_presence_is_idle            purple_presence_is_idle
-#define gaim_presence_get_idle_time      purple_presence_get_idle_time
-#define gaim_presence_get_login_time     purple_presence_get_login_time
-#define gaim_presence_compare            purple_presence_compare
-
-#define gaim_status_get_handle  purple_status_get_handle
-#define gaim_status_init        purple_status_init
-#define gaim_status_uninit      purple_status_uninit
-
-/* from stringref.h */
-
-#define GaimStringref  PurpleStringref
-
-#define gaim_stringref_new        purple_stringref_new
-#define gaim_stringref_new_noref  purple_stringref_new_noref
-#define gaim_stringref_printf     purple_stringref_printf
-#define gaim_stringref_ref        purple_stringref_ref
-#define gaim_stringref_unref      purple_stringref_unref
-#define gaim_stringref_value      purple_stringref_value
-#define gaim_stringref_cmp        purple_stringref_cmp
-#define gaim_stringref_len        purple_stringref_len
-
-/* from stun.h */
-
-#define GaimStunNatDiscovery  PurpleStunNatDiscovery
-
-#define GAIM_STUN_STATUS_UNDISCOVERED  PURPLE_STUN_STATUS_UNDISCOVERED
-#define GAIM_STUN_STATUS_UNKNOWN       PURPLE_STUN_STATUS_UNKNOWN
-#define GAIM_STUN_STATUS_DISCOVERING   PURPLE_STUN_STATUS_DISCOVERING
-#define GAIM_STUN_STATUS_DISCOVERED    PURPLE_STUN_STATUS_DISCOVERED
-#define GaimStunStatus  PurpleStunStatus
-
-#define GAIM_STUN_NAT_TYPE_PUBLIC_IP             PURPLE_STUN_NAT_TYPE_PUBLIC_IP
-#define GAIM_STUN_NAT_TYPE_UNKNOWN_NAT           PURPLE_STUN_NAT_TYPE_UNKNOWN_NAT
-#define GAIM_STUN_NAT_TYPE_FULL_CONE             PURPLE_STUN_NAT_TYPE_FULL_CONE
-#define GAIM_STUN_NAT_TYPE_RESTRICTED_CONE       PURPLE_STUN_NAT_TYPE_RESTRICTED_CONE
-#define GAIM_STUN_NAT_TYPE_PORT_RESTRICTED_CONE  PURPLE_STUN_NAT_TYPE_PORT_RESTRICTED_CONE
-#define GAIM_STUN_NAT_TYPE_SYMMETRIC             PURPLE_STUN_NAT_TYPE_SYMMETRIC
-#define GaimStunNatType  PurpleStunNatType
-
-/* why didn't this have a Gaim prefix before? */
-#define StunCallback  PurpleStunCallback
-
-#define gaim_stun_discover  purple_stun_discover
-#define gaim_stun_init      purple_stun_init
-
-/* from upnp.h */
-
-/* suggested rename: PurpleUPnpMappingHandle */
-#define UPnPMappingAddRemove  PurpleUPnPMappingAddRemove
-
-#define GaimUPnPCallback  PurpleUPnPCallback
-
-#define gaim_upnp_discover             purple_upnp_discover
-#define gaim_upnp_get_public_ip        purple_upnp_get_public_ip
-#define gaim_upnp_cancel_port_mapping  purple_upnp_cancel_port_mapping
-#define gaim_upnp_set_port_mapping     purple_upnp_set_port_mapping
-
-#define gaim_upnp_remove_port_mapping  purple_upnp_remove_port_mapping
-
-/* from util.h */
-
-#define GaimUtilFetchUrlData  PurpleUtilFetchUrlData
-#define GaimMenuAction        PurpleMenuAction
-
-#define GaimInfoFieldFormatCallback  PurpleIntoFieldFormatCallback
-
-#define GaimKeyValuePair  PurpleKeyValuePair
-
-#define gaim_menu_action_new   purple_menu_action_new
-#define gaim_menu_action_free  purple_menu_action_free
-
-#define gaim_base16_encode   purple_base16_encode
-#define gaim_base16_decode   purple_base16_decode
-#define gaim_base64_encode   purple_base64_encode
-#define gaim_base64_decode   purple_base64_decode
-#define gaim_quotedp_decode  purple_quotedp_decode
-
-#define gaim_mime_decode_field  purple_mime_deco_field
-
-#define gaim_utf8_strftime      purple_utf8_strftime
-#define gaim_date_format_short  purple_date_format_short
-#define gaim_date_format_long   purple_date_format_long
-#define gaim_date_format_full   purple_date_format_full
-#define gaim_time_format        purple_time_format
-#define gaim_time_build         purple_time_build
-
-#define GAIM_NO_TZ_OFF  PURPLE_NO_TZ_OFF
-
-#define gaim_str_to_time  purple_str_to_time
-
-#define gaim_markup_find_tag            purple_markup_find_tag
-#define gaim_markup_extract_info_field  purple_markup_extract_info_field
-#define gaim_markup_html_to_xhtml       purple_markup_html_to_xhtml
-#define gaim_markup_strip_html          purple_markup_strip_html
-#define gaim_markup_linkify             purple_markup_linkify
-#define gaim_markup_slice               purple_markup_slice
-#define gaim_markup_get_tag_name        purple_markup_get_tag_name
-#define gaim_unescape_html              purple_unescape_html
-
-#define gaim_home_dir  purple_home_dir
-#define gaim_user_dir  purple_user_dir
-
-#define gaim_util_set_user_dir  purple_util_set_user_dir
-
-#define gaim_build_dir  purple_build_dir
-
-#define gaim_util_write_data_to_file  purple_util_write_data_to_file
-
-#define gaim_util_read_xml_from_file  purple_util_read_xml_from_file
-
-#define gaim_mkstemp  purple_mkstemp
-
-#define gaim_program_is_valid  purple_program_is_valid
-
-#define gaim_running_gnome  purple_running_gnome
-#define gaim_running_kde    purple_running_kde
-#define gaim_running_osx    purple_running_osx
-
-#define gaim_fd_get_ip  purple_fd_get_ip
-
-#define gaim_normalize         purple_normalize
-#define gaim_normalize_nocase  purple_normalize_nocase
-
-#define gaim_strdup_withhtml  purple_strdup_withhtml
-
-#define gaim_str_has_prefix  purple_str_has_prefix
-#define gaim_str_has_suffix  purple_str_has_suffix
-#define gaim_str_add_cr      purple_str_add_cr
-#define gaim_str_strip_char  purple_str_strip_char
-
-#define gaim_util_chrreplace  purple_util_chrreplace
-
-#define gaim_strreplace  purple_strreplace
-
-#define gaim_utf8_ncr_encode  purple_utf8_ncr_encode
-#define gaim_utf8_ncr_decode  purple_utf8_ncr_decode
-
-#define gaim_strcasereplace  purple_strcasereplace
-#define gaim_strcasestr      purple_strcasestr
-
-#define gaim_str_size_to_units      purple_str_size_to_units
-#define gaim_str_seconds_to_string  purple_str_seconds_to_string
-#define gaim_str_binary_to_ascii    purple_str_binary_to_ascii
-
-
-#define gaim_got_protocol_handler_uri  purple_got_protocol_handler_uri
-
-#define gaim_url_parse  purple_url_parse
-
-#define GaimUtilFetchUrlCallback  PurpleUtilFetchUrlCallback
-#define gaim_util_fetch_url          purple_util_fetch_url
-#define gaim_util_fetch_url_request  purple_util_fetch_url_request
-#define gaim_util_fetch_url_cancel   purple_util_fetch_url_cancel
-
-#define gaim_url_decode  purple_url_decode
-#define gaim_url_encode  purple_url_encode
-
-#define gaim_email_is_valid  purple_email_is_valid
-
-#define gaim_uri_list_extract_uris       purple_uri_list_extract_uris
-#define gaim_uri_list_extract_filenames  purple_uri_list_extract_filenames
-
-#define gaim_utf8_try_convert  purple_utf8_try_convert
-#define gaim_utf8_salvage      purple_utf8_salvage
-#define gaim_utf8_strcasecmp   purple_utf8_strcasecmp
-#define gaim_utf8_has_word     purple_utf8_has_word
-
-#define gaim_print_utf8_to_console  purple_print_utf8_to_console
-
-#define gaim_message_meify  purple_message_meify
-
-#define gaim_text_strip_mnemonic  purple_text_strip_mnemonic
-
-#define gaim_unescape_filename  purple_unescape_filename
-#define gaim_escape_filename    purple_escape_filename
-
-/* from value.h */
-
-#define GAIM_TYPE_UNKNOWN  PURPLE_TYPE_UNKNOWN
-#define GAIM_TYPE_SUBTYPE  PURPLE_TYPE_SUBTYPE
-#define GAIM_TYPE_CHAR     PURPLE_TYPE_CHAR
-#define GAIM_TYPE_UCHAR    PURPLE_TYPE_UCHAR
-#define GAIM_TYPE_BOOLEAN  PURPLE_TYPE_BOOLEAN
-#define GAIM_TYPE_SHORT    PURPLE_TYPE_SHORT
-#define GAIM_TYPE_USHORT   PURPLE_TYPE_USHORT
-#define GAIM_TYPE_INT      PURPLE_TYPE_INT
-#define GAIM_TYPE_UINT     PURPLE_TYPE_UINT
-#define GAIM_TYPE_LONG     PURPLE_TYPE_LONG
-#define GAIM_TYPE_ULONG    PURPLE_TYPE_ULONG
-#define GAIM_TYPE_INT64    PURPLE_TYPE_INT64
-#define GAIM_TYPE_UINT64   PURPLE_TYPE_UINT64
-#define GAIM_TYPE_STRING   PURPLE_TYPE_STRING
-#define GAIM_TYPE_OBJECT   PURPLE_TYPE_OBJECT
-#define GAIM_TYPE_POINTER  PURPLE_TYPE_POINTER
-#define GAIM_TYPE_ENUM     PURPLE_TYPE_ENUM
-#define GAIM_TYPE_BOXED    PURPLE_TYPE_BOXED
-#define GaimType  PurpleType
-
-
-#define GAIM_SUBTYPE_UNKNOWN       PURPLE_SUBTYPE_UNKNOWN
-#define GAIM_SUBTYPE_ACCOUNT       PURPLE_SUBTYPE_ACCOUNT
-#define GAIM_SUBTYPE_BLIST         PURPLE_SUBTYPE_BLIST
-#define GAIM_SUBTYPE_BLIST_BUDDY   PURPLE_SUBTYPE_BLIST_BUDDY
-#define GAIM_SUBTYPE_BLIST_GROUP   PURPLE_SUBTYPE_BLIST_GROUP
-#define GAIM_SUBTYPE_BLIST_CHAT    PURPLE_SUBTYPE_BLIST_CHAT
-#define GAIM_SUBTYPE_BUDDY_ICON    PURPLE_SUBTYPE_BUDDY_ICON
-#define GAIM_SUBTYPE_CONNECTION    PURPLE_SUBTYPE_CONNECTION
-#define GAIM_SUBTYPE_CONVERSATION  PURPLE_SUBTYPE_CONVERSATION
-#define GAIM_SUBTYPE_PLUGIN        PURPLE_SUBTYPE_PLUGIN
-#define GAIM_SUBTYPE_BLIST_NODE    PURPLE_SUBTYPE_BLIST_NODE
-#define GAIM_SUBTYPE_CIPHER        PURPLE_SUBTYPE_CIPHER
-#define GAIM_SUBTYPE_STATUS        PURPLE_SUBTYPE_STATUS
-#define GAIM_SUBTYPE_LOG           PURPLE_SUBTYPE_LOG
-#define GAIM_SUBTYPE_XFER          PURPLE_SUBTYPE_XFER
-#define GAIM_SUBTYPE_SAVEDSTATUS   PURPLE_SUBTYPE_SAVEDSTATUS
-#define GAIM_SUBTYPE_XMLNODE       PURPLE_SUBTYPE_XMLNODE
-#define GAIM_SUBTYPE_USERINFO      PURPLE_SUBTYPE_USERINFO
-#define GaimSubType  PurpleSubType
-
-#define GaimValue  PurpleValue
-
-#define gaim_value_new                purple_value_new
-#define gaim_value_new_outgoing       purple_value_new_outgoing
-#define gaim_value_destroy            purple_value_destroy
-#define gaim_value_dup                purple_value_dup
-#define gaim_value_purple_buddy_icon_get_extensionget_type           purple_value_get_type
-#define gaim_value_get_subtype        purple_value_get_subtype
-#define gaim_value_get_specific_type  purple_value_get_specific_type
-#define gaim_value_is_outgoing        purple_value_is_outgoing
-#define gaim_value_set_char           purple_value_set_char
-#define gaim_value_set_uchar          purple_value_set_uchar
-#define gaim_value_set_boolean        purple_value_set_boolean
-#define gaim_value_set_short          purple_value_set_short
-#define gaim_value_set_ushort         purple_value_set_ushort
-#define gaim_value_set_int            purple_value_set_int
-#define gaim_value_set_uint           purple_value_set_uint
-#define gaim_value_set_long           purple_value_set_long
-#define gaim_value_set_ulong          purple_value_set_ulong
-#define gaim_value_set_int64          purple_value_set_int64
-#define gaim_value_set_uint64         purple_value_set_uint64
-#define gaim_value_set_string         purple_value_set_string
-#define gaim_value_set_object         purple_value_set_object
-#define gaim_value_set_pointer        purple_value_set_pointer
-#define gaim_value_set_enum           purple_value_set_enum
-#define gaim_value_set_boxed          purple_value_set_boxed
-#define gaim_value_get_char           purple_value_get_char
-#define gaim_value_get_uchar          purple_value_get_uchar
-#define gaim_value_get_boolean        purple_value_get_boolean
-#define gaim_value_get_short          purple_value_get_short
-#define gaim_value_get_ushort         purple_value_get_ushort
-#define gaim_value_get_int            purple_value_get_int
-#define gaim_value_get_uint           purple_value_get_uint
-#define gaim_value_get_long           purple_value_get_long
-#define gaim_value_get_ulong          purple_value_get_ulong
-#define gaim_value_get_int64          purple_value_get_int64
-#define gaim_value_get_uint64         purple_value_get_uint64
-#define gaim_value_get_string         purple_value_get_string
-#define gaim_value_get_object         purple_value_get_object
-#define gaim_value_get_pointer        purple_value_get_pointer
-#define gaim_value_get_enum           purple_value_get_enum
-#define gaim_value_get_boxed          purple_value_get_boxed
-
-/* from version.h */
-
-#define GAIM_MAJOR_VERSION  PURPLE_MAJOR_VERSION
-#define GAIM_MINOR_VERSION  PURPLE_MINOR_VERSION
-#define GAIM_MICRO_VERSION  PURPLE_MICRO_VERSION
-
-#define GAIM_VERSION_CHECK  PURPLE_VERSION_CHECK
-
-/* from whiteboard.h */
-
-#define GaimWhiteboardPrplOps  PurpleWhiteboardPrplOps
-#define GaimWhiteboard         PurpleWhiteboard
-#define GaimWhiteboardUiOps    PurpleWhiteboardUiOps
-
-#define gaim_whiteboard_set_ui_ops    purple_whiteboard_set_ui_ops
-#define gaim_whiteboard_set_prpl_ops  purple_whiteboard_set_prpl_ops
-
-#define gaim_whiteboard_create             purple_whiteboard_create
-#define gaim_whiteboard_destroy            purple_whiteboard_destroy
-#define gaim_whiteboard_start              purple_whiteboard_start
-#define gaim_whiteboard_get_session        purple_whiteboard_get_session
-#define gaim_whiteboard_draw_list_destroy  purple_whiteboard_draw_list_destroy
-#define gaim_whiteboard_get_dimensions     purple_whiteboard_get_dimensions
-#define gaim_whiteboard_set_dimensions     purple_whiteboard_set_dimensions
-#define gaim_whiteboard_draw_point         purple_whiteboard_draw_point
-#define gaim_whiteboard_send_draw_list     purple_whiteboard_send_draw_list
-#define gaim_whiteboard_draw_line          purple_whiteboard_draw_line
-#define gaim_whiteboard_clear              purple_whiteboard_clear
-#define gaim_whiteboard_send_clear         purple_whiteboard_send_clear
-#define gaim_whiteboard_send_brush         purple_whiteboard_send_brush
-#define gaim_whiteboard_get_brush          purple_whiteboard_get_brush
-#define gaim_whiteboard_set_brush          purple_whiteboard_set_brush
-
-/* for static plugins */
-#define gaim_init_ssl_plugin			purple_init_ssl_plugin
-#define gaim_init_ssl_openssl_plugin	purple_init_ssl_openssl_plugin
-#define gaim_init_ssl_gnutls_plugin		purple_init_ssl_gnutls_plugin
-#define gaim_init_gg_plugin				purple_init_gg_plugin
-#define gaim_init_jabber_plugin			purple_init_jabber_plugin
-#define gaim_init_sametime_plugin		purple_init_sametime_plugin
-#define gaim_init_msn_plugin			purple_init_msn_plugin
-#define gaim_init_novell_plugin			purple_init_novell_plugin
-#define gaim_init_qq_plugin				purple_init_qq_plugin
-#define gaim_init_simple_plugin			purple_init_simple_plugin
-#define gaim_init_yahoo_plugin			purple_init_yahoo_plugin
-#define gaim_init_zephyr_plugin			purple_init_zephyr_plugin
-#define gaim_init_aim_plugin			purple_init_aim_plugin
-#define gaim_init_icq_plugin			purple_init_icq_plugin
-
-#endif /* _GAIM_COMPAT_H_ */
--- a/libpurple/imgstore.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/imgstore.h	Mon Oct 31 01:25:36 2011 +0000
@@ -68,7 +68,6 @@
  * @param path  The path to the image.
  *
  * @return  The stored image.
- * @since 2.X.X
  */
 PurpleStoredImage *
 purple_imgstore_new_from_file(const char *path);
--- a/libpurple/internal.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/internal.h	Mon Oct 31 01:25:36 2011 +0000
@@ -151,12 +151,6 @@
 
 #include <glib-object.h>
 
-/* Safer ways to work with static buffers. When using non-static
- * buffers, either use g_strdup_* functions (preferred) or use
- * g_strlcpy/g_strlcpy directly. */
-#define purple_strlcpy(dest, src) g_strlcpy(dest, src, sizeof(dest))
-#define purple_strlcat(dest, src) g_strlcat(dest, src, sizeof(dest))
-
 #define PURPLE_WEBSITE "http://pidgin.im/"
 #define PURPLE_DEVEL_WEBSITE "http://developer.pidgin.im/"
 
@@ -176,12 +170,6 @@
 void
 _purple_buddy_icons_blist_loaded_cb(void);
 
-/* This is for the purple_core_migrate() code to tell the buddy
- * icon subsystem about the old icons directory so it can
- * migrate any icons in use. */
-void
-_purple_buddy_icon_set_old_icons_dir(const char *dirname);
-
 /**
  * Creates a connection to the specified account and either connects
  * or attempts to register a new account.  If you are logging in,
--- a/libpurple/log.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/log.c	Mon Oct 31 01:25:36 2011 +0000
@@ -1103,7 +1103,7 @@
 			/* Find the account for username in the list of accounts for protocol. */
 			username_unescaped = purple_unescape_filename(username);
 			for (account_iter = g_list_first(accounts) ; account_iter != NULL ; account_iter = account_iter->next) {
-				if (purple_strequal(((PurpleAccount *)account_iter->data)->username, username_unescaped)) {
+				if (purple_strequal(purple_account_get_username((PurpleAccount *)account_iter->data), username_unescaped)) {
 					account = account_iter->data;
 					break;
 				}
--- a/libpurple/log.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/log.h	Mon Oct 31 01:25:36 2011 +0000
@@ -301,8 +301,6 @@
  * @param name                The name of the log
  * @param account             The account
  * @return                    The activity score
- *
- * @since 2.6.0
  */
 int purple_log_get_activity_score(PurpleLogType type, const char *name, PurpleAccount *account);
 
--- a/libpurple/media-gst.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media-gst.h	Mon Oct 31 01:25:36 2011 +0000
@@ -81,8 +81,6 @@
  * Gets the element type's GType.
  *
  * @return The element type's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_element_type_get_type(void);
 
@@ -90,8 +88,6 @@
  * Gets the element info's GType.
  *
  * @return The element info's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_element_info_get_type(void);
 
@@ -102,8 +98,6 @@
  * @param sess_id The session id of the session to get the source from.
  *
  * @return The source retrieved.
- *
- * @since 2.6.0
  */
 GstElement *purple_media_get_src(PurpleMedia *media, const gchar *sess_id);
 
@@ -115,8 +109,6 @@
  * @param participant Optionally, the participant of the stream to get the tee from.
  *
  * @return The GstTee element from the chosen session/stream.
- *
- * @since 2.6.0
  */
 GstElement *purple_media_get_tee(PurpleMedia *media,
 		const gchar *session_id, const gchar *participant);
@@ -128,8 +120,6 @@
  * @param manager The media manager to get the pipeline from.
  *
  * @return The pipeline.
- *
- * @since 2.6.0
  */
 GstElement *purple_media_manager_get_pipeline(PurpleMediaManager *manager);
 
@@ -141,8 +131,6 @@
  * @param media The media call this element is requested for.
  * @param session_id The id of the session this element is requested for or NULL.
  * @param participant The remote user this element is requested for or NULL.
- *
- * @since 2.6.0
  */
 GstElement *purple_media_manager_get_element(PurpleMediaManager *manager,
 		PurpleMediaSessionType type, PurpleMedia *media,
@@ -167,8 +155,6 @@
  *
  * @param manager The media manager to set the media formats.
  * @param caps Set of allowed media formats.
- *
- * @since 2.8.0
  */
 void purple_media_manager_set_video_caps(PurpleMediaManager *manager,
 		GstCaps *caps);
@@ -179,8 +165,6 @@
  * @param manager The media manager to get the media formats from.
  *
  * @return @c GstCaps limiting the video source's formats.
- *
- * @since 2.8.0
  */
 GstCaps *purple_media_manager_get_video_caps(PurpleMediaManager *manager);
 
--- a/libpurple/media.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media.h	Mon Oct 31 01:25:36 2011 +0000
@@ -57,8 +57,6 @@
  * Gets the media class's GType
  *
  * @return The media class's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_get_type(void);
 
@@ -68,8 +66,6 @@
  * @param media The media session from which to retrieve session IDs.
  *
  * @return GList of session IDs. The caller must free the list.
- *
- * @since 2.6.0
  */
 GList *purple_media_get_session_ids(PurpleMedia *media);
 
@@ -79,8 +75,6 @@
  * @param media The media session to retrieve the account from.
  *
  * @return The account retrieved.
- *
- * @since 2.6.0
  */
 PurpleAccount *purple_media_get_account(PurpleMedia *media);
 
@@ -90,8 +84,6 @@
  * @param media The media session to retrieve the prpl data from.
  *
  * @return The prpl data retrieved.
- *
- * @since 2.6.0
  */
 gpointer purple_media_get_prpl_data(PurpleMedia *media);
 
@@ -100,8 +92,6 @@
  *
  * @param media The media session to set the prpl data on.
  * @param prpl_data The data to set on the media session.
- *
- * @since 2.6.0
  */
 void purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data);
 
@@ -111,8 +101,6 @@
  * @param media The media object to set the state on.
  * @param error The format of the error message to send in the signal.
  * @param ... The arguments to plug into the format.
- *
- * @since 2.6.0
  */
 void purple_media_error(PurpleMedia *media, const gchar *error, ...);
 
@@ -122,8 +110,6 @@
  * @param media The media object with which to end streams.
  * @param session_id The session to end streams on.
  * @param participant The participant to end streams with.
- *
- * @since 2.6.0
  */
 void purple_media_end(PurpleMedia *media, const gchar *session_id,
 		const gchar *participant);
@@ -136,8 +122,6 @@
  * @param session_id The id of the session of the stream being signaled.
  * @param participant The participant of the stream being signaled.
  * @param local TRUE if the info originated locally, FALSE if on the remote end.
- *
- * @since 2.6.0
  */
 void purple_media_stream_info(PurpleMedia *media, PurpleMediaInfoType type,
 		const gchar *session_id, const gchar *participant,
@@ -158,8 +142,6 @@
  * @param media The media object to set the parameters on.
  * @param num_params The number of parameters to pass
  * @param params Array of @c GParameter to pass
- *
- * @since 2.8.0
  */
 void purple_media_set_params(PurpleMedia *media,
 		guint num_params, GParameter *params);
@@ -172,8 +154,6 @@
  * @param media The media object
  *
  * @return NULL-terminated array of names of supported parameters.
- *
- * @since 2.8.0
  */
 const gchar **purple_media_get_available_params(PurpleMedia *media);
 
@@ -184,8 +164,6 @@
  * @param param name of parameter
  *
  * @return @c TRUE if backend recognizes the parameter, @c FALSE otherwise.
- *
- * @since 2.8.0
  */
 gboolean purple_media_param_is_supported(PurpleMedia *media, const gchar *param);
 
@@ -205,8 +183,6 @@
  * @param params The parameters to pass to Farsight.
  *
  * @return @c TRUE The stream was added successfully, @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_media_add_stream(PurpleMedia *media, const gchar *sess_id,
 		const gchar *who, PurpleMediaSessionType type,
@@ -220,8 +196,6 @@
  * @param sess_id The session id of the session to get the type from.
  *
  * @return The retreived session type.
- *
- * @since 2.6.0
  */
 PurpleMediaSessionType purple_media_get_session_type(PurpleMedia *media, const gchar *sess_id);
 
@@ -231,8 +205,6 @@
  * @param media The media object to get the manager instance from.
  *
  * @return The PurpleMediaManager instance retrieved.
- *
- * @since 2.6.0
  */
 struct _PurpleMediaManager *purple_media_get_manager(PurpleMedia *media);
 
@@ -243,8 +215,6 @@
  * @param sess_id The session id of the session to get the codecs from.
  *
  * @return The retreieved codecs.
- *
- * @since 2.6.0
  */
 GList *purple_media_get_codecs(PurpleMedia *media, const gchar *sess_id);
 
@@ -255,8 +225,6 @@
  * @param sess_id The session id of the session find the stream in.
  * @param participant The name of the remote user to add the candidates for.
  * @param remote_candidates The remote candidates to add.
- *
- * @since 2.6.0
  */
 void purple_media_add_remote_candidates(PurpleMedia *media,
 					const gchar *sess_id,
@@ -269,8 +237,6 @@
  * @param media The media object to find the session in.
  * @param sess_id The session id of the session to find the stream in.
  * @param participant The name of the remote user to get the candidates from.
- *
- * @since 2.6.0
  */
 GList *purple_media_get_local_candidates(PurpleMedia *media,
 					 const gchar *sess_id,
@@ -285,8 +251,6 @@
  *                    from.
  *
  * @return The active candidates retrieved.
- *
- * @since 2.8.0
  */
 GList *purple_media_get_active_local_candidates(PurpleMedia *media,
 		const gchar *sess_id, const gchar *participant);
@@ -300,8 +264,6 @@
  *                    from.
  *
  * @return The remote candidates retrieved.
- *
- * @since 2.8.0
  */
 GList *purple_media_get_active_remote_candidates(PurpleMedia *media,
 		const gchar *sess_id, const gchar *participant);
@@ -315,8 +277,6 @@
  * @param codecs The list of remote codecs to set.
  *
  * @return @c TRUE The codecs were set successfully, or @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_media_set_remote_codecs(PurpleMedia *media, const gchar *sess_id,
 					const gchar *participant, GList *codecs);
@@ -329,8 +289,6 @@
  * @param participant The remote user to check for.
  *
  * @return @c TRUE All streams for the given session_id/participant combination have candidates prepared, @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_media_candidates_prepared(PurpleMedia *media,
 		const gchar *session_id, const gchar *participant);
@@ -343,8 +301,6 @@
  * @param codec The codec to set the session to stream.
  *
  * @return @c TRUE The codec was successfully changed, or @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, PurpleMediaCodec *codec);
 
@@ -355,8 +311,6 @@
  * @param sess_id The session id of the session to check.
  *
  * @return @c TRUE The codecs are ready, or @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id);
 
@@ -368,8 +322,6 @@
  * @param participant The participant of the stream to check.
  *
  * @return TRUE if the local user is the stream's initator, else FALSE.
- *
- * @since 2.6.0
  */
 gboolean purple_media_is_initiator(PurpleMedia *media,
 		const gchar *sess_id, const gchar *participant);
@@ -382,8 +334,6 @@
  * @param participant The participant to check.
  *
  * @return @c TRUE The selected streams have been accepted, or @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_media_accepted(PurpleMedia *media, const gchar *sess_id,
 		const gchar *participant);
@@ -394,8 +344,6 @@
  * @param media The media object the sessions are in.
  * @param session_id The session to select (if any).
  * @param level The level to set the volume to.
- *
- * @since 2.6.0
  */
 void purple_media_set_input_volume(PurpleMedia *media, const gchar *session_id, double level);
 
@@ -406,8 +354,6 @@
  * @param session_id The session to limit the streams to (if any).
  * @param participant The participant to limit the streams to (if any).
  * @param level The level to set the volume to.
- *
- * @since 2.6.0
  */
 void purple_media_set_output_volume(PurpleMedia *media, const gchar *session_id,
 		const gchar *participant, double level);
@@ -421,8 +367,6 @@
  * @param window_id The window id use for embedding the video in.
  *
  * @return An id to reference the output window.
- *
- * @since 2.6.0
  */
 gulong purple_media_set_output_window(PurpleMedia *media,
 		const gchar *session_id, const gchar *participant,
@@ -432,8 +376,6 @@
  * Removes all output windows from a given media session.
  *
  * @param media The instance to remove all output windows from.
- *
- * @since 2.6.0
  */
 void purple_media_remove_output_windows(PurpleMedia *media);
 
--- a/libpurple/media/backend-fs2.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media/backend-fs2.h	Mon Oct 31 01:25:36 2011 +0000
@@ -50,8 +50,6 @@
  * Gets the type of the Farsight 2 media backend object.
  *
  * @return The Farsight 2 media backend's GType
- *
- * @since 2.7.0
  */
 GType purple_media_backend_fs2_get_type(void);
 
--- a/libpurple/media/backend-iface.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media/backend-iface.h	Mon Oct 31 01:25:36 2011 +0000
@@ -77,8 +77,6 @@
  * Gets the media backend's GType.
  *
  * @return The media backend's GType.
- *
- * @since 2.7.0
  */
 GType purple_media_backend_get_type(void);
 
@@ -95,8 +93,6 @@
  * @param params The additional parameters to pass when creating the stream.
  *
  * @return True if the stream was successfully created, othewise False.
- *
- * @since 2.7.0
  */
 gboolean purple_media_backend_add_stream(PurpleMediaBackend *self,
 		const gchar *sess_id, const gchar *who,
@@ -111,8 +107,6 @@
  * @param sess_id The session id associated with the stream.
  * @param participant The participant associated with the stream.
  * @param remote_candidates The list of remote candidates to add.
- *
- * @since 2.7.0
  */
 void purple_media_backend_add_remote_candidates(PurpleMediaBackend *self,
 		const gchar *sess_id, const gchar *participant,
@@ -128,8 +122,6 @@
  * @param sess_id The session id of the session to check.
  *
  * @return True if the codecs are ready, otherwise False.
- *
- * @since 2.7.0
  */
 gboolean purple_media_backend_codecs_ready(PurpleMediaBackend *self,
 		const gchar *sess_id);
@@ -144,8 +136,6 @@
  * @param sess_id The session id of the session to use.
  *
  * @return The codec intersection list.
- *
- * @since 2.7.0
  */
 GList *purple_media_backend_get_codecs(PurpleMediaBackend *self,
 		const gchar *sess_id);
@@ -158,8 +148,6 @@
  * @param particilant The participant associated with the stream.
  *
  * @return The list of local candidates.
- *
- * @since 2.7.0
  */
 GList *purple_media_backend_get_local_candidates(PurpleMediaBackend *self,
 		const gchar *sess_id, const gchar *participant);
@@ -173,8 +161,6 @@
  * @param codecs The list of remote codecs to set.
  *
  * @return True if the remote codecs were set successfully, otherwise False.
- *
- * @since 2.7.0
  */
 gboolean purple_media_backend_set_remote_codecs(PurpleMediaBackend *self,
 		const gchar *sess_id, const gchar *participant,
@@ -188,8 +174,6 @@
  * @param codec The codec to set.
  *
  * @return True if set successfully, otherwise False.
- *
- * @since 2.7.0
  */
 gboolean purple_media_backend_set_send_codec(PurpleMediaBackend *self,
 		const gchar *sess_id, PurpleMediaCodec *codec);
@@ -200,8 +184,6 @@
  * @param self The media backend to set the parameters on.
  * @param num_params The number of parameters to pass to backend
  * @param params Array of @c GParameter to pass to backend
- *
- * @since 2.8.0
  */
 void purple_media_backend_set_params(PurpleMediaBackend *self,
 		guint num_params, GParameter *params);
@@ -214,8 +196,6 @@
  * @param self The media backend
  *
  * @return NULL-terminated array of names of supported parameters.
- *
- * @since 2.8.0
  */
 const gchar **purple_media_backend_get_available_params(PurpleMediaBackend *self);
 
--- a/libpurple/media/candidate.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media/candidate.h	Mon Oct 31 01:25:36 2011 +0000
@@ -47,8 +47,6 @@
  * Gets the type of the media candidate structure.
  *
  * @return The media canditate's GType
- *
- * @since 2.6.0
  */
 GType purple_media_candidate_get_type(void);
 
@@ -63,8 +61,6 @@
  * @param port The network port.
  *
  * @return The newly created PurpleMediaCandidate instance.
- *
- * @since 2.6.0
  */
 PurpleMediaCandidate *purple_media_candidate_new(
 		const gchar *foundation, guint component_id,
@@ -78,8 +74,6 @@
  * @param candidate The candidate to copy.
  *
  * @return The copy of the PurpleMediaCandidate.
- *
- * @since 2.7.0
  */
 PurpleMediaCandidate *purple_media_candidate_copy(
 		PurpleMediaCandidate *candidate);
@@ -90,8 +84,6 @@
  * @param candidates The list of candidates to be copied.
  *
  * @return The copy of the GList.
- *
- * @since 2.6.0
  */
 GList *purple_media_candidate_list_copy(GList *candidates);
 
@@ -99,8 +91,6 @@
  * Frees a GList of PurpleMediaCandidate and its contents.
  *
  * @param candidates The list of candidates to be freed.
- *
- * @since 2.6.0
  */
 void purple_media_candidate_list_free(GList *candidates);
 
@@ -110,8 +100,6 @@
  * @param candidate The candidate to get the foundation from.
  *
  * @return The foundation.
- *
- * @since 2.6.0
  */
 gchar *purple_media_candidate_get_foundation(PurpleMediaCandidate *candidate);
 
@@ -121,8 +109,6 @@
  * @param candidate The candidate to get the compnent id from.
  *
  * @return The component id.
- *
- * @since 2.6.0
  */
 guint purple_media_candidate_get_component_id(PurpleMediaCandidate *candidate);
 
@@ -132,8 +118,6 @@
  * @param candidate The candidate to get the IP address from.
  *
  * @return The IP address.
- *
- * @since 2.6.0
  */
 gchar *purple_media_candidate_get_ip(PurpleMediaCandidate *candidate);
 
@@ -143,8 +127,6 @@
  * @param candidate The candidate to get the port from.
  *
  * @return The port.
- *
- * @since 2.6.0
  */
 guint16 purple_media_candidate_get_port(PurpleMediaCandidate *candidate);
 
@@ -156,8 +138,6 @@
  * @param candidate The candidate to get the base IP address from.
  *
  * @return The base IP address.
- *
- * @since 2.6.0
  */
 gchar *purple_media_candidate_get_base_ip(PurpleMediaCandidate *candidate);
 
@@ -169,8 +149,6 @@
  * @param candidate The candidate to get the base port.
  *
  * @return The base port.
- *
- * @since 2.6.0
  */
 guint16 purple_media_candidate_get_base_port(PurpleMediaCandidate *candidate);
 
@@ -180,8 +158,6 @@
  * @param candidate The candidate to get the protocol from.
  *
  * @return The protocol.
- *
- * @since 2.6.0
  */
 PurpleMediaNetworkProtocol purple_media_candidate_get_protocol(
 		PurpleMediaCandidate *candidate);
@@ -192,8 +168,6 @@
  * @param candidate The candidate to get the priority from.
  *
  * @return The priority.
- *
- * @since 2.6.0
  */
 guint32 purple_media_candidate_get_priority(PurpleMediaCandidate *candidate);
 
@@ -203,8 +177,6 @@
  * @param candidate The candidate to get the candidate type from.
  *
  * @return The candidate type.
- *
- * @since 2.6.0
  */
 PurpleMediaCandidateType purple_media_candidate_get_candidate_type(
 		PurpleMediaCandidate *candidate);
@@ -217,8 +189,6 @@
  * @param The candidate to get the username from.
  *
  * @return The username.
- *
- * @since 2.6.0
  */
 gchar *purple_media_candidate_get_username(PurpleMediaCandidate *candidate);
 
@@ -230,8 +200,6 @@
  * @param The candidate to get the password from.
  *
  * @return The password.
- *
- * @since 2.6.0
  */
 gchar *purple_media_candidate_get_password(PurpleMediaCandidate *candidate);
 
@@ -241,8 +209,6 @@
  * @param The candidate to get the TTL from.
  *
  * @return The TTL.
- *
- * @since 2.6.0
  */
 guint purple_media_candidate_get_ttl(PurpleMediaCandidate *candidate);
 
--- a/libpurple/media/codec.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media/codec.h	Mon Oct 31 01:25:36 2011 +0000
@@ -50,8 +50,6 @@
  * Gets the type of the media codec structure.
  *
  * @return The media codec's GType
- *
- * @since 2.6.0
  */
 GType purple_media_codec_get_type(void);
 
@@ -64,8 +62,6 @@
  * @param clock_rate The clock rate this codec encodes at, if applicable.
  *
  * @return The newly created PurpleMediaCodec.
- *
- * @since 2.6.0
  */
 PurpleMediaCodec *purple_media_codec_new(int id, const char *encoding_name,
 		PurpleMediaSessionType media_type, guint clock_rate);
@@ -76,8 +72,6 @@
  * @param The codec to get the id from.
  *
  * @return The codec id.
- *
- * @since 2.6.0
  */
 guint purple_media_codec_get_id(PurpleMediaCodec *codec);
 
@@ -87,8 +81,6 @@
  * @param The codec to get the encoding name from.
  *
  * @return The encoding name.
- *
- * @since 2.6.0
  */
 gchar *purple_media_codec_get_encoding_name(PurpleMediaCodec *codec);
 
@@ -98,8 +90,6 @@
  * @param The codec to get the clock rate from.
  *
  * @return The clock rate.
- *
- * @since 2.6.0
  */
 guint purple_media_codec_get_clock_rate(PurpleMediaCodec *codec);
 
@@ -109,8 +99,6 @@
  * @param The codec to get the number of channels from.
  *
  * @return The number of channels.
- *
- * @since 2.6.0
  */
 guint purple_media_codec_get_channels(PurpleMediaCodec *codec);
 
@@ -123,8 +111,6 @@
  *
  * @return The list of optional parameters. The list is owned by the codec and
  *         should not be freed.
- *
- * @since 2.6.0
  */
 GList *purple_media_codec_get_optional_parameters(PurpleMediaCodec *codec);
 
@@ -134,8 +120,6 @@
  * @param codec The codec to add the parameter to.
  * @param name The name of the parameter to add.
  * @param value The value of the parameter to add.
- *
- * @since 2.6.0
  */
 void purple_media_codec_add_optional_parameter(PurpleMediaCodec *codec,
 		const gchar *name, const gchar *value);
@@ -145,8 +129,6 @@
  *
  * @param codec The codec to remove the parameter from.
  * @param param A pointer to the parameter to remove.
- *
- * @since 2.6.0
  */
 void purple_media_codec_remove_optional_parameter(PurpleMediaCodec *codec,
 		PurpleKeyValuePair *param);
@@ -159,8 +141,6 @@
  * @param value The value to search for or NULL.
  *
  * @return The value found or NULL.
- *
- * @since 2.6.0
  */
 PurpleKeyValuePair *purple_media_codec_get_optional_parameter(
 		PurpleMediaCodec *codec, const gchar *name,
@@ -172,8 +152,6 @@
  * @param codec The codec to copy.
  *
  * @return The copy of the codec.
- *
- * @since 2.7.0
  */
 PurpleMediaCodec *purple_media_codec_copy(PurpleMediaCodec *codec);
 
@@ -183,8 +161,6 @@
  * @param codecs The list of codecs to be copied.
  *
  * @return The copy of the GList.
- *
- * @since 2.6.0
  */
 GList *purple_media_codec_list_copy(GList *codecs);
 
@@ -192,8 +168,6 @@
  * Frees a GList of PurpleMediaCodec and its contents.
  *
  * @param codecs The list of codecs to be freed.
- *
- * @since 2.6.0
  */
 void purple_media_codec_list_free(GList *codecs);
 
@@ -203,8 +177,6 @@
  * @param codec The codec to create the string of.
  *
  * @return The new string representation.
- *
- * @since 2.6.0
  */
 gchar *purple_media_codec_to_string(const PurpleMediaCodec *codec);
 
--- a/libpurple/media/enum-types.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/media/enum-types.h	Mon Oct 31 01:25:36 2011 +0000
@@ -107,8 +107,6 @@
  * Gets the media candidate type's GType
  *
  * @return The media candidate type's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_candidate_type_get_type(void);
 
@@ -116,8 +114,6 @@
  * Gets the type of the media caps flags
  *
  * @return The media caps flags' GType
- *
- * @since 2.7.0
  */
 GType purple_media_caps_get_type(void);
 
@@ -125,8 +121,6 @@
  * Gets the type of the info type enum
  *
  * @return The info type enum's GType
- *
- * @since 2.6.0
  */
 GType purple_media_info_type_get_type(void);
 
@@ -134,8 +128,6 @@
  * Gets the media network protocol's GType
  *
  * @return The media network protocol's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_network_protocol_get_type(void);
 
@@ -143,8 +135,6 @@
  * Gets the media session type's GType
  *
  * @return The media session type's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_session_type_get_type(void);
 
@@ -152,8 +142,6 @@
  * Gets the type of the state-changed enum
  *
  * @return The state-changed enum's GType
- *
- * @since 2.6.0
  */
 GType purple_media_state_changed_get_type(void);
 
--- a/libpurple/mediamanager.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/mediamanager.h	Mon Oct 31 01:25:36 2011 +0000
@@ -60,8 +60,6 @@
  * Gets the media manager's GType.
  *
  * @return The media manager's GType.
- *
- * @since 2.6.0
  */
 GType purple_media_manager_get_type(void);
 
@@ -69,8 +67,6 @@
  * Gets the "global" media manager object. It's created if it doesn't already exist.
  *
  * @return The "global" instance of the media manager object.
- *
- * @since 2.6.0
  */
 PurpleMediaManager *purple_media_manager_get(void);
 
@@ -84,8 +80,6 @@
  * @param initiator TRUE if the local user is the initiator of this media call, FALSE otherwise.
  *
  * @return A newly created media session.
- *
- * @since 2.6.0
  */
 PurpleMedia *purple_media_manager_create_media(PurpleMediaManager *manager,
 						PurpleAccount *account,
@@ -99,8 +93,6 @@
  * @param manager The media manager to get all of the sessions from.
  *
  * @return A list of all the media sessions.
- *
- * @since 2.6.0
  */
 GList *purple_media_manager_get_media(PurpleMediaManager *manager);
 
@@ -111,8 +103,6 @@
  * @param account The account the sessions are on.
  *
  * @return A list of the media sessions on the given account.
- *
- * @since 2.6.0
  */
 GList *purple_media_manager_get_media_by_account(
 		PurpleMediaManager *manager, PurpleAccount *account);
@@ -122,8 +112,6 @@
  *
  * @param manager The media manager to remove the media session from.
  * @param media The media session to remove.
- *
- * @since 2.6.0
  */
 void
 purple_media_manager_remove_media(PurpleMediaManager *manager,
@@ -140,8 +128,6 @@
  * @param participant The participant the output windows are registered with.
  *
  * @return TRUE if it succeeded, FALSE if it failed.
- *
- * @since 2.6.0
  */
 gboolean purple_media_manager_create_output_window(
 		PurpleMediaManager *manager, PurpleMedia *media,
@@ -157,8 +143,6 @@
  * @param window_id The window ID to embed the video in.
  *
  * @return A unique ID to the registered output window, 0 if it failed.
- *
- * @since 2.6.0
  */
 gulong purple_media_manager_set_output_window(PurpleMediaManager *manager,
 		PurpleMedia *media, const gchar *session_id,
@@ -171,8 +155,6 @@
  * @param output_window_id The ID of the output window.
  *
  * @return TRUE if it found the output window and was successful, else FALSE.
- *
- * @since 2.6.0
  */
 gboolean purple_media_manager_remove_output_window(
 		PurpleMediaManager *manager, gulong output_window_id);
@@ -184,8 +166,6 @@
  * @param media The media instance the output windows were registered for.
  * @param session_id The session the output windows were registered for.
  * @param participant The participant the output windows were registered for.
- *
- * @since 2.6.0
  */
 void purple_media_manager_remove_output_windows(
 		PurpleMediaManager *manager, PurpleMedia *media,
@@ -196,8 +176,6 @@
  *
  * @param manager The manager to set the caps on.
  * @param caps The caps to set.
- *
- * @since 2.6.0
  */
 void purple_media_manager_set_ui_caps(PurpleMediaManager *manager,
 		PurpleMediaCaps caps);
@@ -208,8 +186,6 @@
  * @param manager The manager to get caps from.
  *
  * @return caps The caps retrieved.
- *
- * @since 2.6.0
  */
 PurpleMediaCaps purple_media_manager_get_ui_caps(PurpleMediaManager *manager);
 
@@ -218,8 +194,6 @@
  *
  * @param manager The manager to set the caps on.
  * @param backend_type The media backend type to use.
- *
- * @since 2.7.0
  */
 void purple_media_manager_set_backend_type(PurpleMediaManager *manager,
 		GType backend_type);
@@ -230,8 +204,6 @@
  * @param manager The manager to get the media backend type from.
  *
  * @return The type of media backend type media objects will use.
- *
- * @since 2.7.0
  */
 GType purple_media_manager_get_backend_type(PurpleMediaManager *manager);
 
--- a/libpurple/network.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/network.c	Mon Oct 31 01:25:36 2011 +0000
@@ -391,14 +391,9 @@
 	return FALSE;
 }
 
-static gboolean listen_map_external = TRUE;
-void purple_network_listen_map_external(gboolean map_external)
-{
-	listen_map_external = map_external;
-}
-
 static PurpleNetworkListenData *
-purple_network_do_listen(unsigned short port, int socket_family, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
+purple_network_do_listen(unsigned short port, int socket_family, int socket_type, gboolean map_external,
+                             PurpleNetworkListenCallback cb, gpointer cb_data)
 {
 	int listenfd = -1;
 	int flags;
@@ -503,7 +498,7 @@
 	listen_data->cb_data = cb_data;
 	listen_data->socket_type = socket_type;
 
-	if (!purple_socket_speaks_ipv4(listenfd) || !listen_map_external ||
+	if (!purple_socket_speaks_ipv4(listenfd) || !map_external ||
 			!purple_prefs_get_bool("/purple/network/map_ports"))
 	{
 		purple_debug_info("network", "Skipping external port mapping.\n");
@@ -531,27 +526,19 @@
 }
 
 PurpleNetworkListenData *
-purple_network_listen_family(unsigned short port, int socket_family,
-                             int socket_type, PurpleNetworkListenCallback cb,
+purple_network_listen(unsigned short port, int socket_family, int socket_type,
+                             gboolean map_external, PurpleNetworkListenCallback cb,
                              gpointer cb_data)
 {
 	g_return_val_if_fail(port != 0, NULL);
 
-	return purple_network_do_listen(port, socket_family, socket_type,
+	return purple_network_do_listen(port, socket_family, socket_type, map_external,
 	                                cb, cb_data);
 }
 
 PurpleNetworkListenData *
-purple_network_listen(unsigned short port, int socket_type,
-		PurpleNetworkListenCallback cb, gpointer cb_data)
-{
-	return purple_network_listen_family(port, AF_UNSPEC, socket_type,
-	                                    cb, cb_data);
-}
-
-PurpleNetworkListenData *
-purple_network_listen_range_family(unsigned short start, unsigned short end,
-                                   int socket_family, int socket_type,
+purple_network_listen_range(unsigned short start, unsigned short end,
+                                   int socket_family, int socket_type, gboolean map_external,
                                    PurpleNetworkListenCallback cb,
                                    gpointer cb_data)
 {
@@ -566,7 +553,7 @@
 	}
 
 	for (; start <= end; start++) {
-		ret = purple_network_do_listen(start, AF_UNSPEC, socket_type, cb, cb_data);
+		ret = purple_network_do_listen(start, AF_UNSPEC, socket_type, map_external, cb, cb_data);
 		if (ret != NULL)
 			break;
 	}
@@ -574,15 +561,6 @@
 	return ret;
 }
 
-PurpleNetworkListenData *
-purple_network_listen_range(unsigned short start, unsigned short end,
-                            int socket_type, PurpleNetworkListenCallback cb,
-                            gpointer cb_data)
-{
-	return purple_network_listen_range_family(start, end, AF_UNSPEC,
-	                                          socket_type, cb, cb_data);
-}
-
 void purple_network_listen_cancel(PurpleNetworkListenData *listen_data)
 {
 	if (listen_data->mapping_data != NULL)
@@ -991,7 +969,7 @@
 	if (stun_server && stun_server[0] != '\0') {
 		if (purple_network_is_available()) {
 			purple_debug_info("network", "running DNS query for STUN server\n");
-			purple_dnsquery_a_account(NULL, stun_server, 3478, purple_network_ip_lookup_cb,
+			purple_dnsquery_a(NULL, stun_server, 3478, purple_network_ip_lookup_cb,
 				&stun_ip);
 		} else {
 			purple_debug_info("network",
@@ -1009,7 +987,7 @@
 	if (turn_server && turn_server[0] != '\0') {
 		if (purple_network_is_available()) {
 			purple_debug_info("network", "running DNS query for TURN server\n");
-			purple_dnsquery_a_account(NULL, turn_server,
+			purple_dnsquery_a(NULL, turn_server,
 				purple_prefs_get_int("/purple/network/turn_port"),
 				purple_network_ip_lookup_cb, &turn_ip);
 		} else {
--- a/libpurple/network.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/network.h	Mon Oct 31 01:25:36 2011 +0000
@@ -92,7 +92,6 @@
  *
  * @note The caller must free this list.  If libpurple was built with
  *       support for it, this function also enumerates IPv6 addresses.
- * @since 2.7.0
  *
  * @return A list of local IP addresses.
  */
@@ -118,18 +117,6 @@
 const char *purple_network_get_my_ip(int fd);
 
 /**
- * Should calls to purple_network_listen() and purple_network_listen_range()
- * map the port externally using NAT-PMP or UPnP?
- * The default value is TRUE
- *
- * @param map_external Should the open port be mapped externally?
- * @deprecated In 3.0.0 a boolean will be added to the functions mentioned
- *             above to perform the same function.
- * @since 2.3.0
- */
-void purple_network_listen_map_external(gboolean map_external);
-
-/**
  * Attempts to open a listening port ONLY on the specified port number.
  * You probably want to use purple_network_listen_range() instead of this.
  * This function is useful, for example, if you wanted to write a telnet
@@ -142,9 +129,22 @@
  * close the listening socket, and add a new watcher on the new socket accept
  * returned.
  *
+ * Libpurple does not currently do any port mapping (stateful firewall hole
+ * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped
+ * addresses, a mapping is done).
+ *
  * @param port The port number to bind to.  Must be greater than 0.
+ * @param socket_family The protocol family of the socket.  This should be
+ *                      AF_INET for IPv4 or AF_INET6 for IPv6.  IPv6 sockets
+ *                      may or may not be able to accept IPv4 connections
+ *                      based on the system configuration (use
+ *                      purple_socket_speaks_ipv4 to check).  If an IPv6
+ *                      socket doesn't accept V4-mapped addresses, you will
+ *                      need a second listener to support both v4 and v6.
  * @param socket_type The type of socket to open for listening.
  *   This will be either SOCK_STREAM for TCP or SOCK_DGRAM for UDP.
+ * @param map_external Should the open port be mapped externally using
+ *           NAT-PNP or UPnP?  (default should be TRUE)
  * @param cb The callback to be invoked when the port to listen on is available.
  *           The file descriptor of the listening socket will be specified in
  *           this callback, or -1 if no socket could be established.
@@ -155,28 +155,8 @@
  *         socket to listen on.
  */
 PurpleNetworkListenData *purple_network_listen(unsigned short port,
-		int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data);
-
-/**
- * \copydoc purple_network_listen
- *
- * Libpurple does not currently do any port mapping (stateful firewall hole
- * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped
- * addresses, a mapping is done).
- *
- * @param socket_family The protocol family of the socket.  This should be
- *                      AF_INET for IPv4 or AF_INET6 for IPv6.  IPv6 sockets
- *                      may or may not be able to accept IPv4 connections
- *                      based on the system configuration (use
- *                      purple_socket_speaks_ipv4 to check).  If an IPv6
- *                      socket doesn't accept V4-mapped addresses, you will
- *                      need a second listener to support both v4 and v6.
- * @since 2.7.0
- * @deprecated This function will be renamed to purple_network_listen in 3.0.0.
- */
-PurpleNetworkListenData *purple_network_listen_family(unsigned short port,
-	int socket_family, int socket_type, PurpleNetworkListenCallback cb,
-	gpointer cb_data);
+	int socket_family, int socket_type, gboolean map_external,
+	PurpleNetworkListenCallback cb, gpointer cb_data);
 
 /**
  * Opens a listening port selected from a range of ports.  The range of
@@ -192,13 +172,26 @@
  * the listening socket, and add a new watcher on the new socket accept
  * returned.
  *
+ * Libpurple does not currently do any port mapping (stateful firewall hole
+ * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped
+ * addresses, a mapping is done).
+ *
  * @param start The port number to bind to, or 0 to pick a random port.
  *              Users are allowed to override this arg in prefs.
  * @param end The highest possible port in the range of ports to listen on,
  *            or 0 to pick a random port.  Users are allowed to override this
  *            arg in prefs.
+ * @param socket_family The protocol family of the socket.  This should be
+ *                      AF_INET for IPv4 or AF_INET6 for IPv6.  IPv6 sockets
+ *                      may or may not be able to accept IPv4 connections
+ *                      based on the system configuration (use
+ *                      purple_socket_speaks_ipv4 to check).  If an IPv6
+ *                      socket doesn't accept V4-mapped addresses, you will
+ *                      need a second listener to support both v4 and v6.
  * @param socket_type The type of socket to open for listening.
  *   This will be either SOCK_STREAM for TCP or SOCK_DGRAM for UDP.
+ * @param map_external Should the open port be mapped externally using
+ *           NAT-PNP or UPnP?  (default should be TRUE)
  * @param cb The callback to be invoked when the port to listen on is available.
  *           The file descriptor of the listening socket will be specified in
  *           this callback, or -1 if no socket could be established.
@@ -208,31 +201,10 @@
  *         the pending listener, or NULL if unable to obtain a local
  *         socket to listen on.
  */
-PurpleNetworkListenData *purple_network_listen_range(unsigned short start,
-		unsigned short end, int socket_type,
-		PurpleNetworkListenCallback cb, gpointer cb_data);
-
-/**
- * \copydoc purple_network_listen_range
- *
- * Libpurple does not currently do any port mapping (stateful firewall hole
- * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped
- * addresses, a mapping is done).
- *
- * @param socket_family The protocol family of the socket.  This should be
- *                      AF_INET for IPv4 or AF_INET6 for IPv6.  IPv6 sockets
- *                      may or may not be able to accept IPv4 connections
- *                      based on the system configuration (use
- *                      purple_socket_speaks_ipv4 to check).  If an IPv6
- *                      socket doesn't accept V4-mapped addresses, you will
- *                      need a second listener to support both v4 and v6.
- * @since 2.7.0
- * @deprecated This function will be renamed to purple_network_listen_range
- *             in 3.0.0.
- */
-PurpleNetworkListenData *purple_network_listen_range_family(
+PurpleNetworkListenData *purple_network_listen_range(
 	unsigned short start, unsigned short end, int socket_family,
-	int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data);
+	int socket_type, gboolean map_external,
+	PurpleNetworkListenCallback cb, gpointer cb_data);
 
 /**
  * This can be used to cancel any in-progress listener connection
@@ -267,8 +239,6 @@
  * This is what backs the --force-online command line argument in Pidgin,
  * for example.  This is useful for offline testing, especially when
  * combined with nullprpl.
- *
- * @since 2.6.0
  */
 void purple_network_force_online(void);
 
@@ -284,7 +254,6 @@
  * Will result in a DNS query being executed asynchronous
  *
  * @param stun_server The host name of the STUN server to set
- * @since 2.6.0
  */
 void purple_network_set_stun_server(const gchar *stun_server);
 
@@ -292,7 +261,6 @@
  * Get the IP address of the STUN server as a string representation
  *
  * @return the IP address
- * @since 2.6.0
  */
 const gchar *purple_network_get_stun_ip(void);
 
@@ -301,7 +269,6 @@
  * Will result in a DNS query being executed asynchronous
  *
  * @param turn_server The host name of the TURN server to set
- * @since 2.6.0
  */
 void purple_network_set_turn_server(const gchar *turn_server);
 
@@ -309,7 +276,6 @@
  * Get the IP address of the TURN server as a string representation
  *
  * @return the IP address
- * @since 2.6.0
  */
 const gchar *purple_network_get_turn_ip(void);
 
@@ -317,7 +283,6 @@
  * Remove a port mapping (UPnP or NAT-PMP) associated with listening socket
  *
  * @param fd Socket to remove the port mapping for
- * @since 2.6.0
  */
 void purple_network_remove_port_mapping(gint fd);
 
@@ -336,7 +301,6 @@
  *                The caller is responsible for freeing this.
  * @returns       0 on success, -1 if the out is NULL, or an error code
  *                that currently corresponds to the Idna_rc enum in libidn.
- * @since 2.6.0
  */
 int purple_network_convert_idn_to_ascii(const gchar *in, gchar **out);
 
--- a/libpurple/notify.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/notify.c	Mon Oct 31 01:25:36 2011 +0000
@@ -53,7 +53,17 @@
 
 struct _PurpleNotifyUserInfo
 {
-	GList *user_info_entries;
+	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 *
@@ -363,42 +373,31 @@
 
 	sc = g_new0(PurpleNotifySearchColumn, 1);
 	sc->title = g_strdup(title);
+	sc->visible = TRUE;
 
 	return sc;
 }
 
-guint
-purple_notify_searchresults_get_columns_count(PurpleNotifySearchResults *results)
+const char *purple_notify_searchresult_column_get_title(const PurpleNotifySearchColumn *column)
 {
-	g_return_val_if_fail(results != NULL, 0);
-
-	return g_list_length(results->columns);
-}
-
-guint
-purple_notify_searchresults_get_rows_count(PurpleNotifySearchResults *results)
-{
-	g_return_val_if_fail(results != NULL, 0);
-
-	return g_list_length(results->rows);
+	g_return_val_if_fail(column != NULL, NULL);
+	
+	return column->title;
 }
 
-char *
-purple_notify_searchresults_column_get_title(PurpleNotifySearchResults *results,
-										   unsigned int column_id)
+void purple_notify_searchresult_column_set_visible(PurpleNotifySearchColumn *column, gboolean visible)
 {
-	g_return_val_if_fail(results != NULL, NULL);
+	g_return_if_fail(column != NULL);
 
-	return ((PurpleNotifySearchColumn *)g_list_nth_data(results->columns, column_id))->title;
+	column->visible = visible;
 }
 
-GList *
-purple_notify_searchresults_row_get(PurpleNotifySearchResults *results,
-								  unsigned int row_id)
+gboolean
+purple_notify_searchresult_column_is_visible(const PurpleNotifySearchColumn *column)
 {
-	g_return_val_if_fail(results != NULL, NULL);
+	g_return_val_if_fail(column != NULL, FALSE);
 
-	return g_list_nth_data(results->rows, row_id);
+	return column->visible;
 }
 
 void *
@@ -472,7 +471,7 @@
 
 	user_info = g_new0(PurpleNotifyUserInfo, 1);
 	PURPLE_DBUS_REGISTER_POINTER(user_info, PurpleNotifyUserInfo);
-	user_info->user_info_entries = NULL;
+	g_queue_init(&user_info->entries);
 
 	return user_info;
 }
@@ -482,23 +481,23 @@
 {
 	GList *l;
 
-	for (l = user_info->user_info_entries; l != NULL; l = l->next) {
+	for (l = user_info->entries.head; l != NULL; l = l->next) {
 		PurpleNotifyUserInfoEntry *user_info_entry = l->data;
 
 		purple_notify_user_info_entry_destroy(user_info_entry);
 	}
 
-	g_list_free(user_info->user_info_entries);
+	g_queue_clear(&user_info->entries);
 	PURPLE_DBUS_UNREGISTER_POINTER(user_info);
 	g_free(user_info);
 }
 
-GList *
+GQueue *
 purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info)
 {
 	g_return_val_if_fail(user_info != NULL, NULL);
 
-	return user_info->user_info_entries;
+	return &user_info->entries;
 }
 
 char *
@@ -509,7 +508,7 @@
 
 	text = g_string_new("");
 
-	for (l = user_info->user_info_entries; l != NULL; l = l->next) {
+	for (l = user_info->entries.head; l != NULL; l = l->next) {
 		PurpleNotifyUserInfoEntry *user_info_entry = l->data;
 		/* Add a newline before a section header */
 		if (user_info_entry->type == PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER)
@@ -593,33 +592,41 @@
 }
 
 void
-purple_notify_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value)
+purple_notify_user_info_add_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value)
 {
 	PurpleNotifyUserInfoEntry *entry;
 
 	entry = purple_notify_user_info_entry_new(label, value);
-	user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
+	g_queue_push_tail(&user_info->entries, entry);
 }
 
 void
 purple_notify_user_info_add_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value)
 {
 	gchar *escaped;
-	PurpleNotifyUserInfoEntry *entry;
 
 	escaped = g_markup_escape_text(value, -1);
-	entry = purple_notify_user_info_entry_new(label, escaped);
+	purple_notify_user_info_add_pair_html(user_info, label, escaped);
 	g_free(escaped);
-	user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
 }
 
 void
-purple_notify_user_info_prepend_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value)
+purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value)
 {
 	PurpleNotifyUserInfoEntry *entry;
 
 	entry = purple_notify_user_info_entry_new(label, value);
-	user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry);
+	g_queue_push_head(&user_info->entries, entry);
+}
+
+void
+purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value)
+{
+	gchar *escaped;
+
+	escaped = g_markup_escape_text(value, -1);
+	purple_notify_user_info_prepend_pair_html(user_info, label, escaped);
+	g_free(escaped);
 }
 
 void
@@ -628,7 +635,7 @@
 	g_return_if_fail(user_info != NULL);
 	g_return_if_fail(entry != NULL);
 
-	user_info->user_info_entries = g_list_remove(user_info->user_info_entries, entry);
+	g_queue_remove(&user_info->entries, entry);
 }
 
 void
@@ -639,7 +646,7 @@
 	entry = purple_notify_user_info_entry_new(label, NULL);
 	entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER;
 
-	user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
+	g_queue_push_tail(&user_info->entries, entry);
 }
 
 void
@@ -650,7 +657,7 @@
 	entry = purple_notify_user_info_entry_new(label, NULL);
 	entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER;
 
-	user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry);
+	g_queue_push_head(&user_info->entries, entry);
 }
 
 void
@@ -661,7 +668,7 @@
 	entry = purple_notify_user_info_entry_new(NULL, NULL);
 	entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK;
 
-	user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry);
+	g_queue_push_tail(&user_info->entries, entry);
 }
 
 void
@@ -672,17 +679,17 @@
 	entry = purple_notify_user_info_entry_new(NULL, NULL);
 	entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK;
 
-	user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry);
+	g_queue_push_head(&user_info->entries, entry);
 }
 
 void
 purple_notify_user_info_remove_last_item(PurpleNotifyUserInfo *user_info)
 {
-	GList *last = g_list_last(user_info->user_info_entries);
-	if (last) {
-		purple_notify_user_info_entry_destroy(last->data);
-		user_info->user_info_entries = g_list_delete_link(user_info->user_info_entries, last);
-	}
+	PurpleNotifyUserInfoEntry *entry;
+
+	entry = g_queue_pop_tail(&user_info->entries);
+	if (entry)
+		purple_notify_user_info_entry_destroy(entry);
 }
 
 void *
--- a/libpurple/notify.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/notify.h	Mon Oct 31 01:25:36 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,14 +109,6 @@
 	PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
 } PurpleNotifyUserInfoEntryType;
 
-/**
- * Single column of a search result.
- */
-typedef struct
-{
-	char *title; /**< Title of the column. */
-
-} PurpleNotifySearchColumn;
 
 
 /**
@@ -266,7 +261,8 @@
 PurpleNotifySearchResults *purple_notify_searchresults_new(void);
 
 /**
- * Returns a newly created search result column object.
+ * Returns a newly created search result column object.  The column defaults
+ * to being visible.
  *
  * @param title Title of the column. NOTE: Title will get g_strdup()ed.
  *
@@ -275,6 +271,32 @@
 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.
+ * @param visible TRUE if visible, or FALSE if not.
+ */
+void purple_notify_searchresult_column_set_visible(PurpleNotifySearchColumn *column, gboolean visible);
+
+/**
+ * Returns whether or not a search result column is visible.
+ *
+ * @param column The search column object.
+ *
+ * @return TRUE if the search result column is visible. FALSE otherwise.
+ */
+gboolean purple_notify_searchresult_column_is_visible(const PurpleNotifySearchColumn *column);
+
+/**
  * Adds a new column to the search result object.
  *
  * @param results The result object to which the column will be added.
@@ -292,92 +314,6 @@
 void purple_notify_searchresults_row_add(PurpleNotifySearchResults *results,
 									   GList *row);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_)
-/**
- * Returns a number of the rows in the search results object.
- *
- * @deprecated This function will be removed in Pidgin 3.0.0 unless
- *             there is sufficient demand to keep it.  Using this
- *             function encourages looping through the results
- *             inefficiently.  Instead of using this function you
- *             should iterate through the results using a loop
- *             similar to this:
- *                for (l = results->rows; l != NULL; l = l->next)
- *             If you really need to get the number of rows you
- *             can use g_list_length(results->rows).
- *
- * @param results The search results object.
- *
- * @return Number of the result rows.
- */
-guint purple_notify_searchresults_get_rows_count(PurpleNotifySearchResults *results);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_)
-/**
- * Returns a number of the columns in the search results object.
- *
- * @deprecated This function will be removed in Pidgin 3.0.0 unless
- *             there is sufficient demand to keep it.  Using this
- *             function encourages looping through the columns
- *             inefficiently.  Instead of using this function you
- *             should iterate through the columns using a loop
- *             similar to this:
- *                for (l = results->columns; l != NULL; l = l->next)
- *             If you really need to get the number of columns you
- *             can use g_list_length(results->columns).
- *
- * @param results The search results object.
- *
- * @return Number of the columns.
- */
-guint purple_notify_searchresults_get_columns_count(PurpleNotifySearchResults *results);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_)
-/**
- * Returns a row of the results from the search results object.
- *
- * @deprecated This function will be removed in Pidgin 3.0.0 unless
- *             there is sufficient demand to keep it.  Using this
- *             function encourages looping through the results
- *             inefficiently.  Instead of using this function you
- *             should iterate through the results using a loop
- *             similar to this:
- *                for (l = results->rows; l != NULL; l = l->next)
- *             If you really need to get the data for a particular
- *             row you can use g_list_nth_data(results->rows, row_id).
- *
- * @param results The search results object.
- * @param row_id  Index of the row to be returned.
- *
- * @return Row of the results.
- */
-GList *purple_notify_searchresults_row_get(PurpleNotifySearchResults *results,
-										 unsigned int row_id);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_)
-/**
- * Returns a title of the search results object's column.
- *
- * @deprecated This function will be removed in Pidgin 3.0.0 unless
- *             there is sufficient demand to keep it.  Using this
- *             function encourages looping through the columns
- *             inefficiently.  Instead of using this function you
- *             should iterate through the name of a particular
- *             column you can use
- *             g_list_nth_data(results->columns, row_id).
- *
- * @param results   The search results object.
- * @param column_id Index of the column.
- *
- * @return Title of the column.
- */
-char *purple_notify_searchresults_column_get_title(PurpleNotifySearchResults *results,
-												 unsigned int column_id);
-#endif
-
 /*@}*/
 
 /**************************************************************************/
@@ -506,20 +442,20 @@
  * Retrieve the array of PurpleNotifyUserInfoEntry objects from a
  * PurpleNotifyUserInfo
  *
- * This GList may be manipulated directly with normal GList functions such
- * as g_list_insert(). Only PurpleNotifyUserInfoEntry are allowed in the
- * list.  If a PurpleNotifyUserInfoEntry item is added to the list, it
- * should not be g_free()'d by the caller; PurpleNotifyUserInfo will g_free
- * it when destroyed.
+ * This GQueue may be manipulated directly with normal GQueue functions such
+ * as g_queue_push_tail(). Only PurpleNotifyUserInfoEntry are allowed in the
+ * queue.  If a PurpleNotifyUserInfoEntry item is added to the queue, it
+ * should not be freed by the caller; PurpleNotifyUserInfo will free it when
+ * destroyed.
  *
  * To remove a PurpleNotifyUserInfoEntry, use
- * purple_notify_user_info_remove_entry(). Do not use the GList directly.
+ * purple_notify_user_info_remove_entry(). Do not use the GQueue directly.
  *
  * @param user_info  The PurpleNotifyUserInfo
  *
- * @constreturn A GList of PurpleNotifyUserInfoEntry objects
+ * @constreturn A GQueue of PurpleNotifyUserInfoEntry objects.
  */
-GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info);
+GQueue *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info);
 
 /**
  * Create a textual representation of a PurpleNotifyUserInfo, separating
@@ -547,34 +483,25 @@
  *                   the UI should treat label as independent and not
  *                   include a colon if it would otherwise.
  */
-/*
- * TODO: In 3.0.0 this function should be renamed to
- *       purple_notify_user_info_add_pair_html().  And optionally
- *       purple_notify_user_info_add_pair_plaintext() could be renamed to
- *       purple_notify_user_info_add_pair().
- */
-void purple_notify_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value);
+void purple_notify_user_info_add_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value);
 
 /**
- * Like purple_notify_user_info_add_pair, but value should be plaintext
+ * Like purple_notify_user_info_add_pair_html, but value should be plaintext
  * and will be escaped using g_markup_escape_text().
  */
 void purple_notify_user_info_add_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value);
 
 /**
- * Prepend a label/value pair to a PurpleNotifyUserInfo object
- *
- * @param user_info  The PurpleNotifyUserInfo
- * @param label      A label, which for example might be displayed by a
- *                   UI with a colon after it ("Status:"). Do not include
- *                   a colon.  If NULL, value will be displayed without a
- *                   label.
- * @param value      The value, which might be displayed by a UI after
- *                   the label.  If NULL, label will still be displayed;
- *                   the UI should then treat label as independent and not
- *                   include a colon if it would otherwise.
+ * Like purple_notify_user_info_add_pair_html, but the pair is inserted
+ * at the beginning of the list.
  */
-void purple_notify_user_info_prepend_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value);
+void purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value);
+
+/**
+ * Like purple_notify_user_info_prepend_pair_html, but value should be plaintext
+ * and will be escaped using g_markup_escape_text().
+ */
+void purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value);
 
 #if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_)
 /**
@@ -597,9 +524,11 @@
  *
  * If added to a PurpleNotifyUserInfo object, this should not be free()'d,
  * as PurpleNotifyUserInfo will do so when destroyed.
- * purple_notify_user_info_add_pair() and
- * purple_notify_user_info_prepend_pair() are convenience methods for
- * creating entries and adding them to a PurpleNotifyUserInfo.
+ * purple_notify_user_info_add_pair_html(),
+ * purple_notify_user_info_add_pair_plaintext(),
+ * purple_notify_user_info_prepend_pair_html() and
+ * purple_notify_user_info_prepend_pair_plaintext() are convenience
+ * methods for creating entries and adding them to a PurpleNotifyUserInfo.
  *
  * @param label  A label, which for example might be displayed by a UI
  *               with a colon after it ("Status:"). Do not include a
@@ -624,7 +553,6 @@
  * Prepend a section break.  A UI might display this as a horizontal line.
  *
  * @param user_info  The PurpleNotifyUserInfo
- * @since 2.5.0
  */
 void purple_notify_user_info_prepend_section_break(PurpleNotifyUserInfo *user_info);
 
@@ -643,7 +571,6 @@
  *
  * @param user_info  The PurpleNotifyUserInfo
  * @param label      The name of the section
- * @since 2.5.0
  */
 void purple_notify_user_info_prepend_section_header(PurpleNotifyUserInfo *user_info, const char *label);
 
--- a/libpurple/plugin.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugin.c	Mon Oct 31 01:25:36 2011 +0000
@@ -64,13 +64,6 @@
 static GList *plugins_to_disable = NULL;
 #endif
 
-static void (*probe_cb)(void *) = NULL;
-static void *probe_cb_data = NULL;
-static void (*load_cb)(PurplePlugin *, void *) = NULL;
-static void *load_cb_data = NULL;
-static void (*unload_cb)(PurplePlugin *, void *) = NULL;
-static void *unload_cb_data = NULL;
-
 #ifdef PURPLE_PLUGINS
 
 static gboolean
@@ -615,9 +608,6 @@
 
 	plugin->loaded = TRUE;
 
-	if (load_cb != NULL)
-		load_cb(plugin, load_cb_data);
-
 	purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
 
 	return TRUE;
@@ -745,9 +735,6 @@
 	g_free(plugin->error);
 	plugin->error = NULL;
 
-	if (unload_cb != NULL)
-		unload_cb(plugin, unload_cb_data);
-
 	purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin);
 
 	purple_prefs_disconnect_by_handle(plugin);
@@ -1439,10 +1426,6 @@
 													(GCompareFunc)compare_prpl);
 		}
 	}
-
-	if (probe_cb != NULL)
-		probe_cb(probe_cb_data);
-
 #endif /* PURPLE_PLUGINS */
 }
 
@@ -1513,50 +1496,6 @@
 #endif
 }
 
-void
-purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data)
-{
-	probe_cb = func;
-	probe_cb_data = data;
-}
-
-void
-purple_plugins_unregister_probe_notify_cb(void (*func)(void *))
-{
-	probe_cb = NULL;
-	probe_cb_data = NULL;
-}
-
-void
-purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *),
-									 void *data)
-{
-	load_cb = func;
-	load_cb_data = data;
-}
-
-void
-purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *))
-{
-	load_cb = NULL;
-	load_cb_data = NULL;
-}
-
-void
-purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *),
-									   void *data)
-{
-	unload_cb = func;
-	unload_cb_data = data;
-}
-
-void
-purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *))
-{
-	unload_cb = NULL;
-	unload_cb_data = NULL;
-}
-
 PurplePlugin *
 purple_plugins_find_with_name(const char *name)
 {
--- a/libpurple/plugin.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugin.h	Mon Oct 31 01:25:36 2011 +0000
@@ -317,8 +317,6 @@
  * startup" by excluding said plugins from the list of plugins to save.  The
  * UI needs to call purple_plugins_save_loaded() after calling this for it
  * to have any effect.
- *
- * @since 2.3.0
  */
 void purple_plugin_disable(PurplePlugin *plugin);
 
@@ -515,8 +513,6 @@
  * Returns a list of plugin search paths.
  *
  * @constreturn A list of searched paths.
- *
- * @since 2.6.0
  */
 GList *purple_plugins_get_search_paths(void);
 
@@ -566,72 +562,6 @@
  */
 gboolean purple_plugins_enabled(void);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_)
-/**
- * Registers a function that will be called when probing is finished.
- *
- * @param func The callback function.
- * @param data Data to pass to the callback.
- * @deprecated If you need this, ask for a plugin-probe signal to be added.
- */
-void purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_)
-/**
- * Unregisters a function that would be called when probing is finished.
- *
- * @param func The callback function.
- * @deprecated If you need this, ask for a plugin-probe signal to be added.
- */
-void purple_plugins_unregister_probe_notify_cb(void (*func)(void *));
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_)
-/**
- * Registers a function that will be called when a plugin is loaded.
- *
- * @param func The callback function.
- * @param data Data to pass to the callback.
- * @deprecated Use the plugin-load signal instead.
- */
-void purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *),
-										  void *data);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_)
-/**
- * Unregisters a function that would be called when a plugin is loaded.
- *
- * @param func The callback function.
- * @deprecated Use the plugin-load signal instead.
- */
-void purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *));
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_)
-/**
- * Registers a function that will be called when a plugin is unloaded.
- *
- * @param func The callback function.
- * @param data Data to pass to the callback.
- * @deprecated Use the plugin-unload signal instead.
- */
-void purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *),
-											void *data);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_)
-/**
- * Unregisters a function that would be called when a plugin is unloaded.
- *
- * @param func The callback function.
- * @deprecated Use the plugin-unload signal instead.
- */
-void purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *,
-														   void *));
-#endif
-
 /**
  * Finds a plugin with the specified name.
  *
--- a/libpurple/plugins/autoaccept.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/autoaccept.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/log_reader.c	Mon Oct 31 01:25:36 2011 +0000
@@ -92,7 +92,7 @@
 
 	prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1);
 
-	temp = g_strdup_printf("%s.%s", prpl_name, account->username);
+	temp = g_strdup_printf("%s.%s", prpl_name, purple_account_get_username(account));
 	path = g_build_filename(logdir, temp, sn, NULL);
 	g_free(temp);
 
@@ -635,7 +635,7 @@
 	g_return_val_if_fail(sn != NULL, NULL);
 	g_return_val_if_fail(account != NULL, NULL);
 
-	if (strcmp(account->protocol_id, "prpl-msn"))
+	if (strcmp(purple_account_get_protocol_id(account), "prpl-msn"))
 		return NULL;
 
 	logdir = purple_prefs_get_string("/plugins/core/log_reader/msn/log_directory");
@@ -658,7 +658,7 @@
 			return list;
 		}
 	} else {
-		username = g_strdup(purple_normalize(account, account->username));
+		username = g_strdup(purple_normalize(account, purple_account_get_username(account)));
 	}
 
 	if (buddy) {
@@ -974,7 +974,7 @@
 
 		their_name = from_name;
 		if (from_name && purple_prefs_get_bool("/plugins/core/log_reader/use_name_heuristics")) {
-			const char *friendly_name = purple_connection_get_display_name(log->account->gc);
+			const char *friendly_name = purple_connection_get_display_name(purple_account_get_connection(log->account));
 
 			if (friendly_name != NULL) {
 				int friendly_name_length = strlen(friendly_name);
@@ -987,13 +987,10 @@
 				if (buddy)
 					their_name = purple_buddy_get_alias(buddy);
 
-				if (log->account->alias)
-				{
-					alias = log->account->alias;
+				alias = purple_account_get_alias(log->account);
+				if (alias) {
 					alias_length = strlen(alias);
-				}
-				else
-				{
+				} else {
 					alias = "";
 					alias_length = 0;
 				}
@@ -1115,10 +1112,10 @@
 			text = g_string_append(text, "<b>");
 
 			if (name_guessed == NAME_GUESS_ME) {
-				if (log->account->alias)
-					text = g_string_append(text, log->account->alias);
+				if (purple_account_get_alias(log->account))
+					text = g_string_append(text, purple_account_get_alias(log->account));
 				else
-					text = g_string_append(text, log->account->username);
+					text = g_string_append(text, purple_account_get_username(log->account));
 			}
 			else if (name_guessed == NAME_GUESS_THEM)
 				text = g_string_append(text, their_name);
@@ -1781,7 +1778,7 @@
 	g_return_val_if_fail(account != NULL, NULL);
 
 	/* QIP only supports ICQ. */
-	if (strcmp(account->protocol_id, "prpl-icq"))
+	if (strcmp(purple_account_get_protocol_id(account), "prpl-icq"))
 		return NULL;
 
 	logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory");
@@ -1798,7 +1795,7 @@
 	if (!prpl_info->list_icon)
 		return NULL;
 
-	username = g_strdup(purple_normalize(account, account->username));
+	username = g_strdup(purple_normalize(account, purple_account_get_username(account)));
 	filename = g_strdup_printf("%s.txt", purple_normalize(account, sn));
 	path = g_build_filename(logdir, username, "History", filename, NULL);
 	g_free(username);
@@ -2241,10 +2238,10 @@
 		return NULL;
 
 	/* aMSN only works with MSN/WLM */
-	if (strcmp(account->protocol_id, "prpl-msn"))
+	if (strcmp(purple_account_get_protocol_id(account), "prpl-msn"))
 		return NULL;
 
-	username = g_strdup(purple_normalize(account, account->username));
+	username = g_strdup(purple_normalize(account, purple_account_get_username(account)));
 	buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn));
 	log_path = g_build_filename(logdir, username, "logs", NULL);
 
--- a/libpurple/plugins/perl/common/Account.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Account.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -199,9 +199,10 @@
     Purple::Account account
 
 void
-purple_account_add_buddies(account, list)
+purple_account_add_buddies(account, list, message)
     Purple::Account account
     SV * list
+    const char *message
 PREINIT:
     GList *t_GL;
     int i, t_len;
@@ -212,13 +213,14 @@
     for (i = 0; i <= t_len; i++)
         t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(list), i, 0)));
 
-    purple_account_add_buddies(account, t_GL);
+    purple_account_add_buddies(account, t_GL, message);
     g_list_free(t_GL);
 
 void
-purple_account_add_buddy(account, buddy)
-    Purple::Account account
-    Purple::BuddyList::Buddy  buddy
+purple_account_add_buddy(account, buddy, message)
+    Purple::Account          account
+    Purple::BuddyList::Buddy buddy
+    const char *             message
 
 void
 purple_account_change_password(account, a, b)
--- a/libpurple/plugins/perl/common/BuddyList.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/BuddyList.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -82,11 +82,6 @@
 purple_contact_get_priority_buddy(contact)
 	Purple::BuddyList::Contact contact
 
-void
-purple_contact_set_alias(contact, alias)
-	Purple::BuddyList::Contact contact
-	const char * alias
-
 const char *
 purple_contact_get_alias(contact)
 	Purple::BuddyList::Contact contact
@@ -200,10 +195,6 @@
 	Purple::Status old_status
 
 void
-purple_blist_update_buddy_icon(buddy)
-	Purple::BuddyList::Buddy buddy
-
-void
 purple_blist_rename_buddy(buddy, name)
 	Purple::BuddyList::Buddy buddy
 	const char * name
@@ -430,9 +421,5 @@
 	Purple::BuddyList::Buddy buddy
 
 const char *
-purple_buddy_get_local_alias(buddy)
-	Purple::BuddyList::Buddy buddy
-
-const char *
 purple_buddy_get_alias(buddy)
 	Purple::BuddyList::Buddy buddy
--- a/libpurple/plugins/perl/common/Certificate.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Certificate.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -202,7 +202,7 @@
 			l = g_list_prepend(l, purple_perl_ref_object(ST(i)));
 		}
 		l = g_list_reverse(l);
-		ret = purple_certificate_check_signature_chain(l);
+		ret = purple_certificate_check_signature_chain(l, NULL);
 		g_list_free(l);
 		if(ret) XSRETURN_YES;
 		XSRETURN_NO;
--- a/libpurple/plugins/perl/common/Connection.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Connection.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -36,15 +36,6 @@
 	const char *text
 
 void
-purple_connection_error(gc, reason)
-	Purple::Connection gc
-	const char *reason
-
-void
-purple_connection_destroy(gc)
-	Purple::Connection gc
-
-void
 purple_connection_set_state(gc, state)
 	Purple::Connection gc
 	Purple::ConnectionState state
--- a/libpurple/plugins/perl/common/Conversation.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Conversation.xs	Mon Oct 31 01:25:36 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
@@ -338,24 +338,6 @@
 	Purple::Conversation::Chat chat
 
 void
-purple_conv_chat_set_users(chat, users)
-	Purple::Conversation::Chat chat
-	SV * users
-PREINIT:
-	GList *l, *t_GL;
-	int i, t_len;
-PPCODE:
-	t_GL = NULL;
-	t_len = av_len((AV *)SvRV(users));
-
-	for (i = 0; i <= t_len; i++)
-		t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(users), i, 0)));
-
-	for (l = purple_conv_chat_set_users(chat, t_GL); l != NULL; l = l->next) {
-		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
-	}
-
-void
 purple_conv_chat_get_users(chat)
 	Purple::Conversation::Chat chat
 PREINIT:
--- a/libpurple/plugins/perl/common/FT.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/FT.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -113,7 +113,7 @@
 	Purple::Xfer xfer
 
 gboolean 
-purple_xfer_is_canceled(xfer)
+purple_xfer_is_cancelled(xfer)
 	Purple::Xfer xfer
 
 gboolean 
--- a/libpurple/plugins/perl/common/Network.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Network.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -23,17 +23,21 @@
 	const char *ip
 
 Purple::NetworkListenData
-purple_network_listen(port, socket_type, cb, cb_data)
+purple_network_listen(port, socket_family, socket_type, map_external, cb, cb_data)
 	unsigned short port
+	int socket_family
 	int socket_type
+	gboolean map_external
 	Purple::NetworkListenCallback cb
 	gpointer cb_data
 
 Purple::NetworkListenData
-purple_network_listen_range(start, end, socket_type, cb, cb_data)
+purple_network_listen_range(start, end, socket_family, socket_type, map_external, cb, cb_data)
 	unsigned short start
 	unsigned short end
+	int socket_family
 	int socket_type
+	gboolean map_external
 	Purple::NetworkListenCallback cb
 	gpointer cb_data
 
--- a/libpurple/plugins/perl/common/Notify.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Notify.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -135,7 +135,7 @@
 PREINIT:
 	GList *l;
 PPCODE:
-	l = purple_notify_user_info_get_entries(user_info);
+	l = purple_notify_user_info_get_entries(user_info)->head;
 	for (; l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::NotifyUserInfoEntry")));
 	}
@@ -145,12 +145,12 @@
 	Purple::NotifyUserInfo user_info
 	const char *newline
 
-void purple_notify_user_info_add_pair(user_info, label, value)
+void purple_notify_user_info_add_pair_html(user_info, label, value)
 	Purple::NotifyUserInfo user_info
 	const char *label
 	const char *value
 
-void purple_notify_user_info_prepend_pair(user_info, label, value)
+void purple_notify_user_info_prepend_pair_html(user_info, label, value)
 	Purple::NotifyUserInfo user_info
 	const char *label
 	const char *value
--- a/libpurple/plugins/perl/common/Request.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Request.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -374,12 +374,6 @@
 	C_ARGS: id, text
 
 void
-purple_request_field_list_add(field, item, data)
-	Purple::Request::Field field
-	const char *item
-	void * data
-
-void
 purple_request_field_list_add_icon(field, item, icon_path, data)
 	Purple::Request::Field field
 	const char *item
--- a/libpurple/plugins/perl/common/SSLConn.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/SSLConn.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -16,13 +16,6 @@
 	Purple::Ssl::Connection gsc
 	Purple::SslInputFunction func
 
-Purple::Ssl::Connection
-purple_ssl_connect_fd(account, fd, func, error_func, data)
-	Purple::Account account
-	int fd
-	PurpleSslInputFunction func
-	PurpleSslErrorFunction error_func
-
 */
 
 MODULE = Purple::SSL  PACKAGE = Purple::SSL   PREFIX = purple_ssl_
--- a/libpurple/plugins/perl/common/Status.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Status.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -74,28 +74,6 @@
 		newCONSTSUB(primitive_stash, (char *)civ->name, newSViv(civ->iv));
 }
 
-void
-purple_presence_add_list(presence, source_list)
-	Purple::Presence presence
-	SV *source_list
-PREINIT:
-	GList *t_GL;
-	int i, t_len;
-PPCODE:
-	t_GL = NULL;
-	t_len = av_len((AV *)SvRV(source_list));
-
-	for (i = 0; i <= t_len; i++) {
-		t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(source_list), i, 0)));
-	}
-	purple_presence_add_list(presence, t_GL);
-	g_list_free(t_GL);
-
-void
-purple_presence_add_status(presence, status)
-	Purple::Presence presence
-	Purple::Status status
-
 gint
 purple_presence_compare(presence1, presence2)
 	Purple::Presence presence1
@@ -329,29 +307,10 @@
 	Purple::Status status
 	gboolean active
 
-void
-purple_status_set_attr_boolean(status, id, value)
-	Purple::Status status
-	const char *id
-	gboolean value
-
-void
-purple_status_set_attr_string(status, id, value)
-	Purple::Status status
-	const char *id
-	const char *value
-
 MODULE = Purple::Status  PACKAGE = Purple::StatusType  PREFIX = purple_status_type_
 PROTOTYPES: ENABLE
 
 void
-purple_status_type_add_attr(status_type, id, name, value)
-	Purple::StatusType status_type
-	const char *id
-	const char *name
-	Purple::Value value
-
-void
 purple_status_type_destroy(status_type)
 	Purple::StatusType status_type
 
@@ -397,10 +356,6 @@
 purple_status_type_get_name(status_type)
 	Purple::StatusType status_type
 
-const char *
-purple_status_type_get_primary_attr(status_type)
-	Purple::StatusType status_type
-
 Purple::StatusPrimitive
 purple_status_type_get_primitive(status_type)
 	Purple::StatusType status_type
@@ -440,8 +395,3 @@
 	gboolean saveable
 	gboolean user_settable
 	gboolean independent
-
-void
-purple_status_type_set_primary_attr(status_type, attr_id)
-	Purple::StatusType status_type
-	const char *attr_id
--- a/libpurple/plugins/perl/common/Util.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/perl/common/Util.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -202,6 +202,14 @@
 purple_ip_address_is_valid(ip)
 	const char* ip
 
+gboolean
+purple_ipv4_address_is_valid(ip)
+	const char* ip
+
+gboolean
+purple_ipv6_address_is_valid(ip)
+	const char* ip
+
 const char*
 purple_normalize_nocase(account, str)
 	Purple::Account account
@@ -454,12 +462,13 @@
 
  #XXX: expand...
 void
-purple_util_fetch_url(plugin, url, full, user_agent, http11, cb)
+purple_util_fetch_url(plugin, url, full, user_agent, http11, max_len, cb)
 	Purple::Plugin plugin
 	const char *url
 	gboolean full
 	const char *user_agent
 	gboolean http11
+	gssize max_len
 	SV * cb
 PREINIT:
 	PurpleUtilFetchUrlData *data;
@@ -468,7 +477,7 @@
 	SV *sv = purple_perl_sv_from_fun(plugin, cb);
 
 	if (sv != NULL) {
-		data = purple_util_fetch_url(url, full, user_agent, http11,
+		data = purple_util_fetch_url(url, full, user_agent, http11, max_len,
 		                      purple_perl_util_url_cb, sv);
 		XPUSHs(sv_2mortal(purple_perl_bless_object(data, "Purple::Util::FetchUrlData")));
 	} else {
--- a/libpurple/plugins/statenotify.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/statenotify.c	Mon Oct 31 01:25:36 2011 +0000
@@ -30,7 +30,7 @@
 
 	if (conv == NULL)
 		return;
-	g_return_if_fail(conv->type == PURPLE_CONV_TYPE_IM);
+	g_return_if_fail(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM);
 
 	/* Prevent duplicate notifications for buddies in multiple groups */
 	if (buddy != purple_find_buddy(account, buddy_name))
@@ -42,7 +42,7 @@
 	g_snprintf(buf, sizeof(buf), message, escaped);
 	g_free(escaped);
 
-	purple_conv_im_write(conv->u.im, NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY, time(NULL));
+	purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY, time(NULL));
 }
 
 static void
--- a/libpurple/plugins/tcl/tcl_cmds.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/plugins/tcl/tcl_cmds.c	Mon Oct 31 01:25:36 2011 +0000
@@ -1640,13 +1640,13 @@
 int tcl_cmd_status_type(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
 {
 	const char *cmds[] = { "attr", "attrs", "available", "exclusive", "id",
-	                       "independent", "name", "primary_attr",
+	                       "independent", "name",
 	                       "primitive", "saveable", "user_settable",
 	                       NULL };
 	enum { CMD_STATUS_TYPE_ATTR, CMD_STATUS_TYPE_ATTRS,
 	       CMD_STATUS_TYPE_AVAILABLE, CMD_STATUS_TYPE_EXCLUSIVE,
 	       CMD_STATUS_TYPE_ID, CMD_STATUS_TYPE_INDEPENDENT,
-	       CMD_STATUS_TYPE_NAME, CMD_STATUS_TYPE_PRIMARY_ATTR,
+	       CMD_STATUS_TYPE_NAME,
 	       CMD_STATUS_TYPE_PRIMITIVE, CMD_STATUS_TYPE_SAVEABLE,
 	       CMD_STATUS_TYPE_USER_SETTABLE } cmd;
 	PurpleStatusType *status_type;
@@ -1751,18 +1751,6 @@
 				 Tcl_NewStringObj(purple_primitive_get_id_from_type
 						  (purple_status_type_get_primitive(status_type)), -1));
 		break;
-	case CMD_STATUS_TYPE_PRIMARY_ATTR:
-#if !(defined PURPLE_DISABLE_DEPRECATED)
-		if (objc != 3) {
-			Tcl_WrongNumArgs(interp, 2, objv, "statustype");
-			return TCL_ERROR;
-		}
-		if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL)
-			return TCL_ERROR;
-		Tcl_SetObjResult(interp,
-				 Tcl_NewStringObj(purple_status_type_get_primary_attr(status_type), -1));
-#endif
-		break;
 	case CMD_STATUS_TYPE_SAVEABLE:
 		if (objc != 3) {
 			Tcl_WrongNumArgs(interp, 2, objv, "statustype");
--- a/libpurple/pounce.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/pounce.c	Mon Oct 31 01:25:36 2011 +0000
@@ -32,6 +32,31 @@
 #include "pounce.h"
 #include "util.h"
 
+/**
+ * A buddy pounce structure.
+ *
+ * Buddy pounces are actions triggered by a buddy-related event. For
+ * example, a sound can be played or an IM window opened when a buddy
+ * signs on or returns from away. Such responses are handled in the
+ * UI. The events themselves are done in the core.
+ */
+struct _PurplePounce
+{
+	char *ui_type;                /**< The type of UI.            */
+
+	PurplePounceEvent events;       /**< The event(s) to pounce on. */
+	PurplePounceOption options;     /**< The pounce options         */
+	PurpleAccount *pouncer;         /**< The user who is pouncing.  */
+
+	char *pouncee;                /**< The buddy to pounce on.    */
+
+	GHashTable *actions;          /**< The registered actions.    */
+
+	gboolean save;                /**< Whether or not the pounce should
+	                                   be saved after activation. */
+	void *data;                   /**< Pounce-specific data.      */
+};
+
 typedef struct
 {
 	GString *buffer;
@@ -180,7 +205,7 @@
 	xmlnode_set_attrib(node, "ui", pounce->ui_type);
 
 	child = xmlnode_new_child(node, "account");
-	xmlnode_set_attrib(child, "protocol", pouncer->protocol_id);
+	xmlnode_set_attrib(child, "protocol", purple_account_get_protocol_id(pouncer));
 	xmlnode_insert_data(child,
 			purple_normalize(pouncer, purple_account_get_username(pouncer)), -1);
 
@@ -405,12 +430,8 @@
 	}
 
 	if (purple_strequal(element_name, "account")) {
-		char *tmp;
 		g_free(data->account_name);
 		data->account_name = g_strdup(buffer);
-		tmp = data->protocol_id;
-		data->protocol_id = g_strdup(_purple_oscar_convert(buffer, tmp));
-		g_free(tmp);
 	}
 	else if (purple_strequal(element_name, "pouncee")) {
 		g_free(data->pouncee);
--- a/libpurple/pounce.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/pounce.h	Mon Oct 31 01:25:36 2011 +0000
@@ -59,31 +59,6 @@
 /** A pounce callback. */
 typedef void (*PurplePounceCb)(PurplePounce *, PurplePounceEvent, void *);
 
-/**
- * A buddy pounce structure.
- *
- * Buddy pounces are actions triggered by a buddy-related event. For
- * example, a sound can be played or an IM window opened when a buddy
- * signs on or returns from away. Such responses are handled in the
- * UI. The events themselves are done in the core.
- */
-struct _PurplePounce
-{
-	char *ui_type;                /**< The type of UI.            */
-
-	PurplePounceEvent events;       /**< The event(s) to pounce on. */
-	PurplePounceOption options;     /**< The pounce options         */
-	PurpleAccount *pouncer;         /**< The user who is pouncing.  */
-
-	char *pouncee;                /**< The buddy to pounce on.    */
-
-	GHashTable *actions;          /**< The registered actions.    */
-
-	gboolean save;                /**< Whether or not the pounce should
-	                                   be saved after activation. */
-	void *data;                   /**< Pounce-specific data.      */
-};
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -126,8 +101,6 @@
  * Destroys all buddy pounces for a buddy
  *
  * @param buddy The buddy whose pounces are to be removed
- *
- * @since 2.8.0
  */
 void purple_pounce_destroy_all_by_buddy(PurpleBuddy *buddy);
 
@@ -359,7 +332,6 @@
  *
  * @return The list of buddy pounces. The list should be freed by
  *         the caller when it's no longer used.
- * @since  2.1.0
  */
 GList *purple_pounces_get_all_for_ui(const char *ui);
 
--- a/libpurple/prefs.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/prefs.h	Mon Oct 31 01:25:36 2011 +0000
@@ -32,7 +32,7 @@
 /**
  * Preference data types.
  */
-typedef enum _PurplePrefType
+typedef enum
 {
 	PURPLE_PREF_NONE,        /**< No type.         */
 	PURPLE_PREF_BOOLEAN,     /**< Boolean.         */
@@ -317,8 +317,6 @@
  * @return A list of newly allocated strings denoting the names of the children.
  *         Returns @c NULL if there are no children or if pref doesn't exist.
  *         The caller must free all the strings and the list.
- *
- * @since 2.1.0
  */
 GList *purple_prefs_get_children_names(const char *name);
 
--- a/libpurple/privacy.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/privacy.c	Mon Oct 31 01:25:36 2011 +0000
@@ -264,9 +264,9 @@
 						gboolean restore)
 {
 	GSList *list;
-	PurplePrivacyType type = account->perm_deny;
+	PurplePrivacyType type = purple_account_get_privacy_type(account);
 
-	switch (account->perm_deny) {
+	switch (type) {
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			return;
 		case PURPLE_PRIVACY_ALLOW_USERS:
@@ -287,13 +287,13 @@
 				}
 			}
 			purple_privacy_permit_add(account, who, local);
-			account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
+			purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS);
 			break;
 		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
 			if (!purple_find_buddy(account, who)) {
 				add_all_buddies_to_permit_list(account, local);
 				purple_privacy_permit_add(account, who, local);
-				account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
+				purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS);
 			}
 			break;
 		default:
@@ -301,7 +301,7 @@
 	}
 
 	/* Notify the server if the privacy setting was changed */
-	if (type != account->perm_deny && purple_account_is_connected(account))
+	if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account))
 		serv_set_permit_deny(purple_account_get_connection(account));
 }
 
@@ -316,9 +316,9 @@
 					gboolean restore)
 {
 	GSList *list;
-	PurplePrivacyType type = account->perm_deny;
+	PurplePrivacyType type = purple_account_get_privacy_type(account);
 
-	switch (account->perm_deny) {
+	switch (type) {
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			if (!restore) {
 				/* Empty the deny-list. */
@@ -331,7 +331,7 @@
 				}
 			}
 			purple_privacy_deny_add(account, who, local);
-			account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+			purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
 			break;
 		case PURPLE_PRIVACY_ALLOW_USERS:
 			purple_privacy_permit_remove(account, who, local);
@@ -345,7 +345,7 @@
 			if (purple_find_buddy(account, who)) {
 				add_all_buddies_to_permit_list(account, local);
 				purple_privacy_permit_remove(account, who, local);
-				account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
+				purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS);
 			}
 			break;
 		default:
@@ -353,7 +353,7 @@
 	}
 
 	/* Notify the server if the privacy setting was changed */
-	if (type != account->perm_deny && purple_account_is_connected(account))
+	if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account))
 		serv_set_permit_deny(purple_account_get_connection(account));
 }
 
@@ -362,7 +362,7 @@
 {
 	GSList *list;
 
-	switch (account->perm_deny) {
+	switch (purple_account_get_privacy_type(account)) {
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			return TRUE;
 
--- a/libpurple/privacy.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/privacy.h	Mon Oct 31 01:25:36 2011 +0000
@@ -29,7 +29,7 @@
 /**
  * Privacy data types.
  */
-typedef enum _PurplePrivacyType
+typedef enum
 {
 	PURPLE_PRIVACY_ALLOW_ALL = 1,
 	PURPLE_PRIVACY_DENY_ALL,
--- a/libpurple/protocols/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/Makefile.am	Mon Oct 31 01:25:36 2011 +0000
@@ -1,5 +1,5 @@
 EXTRA_DIST = Makefile.mingw
 
-DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr
+DIST_SUBDIRS = bonjour gg irc jabber msn mxit myspace novell null oscar sametime silc simple yahoo zephyr
 
 SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
--- a/libpurple/protocols/bonjour/bonjour.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Mon Oct 31 01:25:36 2011 +0000
@@ -51,7 +51,7 @@
 bonjour_get_jid(PurpleAccount *account)
 {
 	PurpleConnection *conn = purple_account_get_connection(account);
-	BonjourData *bd = conn->proto_data;
+	BonjourData *bd = purple_connection_get_protocol_data(conn);
 	return bd->jid;
 }
 
@@ -94,7 +94,7 @@
 
 #ifdef _WIN32
 	if (!dns_sd_available()) {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				_("Unable to find Apple's \"Bonjour for Windows\" toolkit, see "
 				  "http://d.pidgin.im/BonjourWindows for more information."));
@@ -102,8 +102,9 @@
 	}
 #endif /* _WIN32 */
 
-	gc->flags |= PURPLE_CONNECTION_HTML;
-	gc->proto_data = bd = g_new0(BonjourData, 1);
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML);
+	bd = g_new0(BonjourData, 1);
+	purple_connection_set_protocol_data(gc, bd);
 
 	/* Start waiting for jabber connections (iChat style) */
 	bd->jabber_data = g_new0(BonjourJabber, 1);
@@ -114,7 +115,7 @@
 
 	if (bonjour_jabber_start(bd->jabber_data) == -1) {
 		/* Send a message about the connection error */
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to listen for incoming IM connections"));
 		return;
@@ -141,7 +142,7 @@
 	bd->dns_sd_data->account = account;
 	if (!bonjour_dns_sd_start(bd->dns_sd_data))
 	{
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to establish connection with the local mDNS server.  Is it running?"));
 		return;
@@ -157,7 +158,7 @@
 bonjour_close(PurpleConnection *connection)
 {
 	PurpleGroup *bonjour_group;
-	BonjourData *bd = connection->proto_data;
+	BonjourData *bd = purple_connection_get_protocol_data(connection);
 
 	bonjour_group = purple_find_group(BONJOUR_GROUP_NAME);
 
@@ -192,7 +193,7 @@
 	if (bd != NULL)
 		g_free(bd->jid);
 	g_free(bd);
-	connection->proto_data = NULL;
+	purple_connection_set_protocol_data(connection, NULL);
 }
 
 static const char *
@@ -204,10 +205,12 @@
 static int
 bonjour_send_im(PurpleConnection *connection, const char *to, const char *msg, PurpleMessageFlags flags)
 {
+	BonjourData *bd = purple_connection_get_protocol_data(connection);
+
 	if(!to || !msg)
 		return 0;
 
-	return bonjour_jabber_send_message(((BonjourData*)(connection->proto_data))->jabber_data, to, msg);
+	return bonjour_jabber_send_message(bd->jabber_data, to, msg);
 }
 
 static void
@@ -220,7 +223,7 @@
 	gchar *stripped;
 
 	gc = purple_account_get_connection(account);
-	bd = gc->proto_data;
+	bd = purple_connection_get_protocol_data(gc);
 	presence = purple_account_get_presence(account);
 
 	message = purple_status_get_attr_string(status, "message");
@@ -253,7 +256,7 @@
  * if there is no add_buddy callback.
  */
 static void
-bonjour_fake_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) {
+bonjour_fake_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) {
 	purple_debug_error("bonjour", "Buddy '%s' manually added; removing.  "
 				      "Bonjour buddies must be discovered and not manually added.\n",
 			   purple_buddy_get_name(buddy));
@@ -306,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)
@@ -325,7 +328,7 @@
 static
 void bonjour_set_buddy_icon(PurpleConnection *conn, PurpleStoredImage *img)
 {
-	BonjourData *bd = conn->proto_data;
+	BonjourData *bd = purple_connection_get_protocol_data(conn);
 	bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data);
 }
 
@@ -371,9 +374,12 @@
 	else
 		status_description = purple_status_get_name(status);
 
-	purple_notify_user_info_add_pair(user_info, _("Status"), status_description);
-	if (message != NULL)
-		purple_notify_user_info_add_pair(user_info, _("Message"), message);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_description);
+	if (message != NULL) {
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Message"), message);
+	}
 
 	if (bb == NULL) {
 		purple_debug_error("bonjour", "Got tooltip request for a buddy without protocol data.\n");
@@ -382,20 +388,35 @@
 
 	/* Only show first/last name if there is a nickname set (to avoid duplication) */
 	if (bb->nick != NULL && *bb->nick != '\0') {
-		if (bb->first != NULL && *bb->first != '\0')
-			purple_notify_user_info_add_pair(user_info, _("First name"), bb->first);
-		if (bb->last != NULL && *bb->last != '\0')
-			purple_notify_user_info_add_pair(user_info, _("Last name"), bb->last);
+		if (bb->first != NULL && *bb->first != '\0') {
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("First name"), bb->first);
+		}
+		if (bb->last != NULL && *bb->last != '\0') {
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Last name"), bb->last);
+		}
 	}
 
-	if (bb->email != NULL && *bb->email != '\0')
-		purple_notify_user_info_add_pair(user_info, _("Email"), bb->email);
+	if (bb->email != NULL && *bb->email != '\0') {
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Email"), bb->email);
+	}
 
-	if (bb->AIM != NULL && *bb->AIM != '\0')
-		purple_notify_user_info_add_pair(user_info, _("AIM Account"), bb->AIM);
+	if (bb->AIM != NULL && *bb->AIM != '\0') {
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("AIM Account"), bb->AIM);
+	}
 
-	if (bb->jid != NULL && *bb->jid != '\0')
-		purple_notify_user_info_add_pair(user_info, _("XMPP Account"), bb->jid);
+	if (bb->jid != NULL && *bb->jid != '\0') {
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("XMPP Account"), bb->jid);
+	}
 }
 
 static void
@@ -418,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);
 
@@ -443,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);
 }
@@ -463,6 +484,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),                        /* struct_size */
 	OPT_PROTO_NO_PASSWORD,
 	NULL,                                                    /* user_splits */
 	NULL,                                                    /* protocol_options */
@@ -503,7 +525,6 @@
 	NULL,                                                    /* keepalive */
 	NULL,                                                    /* register_user */
 	NULL,                                                    /* get_cb_info */
-	NULL,                                                    /* get_cb_away */
 	NULL,                                                    /* alias_buddy */
 	bonjour_group_buddy,                                     /* group_buddy */
 	bonjour_rename_group,                                    /* rename_group */
@@ -528,15 +549,12 @@
 	NULL,                                                    /* unregister_user */
 	NULL,                                                    /* send_attention */
 	NULL,                                                    /* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),                        /* struct_size */
 	NULL,                                                    /* get_account_text_table */
 	NULL,                                                    /* initiate_media */
 	NULL,                                                    /* get_media_caps */
 	NULL,                                                    /* get_moods */
 	NULL,                                                    /* set_public_alias */
-	NULL,                                                    /* get_public_alias */
-	NULL,                                                    /* add_buddy_with_invite */
-	NULL                                                     /* add_buddies_with_invite */
+	NULL                                                     /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/bonjour/bonjour_ft.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/bonjour_ft.c	Mon Oct 31 01:25:36 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 */
@@ -90,12 +90,12 @@
 
 static void bonjour_xfer_request_denied(PurpleXfer *xfer)
 {
-	XepXfer *xf = xfer->data;
+	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
 
 	purple_debug_info("bonjour", "Bonjour-xfer-request-denied.\n");
 
 	if(xf)
-		xep_ft_si_reject(xf->data, xf->sid, xfer->who, "403", "cancel");
+		xep_ft_si_reject(xf->data, xf->sid, purple_xfer_get_remote_user(xfer), "403", "cancel");
 
 	bonjour_free_xfer(xfer);
 }
@@ -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);
 	}
@@ -162,11 +162,11 @@
 		xfer = xfers->data;
 		if(xfer == NULL)
 			break;
-		xf = xfer->data;
+		xf = purple_xfer_get_protocol_data(xfer);
 		if(xf == NULL)
 			break;
-		if(xf->sid && xfer->who && !strcmp(xf->sid, sid) &&
-				!strcmp(xfer->who, from))
+		if(xf->sid && purple_xfer_get_remote_user(xfer) && !strcmp(xf->sid, sid) &&
+				!strcmp(purple_xfer_get_remote_user(xfer), from))
 			return xfer;
 	}
 
@@ -180,7 +180,7 @@
 {
 	xmlnode *si_node, *feature, *field, *file, *x;
 	XepIq *iq;
-	XepXfer *xf = xfer->data;
+	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
 	BonjourData *bd = NULL;
 	char buf[32];
 
@@ -210,8 +210,8 @@
 
 	file = xmlnode_new_child(si_node, "file");
 	xmlnode_set_namespace(file, "http://jabber.org/protocol/si/profile/file-transfer");
-	xmlnode_set_attrib(file, "name", xfer->filename);
-	g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size);
+	xmlnode_set_attrib(file, "name", purple_xfer_get_filename(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");
@@ -240,7 +240,7 @@
 }
 
 static void
-xep_ft_si_result(PurpleXfer *xfer, char *to)
+xep_ft_si_result(PurpleXfer *xfer, const char *to)
 {
 	xmlnode *si_node, *feature, *field, *value, *x;
 	XepIq *iq;
@@ -249,7 +249,7 @@
 
 	if(!to || !xfer)
 		return;
-	xf = xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 	if(!xf)
 		return;
 
@@ -290,14 +290,14 @@
 		return;
 	}
 
-	purple_debug_info("bonjour", "bonjour-free-xfer-%p.\n", xfer);
+	purple_debug_misc("bonjour", "bonjour-free-xfer-%p.\n", xfer);
 
-	xf = (XepXfer*)xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 	if(xf != NULL) {
 		BonjourData *bd = (BonjourData*)xf->data;
 		if(bd != NULL) {
 			bd->xfer_lists = g_slist_remove(bd->xfer_lists, xfer);
-			purple_debug_info("bonjour", "B free xfer from lists(%p).\n", bd->xfer_lists);
+			purple_debug_misc("bonjour", "B free xfer from lists(%p).\n", bd->xfer_lists);
 		}
 		if (xf->proxy_connection != NULL)
 			purple_proxy_connect_cancel(xf->proxy_connection);
@@ -311,10 +311,10 @@
 		g_free(xf->buddy_ip);
 		g_free(xf->sid);
 		g_free(xf);
-		xfer->data = NULL;
+		purple_xfer_set_protocol_data(xfer, NULL);
 	}
 
-	purple_debug_info("bonjour", "Need close socket=%d.\n", xfer->fd);
+	purple_debug_misc("bonjour", "Need close socket.\n");
 }
 
 PurpleXfer *
@@ -328,13 +328,14 @@
 		return NULL;
 
 	purple_debug_info("bonjour", "Bonjour-new-xfer to %s.\n", who);
-	bd = (BonjourData*) gc->proto_data;
+	bd = purple_connection_get_protocol_data(gc);
 	if(bd == NULL)
 		return NULL;
 
 	/* Build the file transfer handle */
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
-	xfer->data = xep_xfer = g_new0(XepXfer, 1);
+	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;
 
 	purple_debug_info("bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data);
@@ -379,13 +380,13 @@
 	BonjourBuddy *bb;
 	XepXfer *xf;
 
-	xf = (XepXfer*)xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 	if(xf == NULL)
 		return;
 
 	purple_debug_info("bonjour", "Bonjour-xfer-init.\n");
 
-	buddy = purple_find_buddy(xfer->account, xfer->who);
+	buddy = purple_find_buddy(purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer));
 	/* this buddy is offline. */
 	if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL)
 		return;
@@ -396,10 +397,10 @@
 	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
 		/* initiate file transfer, send SI offer. */
 		purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_SEND.\n");
-		xep_ft_si_offer(xfer, xfer->who);
+		xep_ft_si_offer(xfer, purple_xfer_get_remote_user(xfer));
 	} else {
 		/* accept file transfer request, send SI result. */
-		xep_ft_si_result(xfer, xfer->who);
+		xep_ft_si_result(xfer, purple_xfer_get_remote_user(xfer));
 		purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_RECEIVE.\n");
 	}
 }
@@ -416,7 +417,7 @@
 	g_return_if_fail(packet != NULL);
 	g_return_if_fail(pb != NULL);
 
-	bd = (BonjourData*) pc->proto_data;
+	bd = purple_connection_get_protocol_data(pc);
 	if(bd == NULL)
 		return;
 
@@ -438,7 +439,7 @@
 			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;
+				goffset filesize = 0;
 				xmlnode *file;
 
 				const char *sid = xmlnode_get_attrib(si, "id");
@@ -446,7 +447,7 @@
 				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);
+						filesize = g_ascii_strtoll(filesize_str, NULL, 10);
 				}
 
 				/* TODO: Make sure that it is advertising a bytestreams transfer */
@@ -502,7 +503,7 @@
 	g_return_if_fail(packet != NULL);
 	g_return_if_fail(pb != NULL);
 
-	bd = (BonjourData*) pc->proto_data;
+	bd = purple_connection_get_protocol_data(pc);
 	if(bd == NULL)
 		return;
 
@@ -530,7 +531,7 @@
 				int portnum;
 				XepXfer *xf = NULL;
 
-				xf = (XepXfer*)xfer->data;
+				xf = purple_xfer_get_protocol_data(xfer);
 				for(streamhost = xmlnode_get_child(query, "streamhost");
 						streamhost;
 						streamhost = xmlnode_get_next_twin(streamhost)) {
@@ -564,7 +565,7 @@
 				purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
 
 				if (iq_id && xfer != NULL)
-					xep_ft_si_reject(bd, iq_id, xfer->who, "404", "cancel");
+					xep_ft_si_reject(bd, iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
 			}
 
 		} else {
@@ -575,7 +576,7 @@
 
 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;
@@ -584,15 +585,16 @@
 	if(pc == NULL || id == NULL || from == NULL)
 		return;
 
-	bd = (BonjourData*) pc->proto_data;
+	bd = purple_connection_get_protocol_data(pc);
 	if(bd == NULL)
 		return;
 
 	purple_debug_info("bonjour", "bonjour-xfer-receive.\n");
 
 	/* Build the file transfer handle */
-	xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from);
-	xfer->data = xf = g_new0(XepXfer, 1);
+	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;
 	purple_xfer_set_filename(xfer, filename);
 	xf->iq_id = g_strdup(id);
@@ -614,7 +616,7 @@
 bonjour_sock5_request_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	XepXfer *xf = xfer->data;
+	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
 	int acceptfd;
 	int len = 0;
 
@@ -632,8 +634,6 @@
 			/* This should cancel the ft */
 			purple_debug_error("bonjour", "Error accepting incoming SOCKS5 connection. (%d)\n", errno);
 
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
 			close(source);
 			purple_xfer_cancel_remote(xfer);
 			return;
@@ -648,29 +648,26 @@
 			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;
 		else if(len <= 0){
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
 			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);
@@ -683,15 +680,13 @@
 		if (len < 0 && errno == EAGAIN)
 			return;
 		else if (len < 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
 			close(source);
 			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;
 		}
@@ -700,9 +695,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);
@@ -721,14 +716,12 @@
 		if (len < 0 && errno == EAGAIN) {
 			return;
 		} else if (len < 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
 			close(source);
 			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);
@@ -757,25 +750,25 @@
 		return;
 	}
 
-	xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ,
-					 bonjour_sock5_request_cb, xfer);
-	xf = (XepXfer*)xfer->data;
+	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;
 
 	bd = xf->data;
 
-	iq = xep_iq_new(bd, XEP_IQ_SET, xfer->who, bonjour_get_jid(bd->jabber_data->account), xf->sid);
+	iq = xep_iq_new(bd, XEP_IQ_SET, purple_xfer_get_remote_user(xfer), bonjour_get_jid(bd->jabber_data->account), xf->sid);
 
 	query = xmlnode_new_child(iq->node, "query");
 	xmlnode_set_namespace(query, "http://jabber.org/protocol/bytestreams");
 	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);
 
-	port = g_strdup_printf("%hu", xfer->local_port);
+	port = g_strdup_printf("%hu", purple_xfer_get_local_port(xfer));
 	while(local_ips) {
 		streamhost = xmlnode_new_child(query, "streamhost");
 		xmlnode_set_attrib(streamhost, "jid", xf->sid);
@@ -797,12 +790,10 @@
 		return;
 
 	purple_debug_info("bonjour", "Bonjour-bytestreams-init.\n");
-	xf = xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 
-	purple_network_listen_map_external(FALSE);
-	xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM,
+	xf->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, FALSE,
 						      bonjour_bytestreams_listen, xfer);
-	purple_network_listen_map_external(TRUE);
 	if (xf->listen_data == NULL)
 		purple_xfer_cancel_local(xfer);
 
@@ -813,7 +804,7 @@
 bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleXfer *xfer = data;
-	XepXfer *xf = xfer->data;
+	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
 	XepIq *iq;
 	xmlnode *q_node, *tmp_node;
 	BonjourData *bd;
@@ -823,7 +814,7 @@
 	if(source < 0) {
 		purple_debug_error("bonjour", "Error connecting via SOCKS5 - %s\n",
 			error_message ? error_message : "(null)");
-		xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel");
+		xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
 		/* Cancel the connection */
 		purple_xfer_cancel_local(xfer);
 		return;
@@ -836,7 +827,7 @@
 	/* Here, start the file transfer.*/
 
 	/* Notify Initiator of Connection */
-	iq = xep_iq_new(bd, XEP_IQ_RESULT, xfer->who, bonjour_get_jid(bd->jabber_data->account), xf->iq_id);
+	iq = xep_iq_new(bd, XEP_IQ_RESULT, purple_xfer_get_remote_user(xfer), bonjour_get_jid(bd->jabber_data->account), xf->iq_id);
 	q_node = xmlnode_new_child(iq->node, "query");
 	xmlnode_set_namespace(q_node, "http://jabber.org/protocol/bytestreams");
 	tmp_node = xmlnode_new_child(q_node, "streamhost-used");
@@ -862,7 +853,7 @@
 
 	purple_debug_info("bonjour", "bonjour-bytestreams-connect.\n");
 
-	xf = (XepXfer*)xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 	if(!xf)
 		return;
 
@@ -891,7 +882,7 @@
 							   bonjour_bytestreams_connect_cb, xfer);
 
 	if(xf->proxy_connection == NULL) {
-		xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel");
+		xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel");
 		/* Cancel the connection */
 		purple_xfer_cancel_local(xfer);
 	}
--- a/libpurple/protocols/bonjour/jabber.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Mon Oct 31 01:25:36 2011 +0000
@@ -744,7 +744,7 @@
 
 #if 0
 	/* TODO: Why isn't this being used? */
-	data->socket = purple_network_listen(jdata->port, SOCK_STREAM);
+	data->socket = purple_network_listen(jdata->port, AF_UNSPEC, SOCK_STREAM, TRUE);
 
 	if (jdata->socket == -1)
 	{
@@ -929,7 +929,9 @@
 		while(tmp) {
 			ip = tmp->data;
 			if (ip != NULL && g_ascii_strcasecmp(ip, bconv->ip) == 0) {
-				BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data;
+				PurpleConnection *pc = purple_account_get_connection(bconv->account);
+				BonjourData *bd = purple_connection_get_protocol_data(pc);
+				BonjourJabber *jdata = bd->jabber_data;
 
 				purple_debug_info("bonjour", "Matched buddy %s to incoming conversation \"from\" attrib and IP (%s)\n",
 					purple_buddy_get_name(pb), bconv->ip);
@@ -962,7 +964,9 @@
 
 void
 bonjour_jabber_conv_match_by_ip(BonjourJabberConversation *bconv) {
-	BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data;
+	PurpleConnection *pc = purple_account_get_connection(bconv->account);
+	BonjourData *bd = purple_connection_get_protocol_data(pc);
+	BonjourJabber *jdata = bd->jabber_data;
 	struct _match_buddies_by_address_t *mbba;
 	GSList *buddies;
 
@@ -1122,7 +1126,9 @@
 
 void
 async_bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) {
-	BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data;
+	PurpleConnection *pc = purple_account_get_connection(bconv->account);
+	BonjourData *bd = purple_connection_get_protocol_data(pc);
+	BonjourJabber *jdata = bd->jabber_data;
 
 	jdata->pending_conversations = g_slist_remove(jdata->pending_conversations, bconv);
 
@@ -1142,8 +1148,9 @@
 	if (bconv != NULL) {
 		BonjourData *bd = NULL;
 
-		if(PURPLE_CONNECTION_IS_VALID(bconv->account->gc)) {
-			bd = bconv->account->gc->proto_data;
+		PurpleConnection *pc = purple_account_get_connection(bconv->account);
+		if (PURPLE_CONNECTION_IS_VALID(pc)) {
+			bd = purple_connection_get_protocol_data(pc);
 			bd->jabber_data->pending_conversations = g_slist_remove(bd->jabber_data->pending_conversations, bconv);
 		}
 
@@ -1157,7 +1164,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);
@@ -1215,7 +1222,7 @@
 		purple_input_remove(jdata->watcher_id6);
 
 	/* Close all the conversation sockets and remove all the watchers after sending end streams */
-	if (jdata->account->gc != NULL) {
+	if (!purple_account_is_disconnected(jdata->account)) {
 		GSList *buddies, *l;
 
 		buddies = purple_find_buddies(jdata->account, NULL);
--- a/libpurple/protocols/bonjour/mdns_avahi.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Mon Oct 31 01:25:36 2011 +0000
@@ -615,7 +615,7 @@
 
 void _mdns_retrieve_buddy_icon(BonjourBuddy* buddy) {
 	PurpleConnection *conn = purple_account_get_connection(buddy->account);
-	BonjourData *bd = conn->proto_data;
+	BonjourData *bd = purple_connection_get_protocol_data(conn);
 	AvahiSessionImplData *session_idata = bd->dns_sd_data->mdns_impl_data;
 	AvahiBuddyImplData *idata = buddy->mdns_impl_data;
 	gchar *name;
--- a/libpurple/protocols/bonjour/mdns_common.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Mon Oct 31 01:25:36 2011 +0000
@@ -257,7 +257,7 @@
 bonjour_dns_sd_set_jid(PurpleAccount *account, const char *hostname)
 {
 	PurpleConnection *conn = purple_account_get_connection(account);
-	BonjourData *bd = conn->proto_data;
+	BonjourData *bd = purple_connection_get_protocol_data(conn);
 	const char *tmp, *account_name = purple_account_get_username(account);
 
 	/* Previously we allowed the hostname part of the jid to be set
--- a/libpurple/protocols/bonjour/mdns_types.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/mdns_types.h	Mon Oct 31 01:25:36 2011 +0000
@@ -37,7 +37,7 @@
 	gchar *msg;
 } BonjourDnsSd;
 
-typedef enum _PublishType {
+typedef enum {
 	PUBLISH_START,
 	PUBLISH_UPDATE
 } PublishType;
--- a/libpurple/protocols/bonjour/mdns_win32.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Mon Oct 31 01:25:36 2011 +0000
@@ -105,7 +105,7 @@
 		purple_debug_error("bonjour", "Error (%d) handling mDNS response.\n", errorCode);
 		/* This happens when the mDNSResponder goes down, I haven't seen it happen any other time (in my limited testing) */
 		if (errorCode == kDNSServiceErr_Unknown) {
-			purple_connection_error_reason(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			purple_connection_error(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Error communicating with local mDNSResponder."));
 		}
 	}
@@ -177,7 +177,7 @@
 	args->resolver_query = NULL;
 
 	if ((pb = purple_find_buddy(args->account, args->res_data->name))) {
-		if (pb->proto_data != args->bb) {
+		if (purple_buddy_get_protocol_data(pb) != args->bb) {
 			purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.",
 				args->res_data->name);
 			goto cleanup;
@@ -348,7 +348,7 @@
 
 				/* Is there an existing buddy? */
 				if ((pb = purple_find_buddy(account, serviceName)))
-					bb = pb->proto_data;
+					bb = purple_buddy_get_protocol_data(pb);
 				/* Is there a pending buddy? */
 				else {
 					while (tmp) {
@@ -368,7 +368,7 @@
 					if (pb == NULL)
 						pending_buddies = g_slist_prepend(pending_buddies, bb);
 					else
-						pb->proto_data = bb;
+						purple_buddy_set_protocol_data(pb, bb);
 				}
 
 				rd = g_new0(Win32SvcResolverData, 1);
@@ -408,7 +408,7 @@
 			GSList *l;
 			/* There may be multiple presences, we should only get rid of this one */
 			Win32SvcResolverData *rd_search;
-			BonjourBuddy *bb = pb->proto_data;
+			BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
 			Win32BuddyImplData *idata;
 
 			g_return_if_fail(bb != NULL);
--- a/libpurple/protocols/gg/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/Makefile.am	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/Makefile.mingw	Mon Oct 31 01:25:36 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/buddylist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/buddylist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -38,7 +38,7 @@
 /* void ggp_buddylist_send(PurpleConnection *gc) {{{ */
 void ggp_buddylist_send(PurpleConnection *gc)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	GSList *buddies;
 	uin_t *userlist;
@@ -90,7 +90,7 @@
 		gchar **data_tbl;
 		gchar *name, *show, *g;
 
-		if (strlen(users_tbl[i]) == 0)
+		if (!*users_tbl[i])
 			continue;
 
 		data_tbl = g_strsplit(users_tbl[i], ";", 8);
--- a/libpurple/protocols/gg/confer.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/confer.c	Mon Oct 31 01:25:36 2011 +0000
@@ -42,7 +42,7 @@
 							 const uin_t uin)
 {
 	PurpleConversation *conv;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPChat *chat;
 	GList *l;
 	gchar *str_uin;
@@ -73,7 +73,7 @@
 void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name,
 				 const uin_t *recipients, int count)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GList *l;
 	gchar *str_uin;
 
@@ -111,7 +111,7 @@
 const char *ggp_confer_find_by_participants(PurpleConnection *gc,
 					    const uin_t *recipients, int count)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPChat *chat = NULL;
 	GList *l;
 	int matches;
@@ -149,7 +149,7 @@
 /* const char *ggp_confer_add_new(PurpleConnection *gc, const char *name) {{{ */
 const char *ggp_confer_add_new(PurpleConnection *gc, const char *name)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPChat *chat;
 
 	chat = g_new0(GGPChat, 1);
--- a/libpurple/protocols/gg/gg-utils.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/gg-utils.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/gg-utils.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/gg.c	Mon Oct 31 01:25:36 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 */
@@ -97,7 +99,7 @@
 static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = _gc;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPToken *token = info->token;
 	GGPTokenCallback cb;
 
@@ -170,7 +172,7 @@
 	if (ggp_setup_proxy(account) == -1)
 		return;
 
-	info = gc->proto_data;
+	info = purple_connection_get_protocol_data(gc);
 
 	if ((req = gg_token(1)) == NULL) {
 		purple_notify_error(account,
@@ -199,7 +201,7 @@
 static void ggp_action_buddylist_get(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *)action->context;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 
 	purple_debug_info("gg", "Downloading...\n");
 
@@ -214,7 +216,7 @@
 static void ggp_action_buddylist_put(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *)action->context;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 
 	char *buddylist = ggp_buddylist_dump(purple_connection_get_account(gc));
 
@@ -235,7 +237,7 @@
 static void ggp_action_buddylist_delete(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *)action->context;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 
 	purple_debug_info("gg", "Deleting...\n");
 
@@ -334,7 +336,7 @@
 					     PurpleRequestFields *fields)
 {
 	PurpleAccount *account;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	struct gg_http *h = NULL;
 	struct gg_pubdir *s;
 	uin_t uin;
@@ -354,14 +356,14 @@
 
 	if (email == NULL || p1 == NULL || p2 == NULL || t == NULL ||
 	    *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 			_("You must fill in all registration fields"));
 		goto exit_err;
 	}
 
 	if (g_utf8_collate(p1, p2) != 0) {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 			_("Passwords do not match"));
 		goto exit_err;
@@ -371,7 +373,7 @@
 			token->id, t);
 	h = gg_register3(email, p1, token->id, t, 0);
 	if (h == NULL || !(s = h->data) || !s->success) {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 			_("Unable to register new account.  An unknown error occurred."));
 		goto exit_err;
@@ -415,10 +417,10 @@
 static void ggp_callback_register_account_cancel(PurpleConnection *gc,
 						 PurpleRequestFields *fields)
 {
-	GGPInfo *info = gc->proto_data;
+	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);
@@ -433,7 +435,7 @@
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
 
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPToken *token = info->token;
 
 
@@ -483,7 +485,7 @@
 
 static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer user_data)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPSearchForm *form = user_data;
 	guint32 seq;
 
@@ -520,7 +522,7 @@
 
 static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPSearchForm *form;
 	guint32 seq;
 
@@ -616,75 +618,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 = gc->proto_data;
+	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);
@@ -696,12 +760,11 @@
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
 
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPToken *token = info->token;
 
 	char *msg;
 
-
 	fields = purple_request_fields_new();
 	group = purple_request_field_group_new(NULL);
 	purple_request_fields_add_group(fields, group);
@@ -721,6 +784,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 +800,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"),
@@ -758,7 +826,7 @@
 
 static void ggp_action_change_status_broadcasting_ok(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	int selected_field;
 	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleStatus *status;
@@ -778,7 +846,7 @@
 static void ggp_action_change_status_broadcasting(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *)action->context;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *group;
@@ -848,7 +916,7 @@
 
 	buddy = (PurpleBuddy *)node;
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	info = gc->proto_data;
+	info = purple_connection_get_protocol_data(gc);
 
 	fields = purple_request_fields_new();
 	group = purple_request_field_group_new(NULL);
@@ -857,7 +925,7 @@
 	field = purple_request_field_list_new("name", "Chat name");
 	for (l = info->chats; l != NULL; l = l->next) {
 		GGPChat *chat = l->data;
-		purple_request_field_list_add(field, chat->name, chat->name);
+		purple_request_field_list_add_icon(field, chat->name, NULL, chat->name);
 	}
 	purple_request_field_group_add_field(group, field);
 
@@ -879,7 +947,7 @@
 
 static void ggp_add_deny(PurpleConnection *gc, const char *who)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	uin_t uin = ggp_str_to_uin(who);
 	
 	purple_debug_info("gg", "ggp_add_deny: %u\n", uin);
@@ -890,7 +958,7 @@
 
 static void ggp_rem_deny(PurpleConnection *gc, const char *who)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	uin_t uin = ggp_str_to_uin(who);
 	
 	purple_debug_info("gg", "ggp_rem_deny: %u\n", uin);
@@ -1024,7 +1092,7 @@
 
 				purple_debug_info("gg", "gg_get_avatar_url_cb: "
 					"requesting avatar for %s\n", uin);
-				url_data = purple_util_fetch_url_request_len_with_account(account,
+				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,7 +1120,7 @@
 
 	avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin);
 
-	url_data = purple_util_fetch_url_request_len_with_account(
+	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,
 			gg_get_avatar_url_cb, gc);
@@ -1086,7 +1154,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 +1164,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);
@@ -1194,27 +1266,37 @@
 
 	val = ggp_search_get_result(req, 0, GG_PUBDIR50_STATUS);
 	/* XXX: Use of ggp_str_to_uin() is an ugly hack! */
-	purple_notify_user_info_add_pair(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val)));
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val)));
 	g_free(val);
 
 	who = ggp_search_get_result(req, 0, GG_PUBDIR50_UIN);
-	purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+	/* TODO: Check whether it's correct to call add_pair_html,
+	         or if we should be using add_pair_plaintext */
+	purple_notify_user_info_add_pair_html(user_info, _("UIN"), who);
 
 	val = ggp_search_get_result(req, 0, GG_PUBDIR50_FIRSTNAME);
-	purple_notify_user_info_add_pair(user_info, _("First Name"), val);
+	/* TODO: Check whether it's correct to call add_pair_html,
+	         or if we should be using add_pair_plaintext */
+	purple_notify_user_info_add_pair_html(user_info, _("First Name"), val);
 	g_free(val);
 
 	val = ggp_search_get_result(req, 0, GG_PUBDIR50_NICKNAME);
-	purple_notify_user_info_add_pair(user_info, _("Nickname"), val);
+	/* TODO: Check whether it's correct to call add_pair_html,
+	         or if we should be using add_pair_plaintext */
+	purple_notify_user_info_add_pair_html(user_info, _("Nickname"), val);
 	g_free(val);
 
 	val = ggp_search_get_result(req, 0, GG_PUBDIR50_CITY);
-	purple_notify_user_info_add_pair(user_info, _("City"), val);
+	/* TODO: Check whether it's correct to call add_pair_html,
+	         or if we should be using add_pair_plaintext */
+	purple_notify_user_info_add_pair_html(user_info, _("City"), val);
 	g_free(val);
 
 	val = ggp_search_get_result(req, 0, GG_PUBDIR50_BIRTHYEAR);
 	if (strncmp(val, "0", 1)) {
-		purple_notify_user_info_add_pair(user_info, _("Birth Year"), val);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Birth Year"), val);
 	}
 	g_free(val);
 
@@ -1225,15 +1307,12 @@
 	if (NULL != buddy) {
 		PurpleStatus *status;
 		const char *msg;
-		char *text;
 
 		status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));
 		msg = purple_status_get_attr_string(status, "message");
 
 		if (msg != NULL) {
-			text = g_markup_escape_text(msg, -1);
-			purple_notify_user_info_add_pair(user_info, _("Message"), text);
-			g_free(text);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Message"), msg);
 		}
 	}
 
@@ -1342,7 +1421,7 @@
 
 static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPSearchForm *form;
 	int res_count;
 	guint32 seq;
@@ -1384,7 +1463,7 @@
 static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev)
 {
 	gint imgid = 0;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GList *entry = g_list_first(info->pending_richtext_messages);
 	gchar *handlerid = g_strdup_printf("IMGID_HANDLER-%i", ev->event.image_reply.crc32);
 
@@ -1432,11 +1511,12 @@
  */
 static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	PurpleConversation *conv;
 	gchar *from;
 	gchar *msg;
 	gchar *tmp;
+	time_t mtime;
 
 	if (ev->event.msg.message == NULL)
 	{
@@ -1565,8 +1645,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;
@@ -1592,7 +1677,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);
@@ -1601,7 +1686,7 @@
 
 static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	PurpleStoredImage *image;
 	gint imgid = GPOINTER_TO_INT(g_hash_table_lookup(info->pending_images, GINT_TO_POINTER(ev->event.image_request.crc32)));
 
@@ -1707,14 +1792,14 @@
 static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = _gc;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	struct gg_event *ev;
 	int i;
 
 	if (!(ev = gg_watch_fd(info->session))) {
 		purple_debug_error("gg",
 			"ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to read from socket"));
 		return;
@@ -1842,7 +1927,7 @@
 
 	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
-	info = gc->proto_data;
+	info = purple_connection_get_protocol_data(gc);
 
 	purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
 			info->session->check, info->session->state);
@@ -1880,7 +1965,7 @@
 
 	if (!(ev = gg_watch_fd(info->session))) {
 		purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n");
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to read from socket"));
 		return;
@@ -1889,11 +1974,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);
@@ -1906,8 +1992,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);
 
@@ -1917,17 +2003,69 @@
 			}
 			break;
 		case GG_EVENT_CONN_FAILED:
-			purple_input_remove(gc->inpa);
-			gc->inpa = 0;
-			purple_connection_error_reason (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",
@@ -1951,6 +2089,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;
@@ -1975,7 +2126,7 @@
 static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
 {
 	PurpleStatus *status;
-	char *text, *tmp;
+	char *tmp;
 	const char *msg, *name, *alias;
 
 	g_return_if_fail(b != NULL);
@@ -1985,21 +2136,19 @@
 	name = purple_status_get_name(status);
 	alias = purple_buddy_get_alias(b);
 
-	purple_notify_user_info_add_pair (user_info, _("Alias"), alias);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias);
 
 	if (msg != NULL) {
-		text = g_markup_escape_text(msg, -1);
 		if (PURPLE_BUDDY_IS_ONLINE(b)) {
-			tmp = g_strdup_printf("%s: %s", name, text);
-			purple_notify_user_info_add_pair(user_info, _("Status"), tmp);
+			tmp = g_strdup_printf("%s: %s", name, msg);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), tmp);
 			g_free(tmp);
 		} else {
-			purple_notify_user_info_add_pair(user_info, _("Message"), text);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Message"), msg);
 		}
-		g_free(text);
 	/* We don't want to duplicate 'Status: Offline'. */
 	} else if (PURPLE_BUDDY_IS_ONLINE(b)) {
-		purple_notify_user_info_add_pair(user_info, _("Status"), name);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), name);
 	}
 }
 
@@ -2008,50 +2157,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);
 	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);
+	/*
+	 * 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);
 	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
+	/*
+	 * 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_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	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;
@@ -2062,13 +2221,15 @@
 	PurpleMenuAction *act;
 	GList *m = NULL;
 	PurpleAccount *account;
+	PurpleConnection *gc;
 	GGPInfo *info;
 
 	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 		return NULL;
 
 	account = purple_buddy_get_account((PurpleBuddy *) node);
-	info = purple_account_get_connection(account)->proto_data;
+	gc = purple_account_get_connection(account);
+	info = purple_connection_get_protocol_data(gc);
 	if (info->chats) {
 		act = purple_menu_action_new(_("Add to chat"),
 			PURPLE_CALLBACK(ggp_bmenu_add_to_chat),
@@ -2120,11 +2281,25 @@
 	info->pending_images = g_hash_table_new(g_direct_hash, g_direct_equal);
 	info->status_broadcasting = purple_account_get_bool(account, "status_broadcasting", TRUE);
 	
-	gc->proto_data = info;
+	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);
@@ -2136,13 +2311,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;
@@ -2157,7 +2345,7 @@
 		if (addr == NULL) {
 			gchar *tmp = g_strdup_printf(_("Unable to resolve hostname '%s': %s"),
 					address, g_strerror(errno));
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, /* should this be a settings error? */
 				tmp);
 			g_free(tmp);
@@ -2172,30 +2360,31 @@
 	info->session = gg_login(glp);
 	purple_connection_update_progress(gc, _("Connecting"), 0, 2);
 	if (info->session == NULL) {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Connection failed"));
 		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);
 }
 
 static void ggp_close(PurpleConnection *gc)
 {
+	PurpleAccount *account;
+	GGPInfo *info;;
 
 	if (gc == NULL) {
 		purple_debug_info("gg", "gc == NULL\n");
 		return;
 	}
 
-	if (gc->proto_data) {
-		PurpleAccount *account = purple_connection_get_account(gc);
-		PurpleStatus *status;
-		GGPInfo *info = gc->proto_data;
-
-		status = purple_account_get_active_status(account);
+	account = purple_connection_get_account(gc);
+	info = purple_connection_get_protocol_data(gc);
+
+	if (info) {
+		PurpleStatus *status = purple_account_get_active_status(account);
 
 		if (info->session != NULL) {
 			ggp_set_status(account, status);
@@ -2213,20 +2402,21 @@
 		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);
-		gc->proto_data = NULL;
 	}
 
-	if (gc->inpa > 0)
-		purple_input_remove(gc->inpa);
-
 	purple_debug_info("gg", "Connection closed.\n");
 }
 
 static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg,
 		       PurpleMessageFlags flags)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	char *tmp, *plain;
 	int ret = 1;
 	unsigned char format[1024];
@@ -2344,6 +2534,7 @@
 
 static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
 {
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	int dummy_length; // we don't send real length of typed message
 	
 	if (state == PURPLE_TYPED) // not supported
@@ -2355,7 +2546,7 @@
 		dummy_length = 0;
 	
 	gg_typing_notification(
-		((GGPInfo*)gc->proto_data)->session,
+		info->session,
 		ggp_str_to_uin(name),
 		dummy_length); 
 	
@@ -2364,7 +2555,7 @@
 
 static void ggp_get_info(PurpleConnection *gc, const char *name)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPSearchForm *form;
 	guint32 seq;
 
@@ -2392,6 +2583,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;
@@ -2440,7 +2634,7 @@
 		return;
 
 	gc = purple_account_get_connection(account);
-	info = gc->proto_data;
+	info = purple_connection_get_protocol_data(gc);
 
 	new_status = ggp_to_gg_status(status, &new_msg);
 
@@ -2458,10 +2652,10 @@
 
 }
 
-static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
 {
 	PurpleAccount *account;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	const gchar *name = purple_buddy_get_name(buddy);
 
 	gg_add_notify(info->session, ggp_str_to_uin(name));
@@ -2475,14 +2669,14 @@
 static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
 						 PurpleGroup *group)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 
 	gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy)));
 }
 
 static void ggp_join_chat(PurpleConnection *gc, GHashTable *data)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPChat *chat;
 	char *chat_name;
 	GList *l;
@@ -2520,7 +2714,7 @@
 static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
 {
 	PurpleConversation *conv;
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPChat *chat = NULL;
 	GList *l;
 	/* char *msg, *plain; */
@@ -2534,7 +2728,7 @@
 	for (l = info->chats; l != NULL; l = l->next) {
 		chat = l->data;
 
-		if (g_utf8_collate(chat->name, conv->name) == 0) {
+		if (g_utf8_collate(chat->name, purple_conversation_get_name(conv)) == 0) {
 			break;
 		}
 
@@ -2575,14 +2769,14 @@
 
 static void ggp_keepalive(PurpleConnection *gc)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 
 	/* purple_debug_info("gg", "Keeping connection alive....\n"); */
 
 	if (gg_ping(info->session) < 0) {
 		purple_debug_info("gg", "Not connected to the server "
 				"or gg_session is not correct\n");
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Not connected to the server"));
 	}
@@ -2600,14 +2794,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);
@@ -2632,10 +2828,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;
 }
 
@@ -2646,6 +2838,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE,
 	NULL,				/* user_splits */
 	NULL,				/* protocol_options */
@@ -2686,13 +2879,12 @@
 	ggp_keepalive,			/* keepalive */
 	ggp_register_user,		/* register_user */
 	NULL,				/* get_cb_info */
-	NULL,				/* get_cb_away */
 	NULL,				/* alias_buddy */
 	NULL,				/* group_buddy */
 	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 */
@@ -2711,15 +2903,12 @@
 	NULL,				/* unregister_user */
 	NULL,				/* send_attention */
 	NULL,				/* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,                           /* get_account_text_table */
 	NULL,                           /* initiate_media */
 	NULL,                            /* can_do_media */
 	NULL,				/* get_moods */
 	NULL,				/* set_public_alias */
-	NULL,				/* get_public_alias */
-	NULL,				/* add_buddy_with_invite */
-	NULL				/* add_buddies_with_invite */
+	NULL				/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
@@ -2785,11 +2974,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,
@@ -2802,22 +2986,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/gg.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/common.c	Mon Oct 31 01:25:36 2011 +0000
@@ -24,15 +24,10 @@
  *
  * \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>
@@ -92,7 +87,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/compat.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/dcc.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/dcc7.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/events.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/handlers.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/http.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu-config.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/pubdir.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/pubdir50.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/resolver.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/lib/resolver.h	Mon Oct 31 01:25:36 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);
 
--- a/libpurple/protocols/gg/search.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/gg/search.c	Mon Oct 31 01:25:36 2011 +0000
@@ -135,7 +135,7 @@
 /* guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form) {{{ */
 guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form)
 {
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	gg_pubdir50_t req;
 	guint seq, offset;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/gg/win32-resolver.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:25:36 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/dcc_send.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/irc/dcc_send.c	Mon Oct 31 01:25:36 2011 +0000
@@ -34,11 +34,12 @@
 
 struct irc_xfer_rx_data {
 	gchar *ip;
+	unsigned int remote_port;
 };
 
 static void irc_dccsend_recv_destroy(PurpleXfer *xfer)
 {
-	struct irc_xfer_rx_data *xd = xfer->data;
+	struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer);
 
 	g_free(xd->ip);
 	g_free(xd);
@@ -51,10 +52,10 @@
  */
 static void irc_dccsend_recv_ack(PurpleXfer *xfer, const guchar *data, size_t size) {
 	guint32 l;
-	size_t result;
+	gssize result;
 
-	l = htonl(xfer->bytes_sent);
-	result = write(xfer->fd, &l, sizeof(l));
+	l = htonl(purple_xfer_get_bytes_sent(xfer));
+	result = purple_xfer_write(xfer, (guchar *)&l, sizeof(l));
 	if (result != sizeof(l)) {
 		purple_debug_error("irc", "unable to send acknowledgement: %s\n", g_strerror(errno));
 		/* TODO: We should probably close the connection here or something. */
@@ -62,9 +63,9 @@
 }
 
 static void irc_dccsend_recv_init(PurpleXfer *xfer) {
-	struct irc_xfer_rx_data *xd = xfer->data;
+	struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer);
 
-	purple_xfer_start(xfer, -1, xd->ip, xfer->remote_port);
+	purple_xfer_start(xfer, -1, xd->ip, xd->remote_port);
 	g_free(xd->ip);
 	xd->ip = NULL;
 }
@@ -114,10 +115,10 @@
 	if (xfer)
 	{
 		xd = g_new0(struct irc_xfer_rx_data, 1);
-		xfer->data = xd;
+		purple_xfer_set_protocol_data(xfer, xd);
 
 		purple_xfer_set_filename(xfer, filename->str);
-		xfer->remote_port = atoi(token[i+1]);
+		xd->remote_port = atoi(token[i+1]);
 
 		nip = strtoul(token[i], NULL, 10);
 		if (nip) {
@@ -157,7 +158,7 @@
 
 static void irc_dccsend_send_destroy(PurpleXfer *xfer)
 {
-	struct irc_xfer_send_data *xd = xfer->data;
+	struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer);
 
 	if (xd == NULL)
 		return;
@@ -178,7 +179,7 @@
 static void irc_dccsend_send_read(gpointer data, int source, PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	struct irc_xfer_send_data *xd = xfer->data;
+	struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer);
 	char buffer[64];
 	int len;
 
@@ -228,13 +229,13 @@
 static gssize irc_dccsend_send_write(const guchar *buffer, size_t size, PurpleXfer *xfer)
 {
 	gssize s;
-	int ret;
+	gssize ret;
 
 	s = MIN(purple_xfer_get_bytes_remaining(xfer), size);
 	if (!s)
 		return 0;
 
-	ret = write(xfer->fd, buffer, s);
+	ret = purple_xfer_write(xfer, buffer, s);
 
 	if (ret < 0 && errno == EAGAIN)
 		ret = 0;
@@ -244,7 +245,7 @@
 
 static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) {
 	PurpleXfer *xfer = (PurpleXfer *) data;
-	struct irc_xfer_send_data *xd = xfer->data;
+	struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer);
 	int conn, flags;
 
 	conn = accept(xd->fd, NULL, 0);
@@ -257,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;
 
@@ -285,7 +286,7 @@
 	struct in_addr addr;
 	unsigned short int port;
 
-	xd = xfer->data;
+	xd = purple_xfer_get_protocol_data(xfer);
 	xd->listen_data = NULL;
 
 	if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL
@@ -294,9 +295,9 @@
 		return;
 	}
 
-	xd = xfer->data;
+	xd = purple_xfer_get_protocol_data(xfer);
 	gc = purple_account_get_connection(purple_xfer_get_account(xfer));
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 
 	purple_xfer_unref(xfer);
 
@@ -312,17 +313,17 @@
 	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] = xfer->who;
+	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",
-	                               xfer->filename, ntohl(addr.s_addr),
-	                               port, xfer->size);
+	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));
 
-	irc_cmd_privmsg(gc->proto_data, "msg", NULL, arg);
+	irc_cmd_privmsg(purple_connection_get_protocol_data(gc), "msg", NULL, arg);
 	g_free(tmp);
 }
 
@@ -331,14 +332,14 @@
  */
 static void irc_dccsend_send_init(PurpleXfer *xfer) {
 	PurpleConnection *gc = purple_account_get_connection(purple_xfer_get_account(xfer));
-	struct irc_xfer_send_data *xd = xfer->data;
+	struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer);
 
-	xfer->filename = g_path_get_basename(xfer->local_filename);
+	purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
 
 	purple_xfer_ref(xfer);
 
 	/* Create a listening socket */
-	xd->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM,
+	xd->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE,
 			irc_dccsend_network_listen_cb, xfer);
 	if (xd->listen_data == NULL) {
 		purple_xfer_unref(xfer);
@@ -359,7 +360,7 @@
 	{
 		xd = g_new0(struct irc_xfer_send_data, 1);
 		xd->fd = -1;
-		xfer->data = xd;
+		purple_xfer_set_protocol_data(xfer, xd);
 
 		/* Setup our I/O op functions */
 		purple_xfer_set_init_fnc(xfer, irc_dccsend_send_init);
--- a/libpurple/protocols/irc/irc.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/irc/irc.c	Mon Oct 31 01:25:36 2011 +0000
@@ -70,11 +70,11 @@
 	struct irc_conn *irc;
 	char *title;
 
-	if (gc == NULL || gc->proto_data == NULL) {
+	if (gc == NULL || purple_connection_get_protocol_data(gc) == NULL) {
 		purple_debug(PURPLE_DEBUG_ERROR, "irc", "got MOTD request for NULL gc\n");
 		return;
 	}
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 	if (irc->motd == NULL) {
 		purple_notify_error(gc, _("Error displaying MOTD"), _("No MOTD available"),
 				  _("There is no MOTD associated with this connection."));
@@ -100,7 +100,7 @@
 
 static int irc_send_raw(PurpleConnection *gc, const char *buf, int len)
 {
-	struct irc_conn *irc = (struct irc_conn*)gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	if (len == -1) {
 		len = strlen(buf);
 	}
@@ -130,7 +130,7 @@
 		PurpleConnection *gc = purple_account_get_connection(irc->account);
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 			g_strerror(errno));
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
@@ -174,7 +174,7 @@
 		PurpleConnection *gc = purple_account_get_connection(irc->account);
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 			g_strerror(errno));
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 	} else if (ret < buflen) {
@@ -356,16 +356,17 @@
 	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_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("IRC nick and server may not contain whitespace"));
 		return;
 	}
 
-	gc->proto_data = irc = g_new0(struct irc_conn, 1);
+	irc = g_new0(struct irc_conn, 1);
+	purple_connection_set_protocol_data(gc, irc);
 	irc->fd = -1;
 	irc->account = account;
 	irc->outbuf = purple_circ_buffer_new(512);
@@ -390,7 +391,7 @@
 					purple_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT),
 					irc_login_cb_ssl, irc_ssl_connect_failure, gc);
 		} else {
-			purple_connection_error_reason (gc,
+			purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("SSL support unavailable"));
 			return;
@@ -403,7 +404,7 @@
 				 purple_account_get_int(account, "port", IRC_DEFAULT_PORT),
 				 irc_login_cb, gc) == NULL)
 		{
-			purple_connection_error_reason (gc,
+			purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to connect"));
 			return;
@@ -415,7 +416,7 @@
 	char *buf, *tmp = NULL;
 	char *server;
 	const char *username, *realname;
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	const char *pass = purple_connection_get_password(gc);
 
 	if (pass && *pass) {
@@ -485,12 +486,12 @@
 static void irc_login_cb(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleConnection *gc = data;
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
 		gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
 			error_message);
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
@@ -499,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);
 	}
 }
 
@@ -508,7 +509,7 @@
 		gpointer data)
 {
 	PurpleConnection *gc = data;
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 
 	irc->gsc = NULL;
 
@@ -517,7 +518,7 @@
 
 static void irc_close(PurpleConnection *gc)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 
 	if (irc == NULL)
 		return;
@@ -525,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) {
@@ -558,7 +561,7 @@
 
 static int irc_im_send(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	char *plain;
 	const char *args[2];
 
@@ -574,7 +577,7 @@
 
 static void irc_get_info(PurpleConnection *gc, const char *who)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	const char *args[2];
 	args[0] = who;
 	args[1] = NULL;
@@ -589,7 +592,7 @@
 	const char *status_id = purple_status_get_id(status);
 
 	g_return_if_fail(gc != NULL);
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 
 	if (!purple_status_is_active(status))
 		return;
@@ -606,9 +609,9 @@
 	}
 }
 
-static void irc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+static void irc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
 {
-	struct irc_conn *irc = (struct irc_conn *)gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	struct irc_buddy *ib;
 	const char *bname = purple_buddy_get_name(buddy);
 
@@ -633,7 +636,7 @@
 
 static void irc_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	struct irc_conn *irc = (struct irc_conn *)gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	struct irc_buddy *ib;
 
 	ib = g_hash_table_lookup(irc->buddies, purple_buddy_get_name(buddy));
@@ -644,9 +647,10 @@
 
 static void read_input(struct irc_conn *irc, int len)
 {
+	PurpleConnection *connection = purple_account_get_connection(irc->account);
 	char *cur, *end;
 
-	irc->account->gc->last_received = time(NULL);
+	purple_connection_update_last_received(connection);
 	irc->inbufused += len;
 	irc->inbuf[irc->inbufused] = '\0';
 
@@ -678,7 +682,7 @@
 {
 
 	PurpleConnection *gc = data;
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	int len;
 
 	if(!g_list_find(purple_connections_get_all(), gc)) {
@@ -699,12 +703,12 @@
 	} else if (len < 0) {
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	} else if (len == 0) {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Server closed the connection"));
 		return;
@@ -716,7 +720,7 @@
 static void irc_input_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = data;
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	int len;
 
 	if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) {
@@ -730,12 +734,12 @@
 	} else if (len < 0) {
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	} else if (len == 0) {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Server closed the connection"));
 		return;
@@ -746,7 +750,7 @@
 
 static void irc_chat_join (PurpleConnection *gc, GHashTable *data)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	const char *args[2];
 
 	args[0] = g_hash_table_lookup(data, "channel");
@@ -760,7 +764,7 @@
 
 static void irc_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	PurpleConversation *convo = purple_find_chat(gc, id);
 	const char *args[2];
 
@@ -776,7 +780,7 @@
 
 static void irc_chat_leave (PurpleConnection *gc, int id)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	PurpleConversation *convo = purple_find_chat(gc, id);
 	const char *args[2];
 
@@ -791,7 +795,7 @@
 
 static int irc_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	PurpleConversation *convo = purple_find_chat(gc, id);
 	const char *args[2];
 	char *tmp;
@@ -806,7 +810,7 @@
 	}
 #endif
 	purple_markup_html_to_xhtml(what, NULL, &tmp);
-	args[0] = convo->name;
+	args[0] = purple_conversation_get_name(convo);
 	args[1] = tmp;
 
 	irc_cmd_privmsg(irc, "msg", NULL, args);
@@ -845,7 +849,7 @@
 	const char *name = NULL;
 	struct irc_conn *irc;
 
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 	name = purple_conversation_get_name(purple_find_chat(gc, id));
 
 	if (name == NULL)
@@ -863,7 +867,7 @@
 	PurpleRoomlistField *f;
 	char *buf;
 
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 
 	if (irc->roomlist)
 		purple_roomlist_unref(irc->roomlist);
@@ -890,13 +894,14 @@
 
 static void irc_roomlist_cancel(PurpleRoomlist *list)
 {
-	PurpleConnection *gc = purple_account_get_connection(list->account);
+	PurpleAccount *account = purple_roomlist_get_account(list);
+	PurpleConnection *gc = purple_account_get_connection(account);
 	struct irc_conn *irc;
 
 	if (gc == NULL)
 		return;
 
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 
 	purple_roomlist_set_in_progress(list, FALSE);
 
@@ -908,13 +913,14 @@
 
 static void irc_keepalive(PurpleConnection *gc)
 {
-	struct irc_conn *irc = gc->proto_data;
+	struct irc_conn *irc = purple_connection_get_protocol_data(gc);
 	if ((time(NULL) - irc->recv_time) > PING_TIMEOUT)
 		irc_cmd_ping(irc, NULL, NULL, NULL);
 }
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),    /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL |
 	OPT_PROTO_SLASH_COMMANDS_NATIVE,
 	NULL,					/* user_splits */
@@ -956,7 +962,6 @@
 	irc_keepalive,		/* keepalive */
 	NULL,					/* register_user */
 	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
 	NULL,					/* alias_buddy */
 	NULL,					/* group_buddy */
 	NULL,					/* rename_group */
@@ -981,15 +986,12 @@
 	NULL,                   /* unregister_user */
 	NULL,                   /* send_attention */
 	NULL,                   /* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),    /* struct_size */
 	NULL,                    /* get_account_text_table */
 	NULL,                    /* initiate_media */
 	NULL,					 /* get_media_caps */
 	NULL,					 /* get_moods */
 	NULL,					 /* set_public_alias */
-	NULL,					 /* get_public_alias */
-	NULL,					 /* add_buddy_with_invite */
-	NULL					 /* add_buddies_with_invite */
+	NULL					 /* get_public_alias */
 };
 
 static gboolean load_plugin (PurplePlugin *plugin) {
--- a/libpurple/protocols/irc/irc.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/irc/irc.h	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/irc/msgs.c	Mon Oct 31 01:25:36 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);
 	}
 
@@ -352,44 +352,40 @@
 	tmp = g_strdup_printf("%s%s%s", tmp2,
 				(irc->whois.ircop ? _(" <i>(ircop)</i>") : ""),
 				(irc->whois.identified ? _(" <i>(identified)</i>") : ""));
-	purple_notify_user_info_add_pair(user_info, _("Nick"), tmp);
+	purple_notify_user_info_add_pair_html(user_info, _("Nick"), tmp);
 	g_free(tmp2);
 	g_free(tmp);
 
 	if (irc->whois.away) {
-		tmp = g_markup_escape_text(irc->whois.away, strlen(irc->whois.away));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Away"), irc->whois.away);
 		g_free(irc->whois.away);
-		purple_notify_user_info_add_pair(user_info, _("Away"), tmp);
-		g_free(tmp);
 	}
 	if (irc->whois.userhost) {
-		tmp = g_markup_escape_text(irc->whois.name, strlen(irc->whois.name));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), irc->whois.userhost);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Real name"), irc->whois.name);
+		g_free(irc->whois.userhost);
 		g_free(irc->whois.name);
-		purple_notify_user_info_add_pair(user_info, _("Username"), irc->whois.userhost);
-		purple_notify_user_info_add_pair(user_info, _("Real name"), tmp);
-		g_free(irc->whois.userhost);
-		g_free(tmp);
 	}
 	if (irc->whois.server) {
 		tmp = g_strdup_printf("%s (%s)", irc->whois.server, irc->whois.serverinfo);
-		purple_notify_user_info_add_pair(user_info, _("Server"), tmp);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Server"), tmp);
 		g_free(tmp);
 		g_free(irc->whois.server);
 		g_free(irc->whois.serverinfo);
 	}
 	if (irc->whois.channels) {
-		purple_notify_user_info_add_pair(user_info, _("Currently on"), irc->whois.channels->str);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), irc->whois.channels->str);
 		g_string_free(irc->whois.channels, TRUE);
 	}
 	if (irc->whois.idle) {
 		gchar *timex = purple_str_seconds_to_string(irc->whois.idle);
-		purple_notify_user_info_add_pair(user_info, _("Idle for"), timex);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Idle for"), timex);
 		g_free(timex);
-		purple_notify_user_info_add_pair(user_info,
+		purple_notify_user_info_add_pair_plaintext(user_info,
 														_("Online since"), purple_date_format_full(localtime(&irc->whois.signon)));
 	}
-	if (!strcmp(irc->whois.nick, "Paco-Paco")) {
-		purple_notify_user_info_add_pair(user_info,
+	if (!strcmp(irc->whois.nick, "elb")) {
+		purple_notify_user_info_add_pair_plaintext(user_info,
 																   _("<b>Defining adjective:</b>"), _("Glorious"));
 	}
 
@@ -461,12 +457,12 @@
 		g_free(userhost);
 		g_free(realname);
 		
-		flags = cb->flags;
+		flags = purple_conv_chat_cb_get_flags(cb);
 
 		if (args[6][0] == 'G' && !(flags & PURPLE_CBFLAGS_AWAY)) {
-			purple_conv_chat_user_set_flags(chat, cb->name, flags | PURPLE_CBFLAGS_AWAY);
+			purple_conv_chat_user_set_flags(chat, purple_conv_chat_cb_get_name(cb), flags | PURPLE_CBFLAGS_AWAY);
 		} else if(args[6][0] == 'H' && (flags & PURPLE_CBFLAGS_AWAY)) {
-			purple_conv_chat_user_set_flags(chat, cb->name, flags & ~PURPLE_CBFLAGS_AWAY);
+			purple_conv_chat_user_set_flags(chat, purple_conv_chat_cb_get_name(cb), flags & ~PURPLE_CBFLAGS_AWAY);
 		}
 	}
 }
@@ -1075,7 +1071,7 @@
 				  _("Your selected nickname was rejected by the server.  It probably contains invalid characters."));
 
 	} else {
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 				  PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 				  _("Your selected account name was rejected by the server.  It probably contains invalid characters."));
 	}
--- a/libpurple/protocols/irc/parse.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/irc/parse.c	Mon Oct 31 01:25:36 2011 +0000
@@ -171,11 +171,11 @@
 	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;
 
-	irc = gc->proto_data;
+	irc = purple_connection_get_protocol_data(gc);
 
 	if ((cmdent = g_hash_table_lookup(irc->cmds, cmd)) == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -670,11 +670,11 @@
 	} else if (!strncmp(input, "ERROR ", 6)) {
 		if (g_utf8_validate(input, -1, NULL)) {
 			char *tmp = g_strdup_printf("%s\n%s", _("Disconnected."), input);
-			purple_connection_error_reason (gc,
+			purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 			g_free(tmp);
 		} else
-			purple_connection_error_reason (gc,
+			purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Disconnected."));
 		return;
--- a/libpurple/protocols/jabber/adhoccommands.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/adhoccommands.c	Mon Oct 31 01:25:36 2011 +0000
@@ -228,7 +228,8 @@
 		JabberAdHocCommands *cmd = data;
 		PurpleBuddy *buddy = (PurpleBuddy *) node;
 		PurpleAccount *account = purple_buddy_get_account(buddy);
-		JabberStream *js = purple_account_get_connection(account)->proto_data;
+		PurpleConnection *gc = purple_account_get_connection(account);
+		JabberStream *js = purple_connection_get_protocol_data(gc);
 
 		jabber_adhoc_execute(js, cmd);
 	}
@@ -321,7 +322,7 @@
 	JabberAdHocCommands *cmd = action->user_data;
 	if(cmd) {
 		PurpleConnection *gc = (PurpleConnection *) action->context;
-		JabberStream *js = gc->proto_data;
+		JabberStream *js = purple_connection_get_protocol_data(gc);
 
 		jabber_adhoc_execute(js, cmd);
 	}
--- a/libpurple/protocols/jabber/auth.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/auth.c	Mon Oct 31 01:25:36 2011 +0000
@@ -77,7 +77,7 @@
 
 static void disallow_plaintext_auth(PurpleAccount *account)
 {
-	purple_connection_error_reason(purple_account_get_connection(account),
+	purple_connection_error(purple_account_get_connection(account),
 		PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 		_("Server requires plaintext authentication over an unencrypted stream"));
 }
@@ -145,7 +145,7 @@
 
 	mechs = xmlnode_get_child(packet, "mechanisms");
 	if(!mechs) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Invalid response from server"));
 		return;
@@ -186,7 +186,7 @@
 
 	if (js->auth_mech == NULL) {
 		/* Found no good mechanisms... */
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 				_("Server does not use any supported authentication method"));
 		return;
@@ -194,7 +194,7 @@
 
 	state = js->auth_mech->start(js, mechs, &response, &msg);
 	if (state == JABBER_SASL_STATE_FAIL) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 				msg ? msg : _("Unknown Error"));
 	} else if (response) {
@@ -231,7 +231,7 @@
 				purple_account_set_password(account, NULL);
 		}
 
-		purple_connection_error_reason(js->gc, reason, msg);
+		purple_connection_error(js->gc, reason, msg);
 		g_free(msg);
 	}
 }
@@ -247,7 +247,7 @@
 	if (type == JABBER_IQ_ERROR) {
 		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
 		char *msg = jabber_parse_error(js, packet, &reason);
-		purple_connection_error_reason(js->gc, reason, msg);
+		purple_connection_error(js->gc, reason, msg);
 		g_free(msg);
 	} else if (type == JABBER_IQ_RESULT) {
 		query = xmlnode_get_child(packet, "query");
@@ -321,7 +321,7 @@
 			}
 			finish_plaintext_authentication(js);
 		} else {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 				_("Server does not use any supported authentication method"));
 			return;
@@ -345,7 +345,7 @@
 	if (!jabber_stream_is_ssl(js) &&
 			g_str_equal("require_tls",
 				purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 			_("You require encryption, but it is not available on this server."));
 		return;
@@ -394,7 +394,7 @@
 	const char *ns = xmlnode_get_namespace(packet);
 
 	if (!purple_strequal(ns, NS_XMPP_SASL)) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Invalid response from server"));
 		return;
@@ -405,7 +405,7 @@
 		char *msg = NULL;
 		JabberSaslState state = js->auth_mech->handle_challenge(js, packet, &response, &msg);
 		if (state == JABBER_SASL_STATE_FAIL) {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 					msg ? msg : _("Invalid challenge from server"));
 		} else if (response) {
@@ -423,7 +423,7 @@
 	const char *ns = xmlnode_get_namespace(packet);
 
 	if (!purple_strequal(ns, NS_XMPP_SASL)) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Invalid response from server"));
 		return;
@@ -434,12 +434,12 @@
 		JabberSaslState state = js->auth_mech->handle_success(js, packet, &msg);
 
 		if (state == JABBER_SASL_STATE_FAIL) {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 					msg ? msg : _("Invalid response from server"));
 			return;
 		} else if (state == JABBER_SASL_STATE_CONTINUE) {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 					msg ? msg : _("Server thinks authentication is complete, but client does not"));
 			return;
@@ -479,11 +479,11 @@
 		msg = jabber_parse_error(js, packet, &reason);
 
 	if (!msg) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Invalid response from server"));
 	} else {
-		purple_connection_error_reason(js->gc, reason, msg);
+		purple_connection_error(js->gc, reason, msg);
 		g_free(msg);
 	}
 }
--- a/libpurple/protocols/jabber/auth_cyrus.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/auth_cyrus.c	Mon Oct 31 01:25:36 2011 +0000
@@ -34,7 +34,7 @@
 
 static void disallow_plaintext_auth(PurpleAccount *account)
 {
-	purple_connection_error_reason(purple_account_get_connection(account),
+	purple_connection_error(purple_account_get_connection(account),
 		PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 		_("Server may require plaintext authentication over an unencrypted stream"));
 }
@@ -46,7 +46,7 @@
 	JabberSaslState state = jabber_auth_start_cyrus(js, &response, &error);
 
 	if (state == JABBER_SASL_STATE_FAIL) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 				error);
 		g_free(error);
--- a/libpurple/protocols/jabber/auth_plain.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/auth_plain.c	Mon Oct 31 01:25:36 2011 +0000
@@ -75,7 +75,7 @@
 
 static void disallow_plaintext_auth(PurpleAccount *account)
 {
-	purple_connection_error_reason(purple_account_get_connection(account),
+	purple_connection_error(purple_account_get_connection(account),
 		PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 		_("Server requires plaintext authentication over an unencrypted stream"));
 }
--- a/libpurple/protocols/jabber/bosh.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/bosh.c	Mon Oct 31 01:25:36 2011 +0000
@@ -436,7 +436,7 @@
 
 	if (type != NULL && !strcmp(type, "terminate")) {
 		conn->state = BOSH_CONN_OFFLINE;
-		purple_connection_error_reason(conn->js->gc,
+		purple_connection_error(conn->js->gc,
 			PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 			_("The BOSH connection manager terminated your session."));
 		return TRUE;
@@ -539,7 +539,7 @@
 	if (sid) {
 		conn->sid = g_strdup(sid);
 	} else {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 		        PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		        _("No session ID given"));
 		return;
@@ -556,7 +556,7 @@
 			minor = atoi(dot + 1);
 
 		if (major != 1 || minor < 6) {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 			        PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			        _("Unsupported version of BOSH protocol"));
 			return;
@@ -733,7 +733,7 @@
 		return;
 
 	if (++conn->bosh->failed_connections == MAX_FAILED_CONNECTIONS) {
-		purple_connection_error_reason(conn->bosh->js->gc,
+		purple_connection_error(conn->bosh->js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to establish a connection with the server"));
 	} else {
@@ -939,7 +939,7 @@
 		gchar *tmp;
 		tmp = g_strdup_printf(_("Unable to establish a connection with the server: %s"),
 		        error);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	}
@@ -965,18 +965,18 @@
 			                               ssl_connection_error_cb,
 			                               conn);
 			if (!conn->psc) {
-				purple_connection_error_reason(gc,
+				purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 					_("Unable to establish SSL connection"));
 			}
 		} else {
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 			    PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 			    _("SSL support unavailable"));
 		}
 	} else if (purple_proxy_connect(conn, account, bosh->host, bosh->port,
 	                                 connection_established_cb, conn) == NULL) {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 		    PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		    _("Unable to connect"));
 	}
@@ -1023,7 +1023,7 @@
 		 */
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(conn->bosh->js->gc,
+		purple_connection_error(conn->bosh->js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				tmp);
 		g_free(tmp);
@@ -1079,7 +1079,7 @@
 		 */
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(conn->bosh->js->gc,
+		purple_connection_error(conn->bosh->js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				tmp);
 		g_free(tmp);
--- a/libpurple/protocols/jabber/buddy.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Mon Oct 31 01:25:36 2011 +0000
@@ -465,10 +465,22 @@
 	xmlnode *vc_node;
 	const struct tag_attr *tag_attr;
 
-	/* if we have't grabbed the remote vcard yet, we can't
+	/* if we haven't grabbed the remote vcard yet, we can't
 	 * assume that what we have here is correct */
-	if(!js->vcard_fetched)
+	if(!js->vcard_fetched) {
+		PurpleStoredImage *image;
+		g_free(js->initial_avatar_hash);
+		image = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc));
+		if (image != NULL) {
+			js->initial_avatar_hash =
+					jabber_calculate_data_hash(purple_imgstore_get_data(image),
+					purple_imgstore_get_size(image), "sha1");
+			purple_imgstore_unref(image);
+		} else {
+			js->initial_avatar_hash = NULL;
+		}
 		return;
+	}
 
 	if (js->vcard_timer) {
 		purple_timeout_remove(js->vcard_timer);
@@ -489,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;
@@ -545,7 +557,7 @@
 	PurpleAccount *account = purple_connection_get_account(gc);
 
 	/* Publish the avatar as specified in XEP-0084 */
-	jabber_avatar_set(gc->proto_data, img);
+	jabber_avatar_set(purple_connection_get_protocol_data(gc), img);
 	/* Set the image in our vCard */
 	jabber_set_info(gc, purple_account_get_user_info(account));
 
@@ -630,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);
 
 	/*
@@ -719,11 +731,16 @@
 			g_strdup_printf("%s%s%s", jbr->client.name,
 		                    (jbr->client.version ? " " : ""),
 		                    (jbr->client.version ? jbr->client.version : ""));
-		purple_notify_user_info_prepend_pair(user_info, _("Client"), tmp);
+		/* TODO: Check whether it's correct to call prepend_pair_html,
+		         or if we should be using prepend_pair_plaintext */
+		purple_notify_user_info_prepend_pair_html(user_info, _("Client"), tmp);
 		g_free(tmp);
 
-		if (jbr->client.os)
-			purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os);
+		if (jbr->client.os) {
+			/* TODO: Check whether it's correct to call prepend_pair_html,
+			         or if we should be using prepend_pair_plaintext */
+			purple_notify_user_info_prepend_pair_html(user_info, _("Operating System"), jbr->client.os);
+		}
 	}
 
 	if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) {
@@ -739,13 +756,13 @@
 		                    jbr->tz_off < 0 ? '-' : '+',
 		                    abs(jbr->tz_off / (60*60)),
 		                    abs((jbr->tz_off % (60*60)) / 60));
-		purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp);
+		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Local Time"), timestamp);
 		g_free(timestamp);
 	}
 
 	if (jbir && jbir->idle_seconds > 0) {
 		char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
-		purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle);
+		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Idle"), idle);
 		g_free(idle);
 	}
 
@@ -767,15 +784,15 @@
 		tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""),
 						((status_name && purdy) ? ": " : ""),
 						(purdy ? purdy : ""));
-		purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp);
+		purple_notify_user_info_prepend_pair_html(user_info, _("Status"), tmp);
 
 		g_snprintf(priority, sizeof(priority), "%d", jbr->priority);
-		purple_notify_user_info_prepend_pair(user_info, _("Priority"), priority);
+		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Priority"), priority);
 
 		g_free(tmp);
 		g_free(purdy);
 	} else {
-		purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown"));
+		purple_notify_user_info_prepend_pair_plaintext(user_info, _("Status"), _("Unknown"));
 	}
 }
 
@@ -794,7 +811,7 @@
 	resource_name = jabber_get_resource(jbi->jid);
 
 	/* If we have one or more pairs from the vcard, put a section break above it */
-	if (purple_notify_user_info_get_entries(user_info))
+	if (g_queue_get_length(purple_notify_user_info_get_entries(user_info)))
 		purple_notify_user_info_prepend_section_break(user_info);
 
 	/* Add the information about the user's resource(s) */
@@ -815,8 +832,11 @@
 
 			add_jbr_info(jbi, jbr->name, jbr);
 
-			if (jbr->name)
-				purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name);
+			if (jbr->name) {
+				/* TODO: Check whether it's correct to call prepend_pair_html,
+				         or if we should be using prepend_pair_plaintext */
+				purple_notify_user_info_prepend_pair_html(user_info, _("Resource"), jbr->name);
+			}
 		}
 	}
 
@@ -836,7 +856,7 @@
 				title = _("Logged Off");
 				message = g_strdup_printf(_("%s ago"), last);
 			}
-			purple_notify_user_info_prepend_pair(user_info, title, message);
+			purple_notify_user_info_prepend_pair_plaintext(user_info, title, message);
 			g_free(last);
 			g_free(message);
 		}
@@ -846,7 +866,9 @@
 				g_strdup_printf("%s%s%s",	_("Offline"),
 				                jbi->last_message ? ": " : "",
 				                jbi->last_message ? jbi->last_message : "");
-			purple_notify_user_info_prepend_pair(user_info, _("Status"), status);
+			/* TODO: Check whether it's correct to call prepend_pair_html,
+			         or if we should be using prepend_pair_plaintext */
+			purple_notify_user_info_prepend_pair_html(user_info, _("Status"), status);
 			g_free(status);
 		}
 	}
@@ -1124,7 +1146,7 @@
 						char *mailto;
 						escaped = g_markup_escape_text(userid, -1);
 						mailto = g_strdup_printf("<a href=\"mailto:%s\">%s</a>", escaped, escaped);
-						purple_notify_user_info_add_pair(user_info, _("Email"), mailto);
+						purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto);
 
 						g_free(mailto);
 						g_free(escaped);
@@ -1137,7 +1159,7 @@
 
 					escaped = g_markup_escape_text(userid, -1);
 					mailto = g_strdup_printf("<a href=\"mailto:%s\">%s</a>", escaped, escaped);
-					purple_notify_user_info_add_pair(user_info, _("Email"), mailto);
+					purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto);
 
 					g_free(mailto);
 					g_free(escaped);
@@ -1184,7 +1206,7 @@
 						jbi->vcard_imgids = g_slist_prepend(jbi->vcard_imgids, GINT_TO_POINTER(purple_imgstore_add_with_id(g_memdup(data, size), size, "logo.png")));
 						img_text = g_strdup_printf("<img id='%d'>", GPOINTER_TO_INT(jbi->vcard_imgids->data));
 
-						purple_notify_user_info_add_pair(user_info, (photo ? _("Photo") : _("Logo")), img_text);
+						purple_notify_user_info_add_pair_html(user_info, (photo ? _("Photo") : _("Logo")), img_text);
 
 						hash = jabber_calculate_data_hash(data, size, "sha1");
 						purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash);
@@ -1338,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);
 									}
 								}
@@ -2233,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");
@@ -2251,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/caps.c	Mon Oct 31 01:25:36 2011 +0000
@@ -958,7 +958,7 @@
 		const char *prpl_id = purple_account_get_protocol_id(account);
 		if (g_str_equal("prpl-jabber", prpl_id) && purple_account_is_connected(account)) {
 			PurpleConnection *gc = purple_account_get_connection(account);
-			jabber_presence_send(gc->proto_data, TRUE);
+			jabber_presence_send(purple_connection_get_protocol_data(gc), TRUE);
 		}
 	}
 
--- a/libpurple/protocols/jabber/chat.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/chat.c	Mon Oct 31 01:25:36 2011 +0000
@@ -70,7 +70,7 @@
 GHashTable *jabber_chat_info_defaults(PurpleConnection *gc, const char *chat_name)
 {
 	GHashTable *defaults;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
 
@@ -146,7 +146,7 @@
 	int id;
 	if (!gc)
 		return NULL;
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 	id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv));
 	return jabber_chat_find_by_id(js, id);
 }
@@ -154,7 +154,7 @@
 void jabber_chat_invite(PurpleConnection *gc, int id, const char *msg,
 		const char *name)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	JabberChat *chat;
 	xmlnode *message, *body, *x, *invite;
 	char *room_jid;
@@ -360,7 +360,7 @@
 {
 	char *room, *server, *handle, *passwd;
 	JabberID *jid;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	char *tmp;
 
 	room = g_hash_table_lookup(data, "room");
@@ -418,10 +418,9 @@
 
 void jabber_chat_leave(PurpleConnection *gc, int id)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	JabberChat *chat = jabber_chat_find_by_id(js, id);
 
-
 	if(!chat)
 		return;
 
@@ -459,7 +458,7 @@
 
 char *jabber_chat_buddy_real_name(PurpleConnection *gc, int id, const char *who)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	JabberChat *chat;
 	JabberChatMember *jcm;
 
@@ -887,13 +886,13 @@
 
 char *jabber_roomlist_room_serialize(PurpleRoomlistRoom *room)
 {
-
-	return g_strdup_printf("%s@%s", (char*)room->fields->data, (char*)room->fields->next->data);
+	GList *fields = purple_roomlist_room_get_fields(room);
+	return g_strdup_printf("%s@%s", (char*)fields->data, (char*)fields->next->data);
 }
 
 PurpleRoomlist *jabber_roomlist_get_list(PurpleConnection *gc)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	GList *fields = NULL;
 	PurpleRoomlistField *f;
 
@@ -928,11 +927,13 @@
 
 void jabber_roomlist_cancel(PurpleRoomlist *list)
 {
+	PurpleAccount *account;
 	PurpleConnection *gc;
 	JabberStream *js;
 
-	gc = purple_account_get_connection(list->account);
-	js = gc->proto_data;
+	account = purple_roomlist_get_account(list);
+	gc = purple_account_get_connection(account);
+	js = purple_connection_get_protocol_data(gc);
 
 	purple_roomlist_set_in_progress(list, FALSE);
 
--- a/libpurple/protocols/jabber/disco.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/disco.c	Mon Oct 31 01:25:36 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;
@@ -485,7 +485,7 @@
 			resp[0].hostname, resp[0].port);
 		account = purple_connection_get_account(js->gc);
 		js->stun_query =
-			purple_dnsquery_a_account(account, resp[0].hostname, resp[0].port,
+			purple_dnsquery_a(account, resp[0].hostname, resp[0].port,
 				jabber_disco_stun_lookup_cb, js);
 	}
 }
@@ -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;
@@ -550,7 +552,7 @@
 		} else if (purple_network_get_stun_ip() == NULL ||
 		    purple_strequal(purple_network_get_stun_ip(), "")) {
 			js->srv_query_data =
-				purple_srv_resolve_account(
+				purple_srv_resolve(
 					purple_connection_get_account(js->gc), "stun", "udp",
 					js->user->domain,
 					jabber_disco_stun_srv_resolve_cb, js);
--- a/libpurple/protocols/jabber/google/gmail.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/google/gmail.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/google/google_presence.c	Mon Oct 31 01:25:36 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/google/jingleinfo.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/google/jingleinfo.c	Mon Oct 31 01:25:36 2011 +0000
@@ -117,7 +117,7 @@
 					purple_dnsquery_destroy(js->stun_query);
 
 				account = purple_connection_get_account(js->gc);
-				js->stun_query = purple_dnsquery_a_account(account, host, port,
+				js->stun_query = purple_dnsquery_a(account, host, port,
 					jabber_google_stun_lookup_cb, js);
 			}
 		}
--- a/libpurple/protocols/jabber/google/relay.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/google/relay.c	Mon Oct 31 01:25:36 2011 +0000
@@ -137,7 +137,7 @@
 	purple_debug_info("jabber",
 		"sending Google relay request %s to %s\n", request, url);
 	url_data =
-		purple_util_fetch_url_request(url, FALSE, NULL, FALSE, request, FALSE,
+		purple_util_fetch_url_request(NULL, url, FALSE, NULL, FALSE, request, FALSE, -1,
 			jabber_google_relay_fetch_cb, data);
 	if (url_data) {
 		js->google_relay_requests =
--- a/libpurple/protocols/jabber/jabber.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Oct 31 01:25:36 2011 +0000
@@ -119,7 +119,7 @@
 		if(js->unregistration)
 			jabber_unregister_account_cb(js);
 	} else {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			("Error initializing session"));
 	}
@@ -153,7 +153,7 @@
 
 			js->user = jabber_id_new(full_jid);
 			if (js->user == NULL) {
-				purple_connection_error_reason(js->gc,
+				purple_connection_error(js->gc,
 					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					_("Invalid response from server"));
 				g_free(full_jid);
@@ -170,7 +170,7 @@
 	} else {
 		PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
 		char *msg = jabber_parse_error(js, packet, &reason);
-		purple_connection_error_reason(js->gc, reason, msg);
+		purple_connection_error(js->gc, reason, msg);
 		g_free(msg);
 
 		return;
@@ -247,14 +247,14 @@
 
 	starttls = xmlnode_get_child(packet, "starttls");
 	if(xmlnode_get_child(starttls, "required")) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("Server requires TLS/SSL, but no TLS/SSL support was found."));
 		return TRUE;
 	}
 
 	if (g_str_equal("require_tls", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("You require encryption, but no TLS/SSL support was found."));
 		return TRUE;
@@ -275,7 +275,7 @@
 			return;
 		}
 	} else if (g_str_equal(connection_security, "require_tls") && !jabber_stream_is_ssl(js)) {
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 			_("You require encryption, but it is not available on this server."));
 		return;
@@ -320,7 +320,7 @@
 	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
 	char *msg = jabber_parse_error(js, packet, &reason);
 
-	purple_connection_error_reason(js->gc, reason, msg);
+	purple_connection_error(js->gc, reason, msg);
 
 	g_free(msg);
 }
@@ -407,7 +407,7 @@
 	else if (ret <= 0) {
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
@@ -443,7 +443,7 @@
 		if (!account->disconnecting) {
 			gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 					g_strerror(errno));
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 			g_free(tmp);
 		}
@@ -544,7 +544,7 @@
 				purple_debug_error("jabber",
 					"sasl_encode error %d: %s\n", rc,
 					sasl_errdetail(js->sasl));
-				purple_connection_error_reason(gc,
+				purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					error);
 				g_free(error);
@@ -616,8 +616,8 @@
 
 static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
 {
-	JabberStream *js = gc->proto_data;
-	purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+	JabberStream *js = purple_connection_get_protocol_data(gc);
+	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					_("Ping timed out"));
 	js->keepalive_timeout = 0;
 	return FALSE;
@@ -642,7 +642,7 @@
 		PurpleInputCondition cond)
 {
 	PurpleConnection *gc = data;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	int len;
 	static char buf[4096];
 
@@ -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);
@@ -670,7 +670,7 @@
 		else
 			tmp = g_strdup_printf(_("Lost connection with server: %s"),
 					g_strerror(errno));
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 	}
@@ -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;
@@ -702,7 +702,7 @@
 				purple_debug_error("jabber",
 					"sasl_decode_error %d: %s\n", rc,
 					sasl_errdetail(js->sasl));
-				purple_connection_error_reason(gc,
+				purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					error);
 			} else if (olen > 0) {
@@ -728,7 +728,7 @@
 		else
 			tmp = g_strdup_printf(_("Lost connection with server: %s"),
 					g_strerror(errno));
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 	}
@@ -747,7 +747,7 @@
 		g_return_if_reached();
 	}
 
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 
 	if(js->state == JABBER_STREAM_CONNECTING)
 		jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
@@ -789,7 +789,7 @@
 	if (!found) {
 		purple_debug_warning("jabber", "Unable to find alternative XMPP connection "
 				  "methods after failing to connect directly.\n");
-		purple_connection_error_reason(js->gc,
+		purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to connect"));
 		return;
@@ -813,7 +813,7 @@
 			try_srv_connect(js);
 		} else {
 			purple_debug_info("jabber","Couldn't connect directly to %s.  Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
-			js->srv_query_data = purple_txt_resolve_account(
+			js->srv_query_data = purple_txt_resolve(
 					purple_connection_get_account(gc), "_xmppconnect",
 					js->user->domain, txt_resolved_cb, js);
 		}
@@ -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
@@ -842,7 +842,7 @@
 	/* If the connection is already disconnected, we don't need to do anything else */
 	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 	js->gsc = NULL;
 
 	purple_connection_ssl_error (gc, error);
@@ -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;
@@ -874,7 +874,7 @@
 	if (purple_proxy_connect(js->gc, purple_connection_get_account(js->gc),
 			host, port, jabber_login_callback, js->gc) == NULL) {
 		if (fatal_failure) {
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to connect"));
 		}
@@ -928,7 +928,8 @@
 	gchar *user;
 	gchar *slash;
 
-	js = gc->proto_data = g_new0(JabberStream, 1);
+	js = g_new0(JabberStream, 1);
+	purple_connection_set_protocol_data(gc, js);
 	js->gc = gc;
 	js->fd = -1;
 
@@ -940,7 +941,7 @@
 	js->user = jabber_id_new(user);
 
 	if (!js->user) {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("Invalid XMPP ID"));
 		g_free(user);
@@ -949,7 +950,7 @@
 	}
 
 	if (!js->user->node || *(js->user->node) == '\0') {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("Invalid XMPP ID. Username portion must be set."));
 		g_free(user);
@@ -958,7 +959,7 @@
 	}
 
 	if (!js->user->domain || *(js->user->domain) == '\0') {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("Invalid XMPP ID. Domain must be set."));
 		g_free(user);
@@ -978,7 +979,7 @@
 	g_free(user);
 	if (!js->user_jb) {
 		/* This basically *can't* fail, but for good measure... */
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("Invalid XMPP ID"));
 		/* Destroying the connection will free the JabberStream */
@@ -1037,7 +1038,7 @@
 		if (js->bosh)
 			jabber_bosh_connection_connect(js->bosh);
 		else {
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 				_("Malformed BOSH URL"));
 		}
@@ -1054,12 +1055,12 @@
 					purple_account_get_int(account, "port", 5223),
 					jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
 			if (!js->gsc) {
-				purple_connection_error_reason(gc,
+				purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 					_("Unable to establish SSL connection"));
 			}
 		} else {
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("SSL support unavailable"));
 		}
@@ -1073,7 +1074,7 @@
 		jabber_login_connect(js, js->user->domain, connect_server,
 				purple_account_get_int(account, "port", 5222), TRUE);
 	} else {
-		js->srv_query_data = purple_srv_resolve_account(account, "xmpp-client",
+		js->srv_query_data = purple_srv_resolve(account, "xmpp-client",
 				"tcp", js->user->domain, srv_resolved_cb, js);
 	}
 }
@@ -1085,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;
@@ -1264,7 +1264,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);
 			}
 		}
 	}
@@ -1273,7 +1273,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);
 	}
 
@@ -1422,7 +1422,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);
@@ -1556,17 +1556,17 @@
 	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 = gc->proto_data;
+		js = purple_connection_get_protocol_data(gc);
 		js->unregistration = TRUE;
 		js->unregistration_cb = cb;
 		js->unregistration_user_data = user_data;
 		return;
 	}
 
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 
 	if (js->unregistration) {
 		purple_debug_error("jabber", "Unregistration in process; ignoring duplicate request.\n");
@@ -1598,13 +1598,15 @@
 		jabber_send_raw(js, "</stream:stream>", -1);
 
 	if (js->srv_query_data)
-		purple_srv_cancel(js->srv_query_data);
+		purple_srv_txt_query_destroy(js->srv_query_data);
 
 	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);
 	}
 
@@ -1726,7 +1728,7 @@
 
 	g_free(js);
 
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 }
 
 void jabber_stream_set_state(JabberStream *js, JabberStreamState state)
@@ -1780,7 +1782,7 @@
 
 void jabber_idle_set(PurpleConnection *gc, int idle)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	js->idle = idle ? time(NULL) - idle : idle;
 
@@ -1871,8 +1873,7 @@
 		return;
 
 	/* This is the only privacy method supported by XEP-0191 */
-	if (account->perm_deny != PURPLE_PRIVACY_DENY_USERS)
-		account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+	purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
 
 	/*
 	 * TODO: When account->deny is something more than a hash table, this can
@@ -2133,7 +2134,7 @@
 	if(!gc)
 		return NULL;
 
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 	if(js)
 		jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
 
@@ -2174,8 +2175,8 @@
 	PurpleAccount *account = purple_buddy_get_account(b);
 	PurpleConnection *gc = purple_account_get_connection(account);
 
-	if (gc && gc->proto_data)
-		jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE);
+	if (gc && purple_connection_get_protocol_data(gc))
+		jb = jabber_buddy_find(purple_connection_get_protocol_data(gc), purple_buddy_get_name(b), FALSE);
 
 	if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) {
 		ret = g_strdup(_("Not Authorized"));
@@ -2225,7 +2226,7 @@
 	label = g_strdup_printf("%s%s", _("Status"), (res ? res : ""));
 	value = g_strdup_printf("%s%s%s", state, (text ? ": " : ""), (text ? text : ""));
 
-	purple_notify_user_info_add_pair(user_info, label, value);
+	purple_notify_user_info_add_pair_html(user_info, label, value);
 	g_free(label);
 	g_free(value);
 	g_free(text);
@@ -2238,7 +2239,7 @@
 		gchar *idle_str =
 			purple_str_seconds_to_string(time(NULL) - jbr->idle);
 		label = g_strdup_printf("%s%s", _("Idle"), (res ? res : ""));
-		purple_notify_user_info_add_pair(user_info, label, idle_str);
+		purple_notify_user_info_add_pair_plaintext(user_info, label, idle_str);
 		g_free(idle_str);
 		g_free(label);
 	}
@@ -2250,6 +2251,7 @@
 	JabberBuddy *jb;
 	PurpleAccount *account;
 	PurpleConnection *gc;
+	JabberStream *js;
 
 	g_return_if_fail(b != NULL);
 
@@ -2258,9 +2260,11 @@
 
 	gc = purple_account_get_connection(account);
 	g_return_if_fail(gc != NULL);
-	g_return_if_fail(gc->proto_data != NULL);
-
-	jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE);
+
+	js = purple_connection_get_protocol_data(gc);
+	g_return_if_fail(js != NULL);
+
+	jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
 
 	if(jb) {
 		JabberBuddyResource *jbr = NULL;
@@ -2310,10 +2314,10 @@
 					char *moodplustext =
 						g_strdup_printf("%s (%s)", description ? _(description) : mood, moodtext);
 
-					purple_notify_user_info_add_pair(user_info, _("Mood"), moodplustext);
+					purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodplustext);
 					g_free(moodplustext);
 				} else
-					purple_notify_user_info_add_pair(user_info, _("Mood"),
+					purple_notify_user_info_add_pair_html(user_info, _("Mood"),
 					    description ? _(description) : mood);
 			}
 			if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
@@ -2323,7 +2327,7 @@
 				const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
 				char *playing = purple_util_format_song_info(title, artist, album, NULL);
 				if (playing) {
-					purple_notify_user_info_add_pair(user_info, _("Now Listening"), playing);
+					purple_notify_user_info_add_pair_html(user_info, _("Now Listening"), playing);
 					g_free(playing);
 				}
 			}
@@ -2344,12 +2348,12 @@
 					sub = _("None");
 			}
 
-			purple_notify_user_info_add_pair(user_info, _("Subscription"), sub);
+			purple_notify_user_info_add_pair_html(user_info, _("Subscription"), sub);
 
 		}
 
 		if(!PURPLE_BUDDY_IS_ONLINE(b) && jb->error_msg) {
-			purple_notify_user_info_add_pair(user_info, _("Error"), jb->error_msg);
+			purple_notify_user_info_add_pair_html(user_info, _("Error"), jb->error_msg);
 		}
 	}
 }
@@ -2484,7 +2488,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);
 
@@ -2531,7 +2535,7 @@
 {
 
 	PurpleConnection *gc = (PurpleConnection *) action->context;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
@@ -2563,7 +2567,7 @@
 GList *jabber_actions(PurplePlugin *plugin, gpointer context)
 {
 	PurpleConnection *gc = (PurpleConnection *) context;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	GList *m = NULL;
 	PurplePluginAction *act;
 
@@ -2634,7 +2638,7 @@
 
 void jabber_convo_closed(PurpleConnection *gc, const char *who)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	JabberID *jid;
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
@@ -2739,8 +2743,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");
@@ -2997,7 +3001,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]);
 
@@ -3044,7 +3048,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);
@@ -3078,7 +3082,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;
@@ -3159,13 +3163,14 @@
 static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv,
 		const char *cmd, char **args, char **error, void *data)
 {
-	JabberStream *js = conv->account->gc->proto_data;
+	PurpleAccount *account = purple_conversation_get_account(conv);
+	JabberStream *js = purple_connection_get_protocol_data(purple_account_get_connection(account));
 	const gchar *who;
 	gchar *description;
 	PurpleBuddy *buddy;
 	const char *alias;
 	PurpleAttentionType *attn =
-		purple_get_attention_type_from_code(conv->account, 0);
+		purple_get_attention_type_from_code(account, 0);
 
 	if (!args || !args[0]) {
 		/* use the buddy from conversation, if it's a one-to-one conversation */
@@ -3178,7 +3183,7 @@
 		who = args[0];
 	}
 
-	buddy = purple_find_buddy(conv->account, who);
+	buddy = purple_find_buddy(account, who);
 	if (buddy != NULL)
 		alias = purple_buddy_get_contact_alias(buddy);
 	else
@@ -3206,7 +3211,7 @@
 
 gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	gchar *error = NULL;
 
 	if (!_jabber_send_buzz(js, username, &error)) {
@@ -3289,8 +3294,8 @@
 		      PurpleMediaSessionType type)
 {
 #ifdef USE_VV
-	JabberStream *js = (JabberStream *)
-			purple_account_get_connection(account)->proto_data;
+	PurpleConnection *gc = purple_account_get_connection(account);
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr = NULL;
 	char *resource;
@@ -3301,7 +3306,6 @@
 		return FALSE;
 	}
 
-
 	if((resource = jabber_get_resource(who)) != NULL) {
 		/* they've specified a resource, no need to ask or
 		 * default or anything, just do it */
@@ -3432,8 +3436,8 @@
 PurpleMediaCaps jabber_get_media_caps(PurpleAccount *account, const char *who)
 {
 #ifdef USE_VV
-	JabberStream *js = (JabberStream *)
-			purple_account_get_connection(account)->proto_data;
+	PurpleConnection *gc = purple_account_get_connection(account);
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
 	PurpleMediaCaps total = PURPLE_MEDIA_CAPS_NONE;
@@ -3521,7 +3525,7 @@
 
 gboolean jabber_can_receive_file(PurpleConnection *gc, const char *who)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	if (js) {
 		JabberBuddy *jb = jabber_buddy_find(js, who, FALSE);
@@ -3571,7 +3575,8 @@
 jabber_cmd_mood(PurpleConversation *conv,
 		const char *cmd, char **args, char **error, void *data)
 {
-	JabberStream *js = conv->account->gc->proto_data;
+	PurpleAccount *account = purple_conversation_get_account(conv);
+	JabberStream *js = purple_connection_get_protocol_data(purple_account_get_connection(account));
 
 	if (js->pep) {
 		/* if no argument was given, unset mood */
@@ -3755,7 +3760,7 @@
 
 	if (!purple_account_is_connected(account))
 		return FALSE;
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 
 	if (!(resource = jabber_get_resource(jid)) ||
 	    !(jb = jabber_buddy_find(js, jid, FALSE)) ||
--- a/libpurple/protocols/jabber/jabber.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Mon Oct 31 01:25:36 2011 +0000
@@ -99,6 +99,7 @@
 struct _JabberStream
 {
 	int fd;
+	guint inpa;
 
 	PurpleSrvTxtQueryData *srv_query_data;
 
--- a/libpurple/protocols/jabber/jutil.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/jutil.c	Mon Oct 31 01:25:36 2011 +0000
@@ -583,11 +583,16 @@
 
 const char *jabber_normalize(const PurpleAccount *account, const char *in)
 {
-	PurpleConnection *gc = account ? account->gc : NULL;
-	JabberStream *js = gc ? gc->proto_data : NULL;
+	PurpleConnection *gc = NULL;
+	JabberStream *js = NULL;
 	static char buf[3072]; /* maximum legal length of a jabber jid */
 	JabberID *jid;
 
+	if (account)
+		gc = purple_account_get_connection(account);
+	if (gc)
+		js = purple_connection_get_protocol_data(gc);
+
 	jid = jabber_id_new_internal(in, TRUE);
 	if(!jid)
 		return NULL;
--- a/libpurple/protocols/jabber/libxmpp.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Oct 31 01:25:36 2011 +0000
@@ -53,6 +53,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK |
 #ifdef HAVE_CYRUS_SASL
 	OPT_PROTO_PASSWORD_OPTIONAL |
@@ -97,7 +98,6 @@
 	jabber_keepalive,				/* keepalive */
 	jabber_register_account,		/* register_user */
 	NULL,							/* get_cb_info */
-	NULL,							/* get_cb_away */
 	jabber_roster_alias_change,		/* alias_buddy */
 	jabber_roster_group_change,		/* group_buddy */
 	jabber_roster_group_rename,		/* rename_group */
@@ -122,16 +122,12 @@
 	jabber_unregister_account,		/* unregister_user */
 	jabber_send_attention,			/* send_attention */
 	jabber_attention_types,			/* attention_types */
-
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL, /* get_account_text_table */
 	jabber_initiate_media,          /* initiate_media */
 	jabber_get_media_caps,                  /* get_media_caps */
 	jabber_get_moods,  							/* get_moods */
 	NULL, /* set_public_alias */
-	NULL, /* get_public_alias */
-	NULL, /* add_buddy_with_invite */
-	NULL  /* add_buddies_with_invite */
+	NULL  /* get_public_alias */
 };
 
 static gboolean load_plugin(PurplePlugin *plugin)
--- a/libpurple/protocols/jabber/message.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/message.c	Mon Oct 31 01:25:36 2011 +0000
@@ -638,6 +638,8 @@
 					jabber_message_add_remote_smileys(js, to, packet);
 				}
 
+				xmlnode_strip_prefixes(child);
+
 				/* reformat xhtml so that img tags with a "cid:" src gets
 				  translated to the bare text of the emoticon (the "alt" attrib) */
 				/* this is done also when custom smiley retrieval is turned off,
@@ -1148,13 +1150,13 @@
 
 	resource = jabber_get_resource(who);
 
-	jb = jabber_buddy_find(gc->proto_data, who, TRUE);
+	jb = jabber_buddy_find(purple_connection_get_protocol_data(gc), who, TRUE);
 	jbr = jabber_buddy_find_resource(jb, resource);
 
 	g_free(resource);
 
 	jm = g_new0(JabberMessage, 1);
-	jm->js = gc->proto_data;
+	jm->js = purple_connection_get_protocol_data(gc);
 	jm->type = JABBER_MESSAGE_CHAT;
 	jm->chat_state = JM_STATE_ACTIVE;
 	jm->to = g_strdup(who);
@@ -1211,14 +1213,14 @@
 	if(!msg || !gc)
 		return 0;
 
-	js = gc->proto_data;
+	js = purple_connection_get_protocol_data(gc);
 	chat = jabber_chat_find_by_id(js, id);
 
 	if(!chat)
 		return 0;
 
 	jm = g_new0(JabberMessage, 1);
-	jm->js = gc->proto_data;
+	jm->js = purple_connection_get_protocol_data(gc);
 	jm->type = JABBER_MESSAGE_GROUPCHAT;
 	jm->to = g_strdup_printf("%s@%s", chat->room, chat->server);
 	jm->id = jabber_get_next_id(jm->js);
--- a/libpurple/protocols/jabber/oob.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/oob.c	Mon Oct 31 01:25:36 2011 +0000
@@ -48,13 +48,13 @@
 
 static void jabber_oob_xfer_init(PurpleXfer *xfer)
 {
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 	purple_xfer_start(xfer, -1, jox->address, jox->port);
 }
 
 static void jabber_oob_xfer_free(PurpleXfer *xfer)
 {
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 	jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers,
 			xfer);
 
@@ -67,16 +67,16 @@
 		purple_input_remove(jox->writeh);
 	g_free(jox);
 
-	xfer->data = NULL;
+	purple_xfer_set_protocol_data(xfer, NULL);
 }
 
 static void jabber_oob_xfer_end(PurpleXfer *xfer)
 {
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 	JabberIq *iq;
 
 	iq = jabber_iq_new(jox->js, JABBER_IQ_RESULT);
-	xmlnode_set_attrib(iq->node, "to", xfer->who);
+	xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 	jabber_iq_set_id(iq, jox->iq_id);
 
 	jabber_iq_send(iq);
@@ -86,10 +86,10 @@
 
 static void jabber_oob_xfer_request_send(gpointer data, gint source, PurpleInputCondition cond) {
 	PurpleXfer *xfer = data;
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 	int len, total_len = strlen(jox->write_buffer);
 
-	len = write(xfer->fd, jox->write_buffer + jox->written_len,
+	len = purple_xfer_write(xfer, (guchar*) jox->write_buffer + jox->written_len,
 		total_len - jox->written_len);
 
 	if(len < 0 && errno == EAGAIN)
@@ -110,7 +110,7 @@
 
 static void jabber_oob_xfer_start(PurpleXfer *xfer)
 {
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 
 	if(jox->write_buffer == NULL) {
 		jox->write_buffer = g_strdup_printf(
@@ -119,26 +119,26 @@
 		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) {
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 	char test[2048];
 	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);
@@ -158,12 +158,12 @@
 }
 
 static void jabber_oob_xfer_recv_error(PurpleXfer *xfer, const char *code) {
-	JabberOOBXfer *jox = xfer->data;
+	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 	JabberIq *iq;
 	xmlnode *y, *z;
 
 	iq = jabber_iq_new(jox->js, JABBER_IQ_ERROR);
-	xmlnode_set_attrib(iq->node, "to", xfer->who);
+	xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 	jabber_iq_set_id(iq, jox->iq_id);
 	y = xmlnode_new_child(iq->node, "error");
 	xmlnode_set_attrib(y, "code", code);
@@ -218,10 +218,10 @@
 	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)
 	{
-		xfer->data = jox;
+		purple_xfer_set_protocol_data(xfer, jox);
 
 		if(!(filename = g_strdup(g_strrstr(jox->page, "/"))))
 			filename = g_strdup(jox->page);
--- a/libpurple/protocols/jabber/parser.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/parser.c	Mon Oct 31 01:25:36 2011 +0000
@@ -52,7 +52,7 @@
 			 */
 			purple_debug_error("jabber", "Expecting stream header, got %s with "
 			                   "xmlns %s\n", element_name, namespace);
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 					_("XMPP stream header missing"));
 			return;
@@ -73,7 +73,7 @@
 
 				if (js->protocol_version.major > 1) {
 					/* TODO: Send <unsupported-version/> error */
-					purple_connection_error_reason(js->gc,
+					purple_connection_error(js->gc,
 							PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 							_("XMPP Version Mismatch"));
 					g_free(attrib);
@@ -98,7 +98,7 @@
 			/* This was underspecified in rfc3920 as only being a SHOULD, so
 			 * we cannot rely on it.  See #12331 and Oracle's server.
 			 */
-			purple_connection_error_reason(js->gc,
+			purple_connection_error(js->gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
 					_("XMPP stream missing ID"));
 #else
@@ -300,7 +300,7 @@
 				break;
 			case XML_ERR_FATAL:
 				purple_debug_error("jabber", "xmlParseChunk returned fatal %i\n", ret);
-				purple_connection_error_reason (js->gc,
+				purple_connection_error (js->gc,
 				                                PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				                                _("XML Parse error"));
 				break;
--- a/libpurple/protocols/jabber/presence.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/presence.c	Mon Oct 31 01:25:36 2011 +0000
@@ -299,11 +299,6 @@
 	jabber_presence_fake_to_self(js, status);
 }
 
-xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority)
-{
-    return jabber_presence_create_js(NULL, state, msg, priority);
-}
-
 xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority)
 {
 	xmlnode *show, *status, *presence, *pri, *c;
@@ -393,7 +388,7 @@
 {
 	struct _jabber_add_permit *jap = data;
 	if(PURPLE_CONNECTION_IS_VALID(jap->gc))
-		jabber_presence_subscription_set(jap->gc->proto_data,
+		jabber_presence_subscription_set(purple_connection_get_protocol_data(jap->gc),
 			jap->who, "subscribed");
 	g_free(jap->who);
 	g_free(jap);
@@ -403,7 +398,7 @@
 {
 	struct _jabber_add_permit *jap = data;
 	if(PURPLE_CONNECTION_IS_VALID(jap->gc))
-		jabber_presence_subscription_set(jap->gc->proto_data,
+		jabber_presence_subscription_set(purple_connection_get_protocol_data(jap->gc),
 			jap->who, "unsubscribed");
 	g_free(jap->who);
 	g_free(jap);
@@ -464,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/presence.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/presence.h	Mon Oct 31 01:25:36 2011 +0000
@@ -92,7 +92,6 @@
  */
 void jabber_presence_send(JabberStream *js, gboolean force);
 
-xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority); /* DEPRECATED */
 xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority);
 void jabber_presence_parse(JabberStream *js, xmlnode *packet);
 void jabber_presence_subscription_set(JabberStream *js, const char *who,
--- a/libpurple/protocols/jabber/roster.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/roster.c	Mon Oct 31 01:25:36 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)
@@ -358,9 +358,9 @@
 }
 
 void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
-		PurpleGroup *group)
+		PurpleGroup *group, const char *message)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	char *who;
 	JabberID *jid;
 	JabberBuddy *jb;
@@ -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);
@@ -431,7 +431,7 @@
 		purple_debug_info("jabber", "jabber_roster_alias_change(): Aliased %s to %s\n",
 				name, alias ? alias : "(null)");
 
-		jabber_roster_update(gc->proto_data, name, NULL);
+		jabber_roster_update(purple_connection_get_protocol_data(gc), name, NULL);
 	}
 }
 
@@ -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);
@@ -461,7 +461,7 @@
 	purple_debug_info("jabber", "jabber_roster_group_change(): Moving %s from %s to %s\n",
 	                  name, old_group, new_group);
 
-	jabber_roster_update(gc->proto_data, name, groups);
+	jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups);
 }
 
 void jabber_roster_group_rename(PurpleConnection *gc, const char *old_name,
@@ -496,9 +496,9 @@
 		purple_debug_info("jabber", "jabber_roster_remove_buddy(): Removing %s from %s\n",
 		                  purple_buddy_get_name(buddy), purple_group_get_name(group));
 
-		jabber_roster_update(gc->proto_data, name, groups);
+		jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups);
 	} else {
-		JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET,
+		JabberIq *iq = jabber_iq_new_query(purple_connection_get_protocol_data(gc), JABBER_IQ_SET,
 				"jabber:iq:roster");
 		xmlnode *query = xmlnode_get_child(iq->node, "query");
 		xmlnode *item = xmlnode_new_child(query, "item");
--- a/libpurple/protocols/jabber/roster.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/roster.h	Mon Oct 31 01:25:36 2011 +0000
@@ -32,7 +32,7 @@
                          JabberIqType type, const char *id, xmlnode *query);
 
 void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
-		PurpleGroup *group);
+		PurpleGroup *group, const char *message);
 void jabber_roster_alias_change(PurpleConnection *gc, const char *name,
 		const char *alias);
 void jabber_roster_group_change(PurpleConnection *gc, const char *name,
--- a/libpurple/protocols/jabber/si.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/si.c	Mon Oct 31 01:25:36 2011 +0000
@@ -87,9 +87,9 @@
 
 	for(xfers = js->file_transfers; xfers; xfers = xfers->next) {
 		PurpleXfer *xfer = xfers->data;
-		JabberSIXfer *jsx = xfer->data;
-		if(jsx->stream_id && xfer->who &&
-				!strcmp(jsx->stream_id, sid) && !strcmp(xfer->who, from))
+		JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
+		if(jsx->stream_id && purple_xfer_get_remote_user(xfer) &&
+				!strcmp(jsx->stream_id, sid) && !strcmp(purple_xfer_get_remote_user(xfer), from))
 			return xfer;
 	}
 
@@ -118,7 +118,7 @@
 jabber_si_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	JabberIq *iq;
 	xmlnode *query, *su;
 	JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data;
@@ -143,7 +143,7 @@
 	}
 
 	/* unknown file transfer type is assumed to be RECEIVE */
-	if(xfer->type == PURPLE_XFER_SEND)
+	if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
 	{
 		xmlnode *activate;
 		iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS);
@@ -151,14 +151,14 @@
 		query = xmlnode_get_child(iq->node, "query");
 		xmlnode_set_attrib(query, "sid", jsx->stream_id);
 		activate = xmlnode_new_child(query, "activate");
-		xmlnode_insert_data(activate, xfer->who, -1);
+		xmlnode_insert_data(activate, purple_xfer_get_remote_user(xfer), -1);
 
 		/* TODO: We need to wait for an activation result before starting */
 	}
 	else
 	{
 		iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, NS_BYTESTREAMS);
-		xmlnode_set_attrib(iq->node, "to", xfer->who);
+		xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 		jabber_iq_set_id(iq, jsx->iq_id);
 		query = xmlnode_get_child(iq->node, "query");
 		su = xmlnode_new_child(query, "streamhost-used");
@@ -174,7 +174,7 @@
 connect_timeout_cb(gpointer data)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	purple_debug_info("jabber", "Streamhost connection timeout of %d seconds exceeded.\n", STREAMHOST_CONNECT_TIMEOUT);
 
@@ -203,7 +203,7 @@
 jabber_si_bytestreams_ibb_timeout_cb(gpointer data)
 {
 	PurpleXfer *xfer = (PurpleXfer *) data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	if (jsx && !jsx->ibb_session) {
 		purple_debug_info("jabber",
@@ -218,7 +218,7 @@
 
 static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	JabberBytestreamsStreamhost *streamhost;
 	JabberID *dstjid;
 
@@ -229,7 +229,7 @@
 		if(jsx->iq_id)
 			jabber_iq_set_id(iq, jsx->iq_id);
 
-		xmlnode_set_attrib(iq->node, "to", xfer->who);
+		xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 		error = xmlnode_new_child(iq->node, "error");
 		xmlnode_set_attrib(error, "code", "404");
 		xmlnode_set_attrib(error, "type", "cancel");
@@ -271,7 +271,7 @@
 		purple_proxy_info_destroy(jsx->gpi);
 	jsx->gpi = NULL;
 
-	dstjid = jabber_id_new(xfer->who);
+	dstjid = jabber_id_new(purple_xfer_get_remote_user(xfer));
 
 	/* TODO: Deal with zeroconf */
 
@@ -284,7 +284,7 @@
 		purple_proxy_info_set_port(jsx->gpi, streamhost->port);
 
 		/* unknown file transfer type is assumed to be RECEIVE */
-		if(xfer->type == PURPLE_XFER_SEND)
+		if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
 			dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, jsx->js->user->node, jsx->js->user->domain,
 				jsx->js->user->resource, dstjid->node, dstjid->domain, dstjid->resource);
 		else
@@ -302,7 +302,7 @@
 		g_free(dstaddr);
 
 		/* When selecting a streamhost, timeout after STREAMHOST_CONNECT_TIMEOUT seconds, otherwise it takes forever */
-		if (xfer->type != PURPLE_XFER_SEND && jsx->connect_data != NULL)
+		if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND && jsx->connect_data != NULL)
 			jsx->connect_timeout = purple_timeout_add_seconds(
 				STREAMHOST_CONNECT_TIMEOUT, connect_timeout_cb, xfer);
 
@@ -337,7 +337,7 @@
 	if(!(xfer = jabber_si_xfer_find(js, sid, from)))
 		return;
 
-	jsx = xfer->data;
+	jsx = purple_xfer_get_protocol_data(xfer);
 
 	if(!jsx->accepted)
 		return;
@@ -375,15 +375,13 @@
 		PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	int len;
 
 	len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);
 	if (len < 0 && errno == EAGAIN)
 		return;
 	else if (len < 0) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
 		g_free(jsx->rxqueue);
 		jsx->rxqueue = NULL;
 		close(source);
@@ -395,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;
 
@@ -412,7 +410,7 @@
 		PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/
 	int len;
 	char *dstaddr, *hash;
@@ -426,8 +424,6 @@
 		if(len < 0 && errno == EAGAIN)
 			return;
 		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
 			close(source);
 			purple_xfer_cancel_remote(xfer);
 			return;
@@ -441,8 +437,6 @@
 		purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n",
 				  jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2],
 				  jsx->rxqueue[3], jsx->rxqueue[4]);
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
 		close(source);
 		purple_xfer_cancel_remote(xfer);
 		return;
@@ -455,8 +449,6 @@
 		if(len < 0 && errno == EAGAIN)
 			return;
 		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
 			close(source);
 			purple_xfer_cancel_remote(xfer);
 			return;
@@ -470,12 +462,12 @@
 	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,
-			jsx->js->user->resource, xfer->who);
+			jsx->js->user->resource, purple_xfer_get_remote_user(xfer));
 
 	/* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
 	hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1");
@@ -516,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);
 }
@@ -527,15 +519,13 @@
 		PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	int len;
 
 	len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);
 	if (len < 0 && errno == EAGAIN)
 		return;
 	else if (len < 0) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
 		g_free(jsx->rxqueue);
 		jsx->rxqueue = NULL;
 		close(source);
@@ -547,13 +537,11 @@
 	if (jsx->rxlen < jsx->rxmaxlen)
 		return;
 
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
 	/* If we sent a "Success", wait for a response, otherwise give up and cancel */
 	if (jsx->rxqueue[1] == 0x00) {
-		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;
@@ -568,14 +556,14 @@
 		PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	int i;
 	int len;
 	char buffer[256];
 
 	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) {
@@ -584,9 +572,6 @@
 		if(len < 0 && errno == EAGAIN)
 			return;
 		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
 			purple_xfer_cancel_remote(xfer);
 			return;
 		}
@@ -603,9 +588,6 @@
 		if(len < 0 && errno == EAGAIN)
 			return;
 		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
 			purple_xfer_cancel_remote(xfer);
 			return;
 		}
@@ -618,13 +600,9 @@
 	if(jsx->rxlen -2 < jsx->rxqueue[1])
 		return;
 
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
 	purple_debug_info("jabber", "checking to make sure we're socks FIVE\n");
 
 	if(jsx->rxqueue[0] != 0x05) {
-		close(source);
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
@@ -641,9 +619,10 @@
 			jsx->rxqueue = g_malloc(jsx->rxmaxlen);
 			jsx->rxqueue[0] = 0x05;
 			jsx->rxqueue[1] = 0x00;
-			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;
@@ -658,8 +637,9 @@
 	jsx->rxqueue = g_malloc(jsx->rxmaxlen);
 	jsx->rxqueue[0] = 0x05;
 	jsx->rxqueue[1] = 0xFF;
-	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);
 }
@@ -680,7 +660,7 @@
 		PurpleInputCondition cond)
 {
 	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	int acceptfd, flags;
 
 	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n");
@@ -694,7 +674,7 @@
 		return;
 	}
 
-	purple_input_remove(xfer->watcher);
+	purple_input_remove(purple_xfer_get_watcher(xfer));
 	close(source);
 	jsx->local_streamhost_fd = -1;
 
@@ -704,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
@@ -727,12 +707,12 @@
 		return;
 	}
 
+	jsx = purple_xfer_get_protocol_data(xfer);
+
 	/* In the case of a direct file transfer, this is expected to return */
-	if(!xfer->data)
+	if(!jsx)
 		return;
 
-	jsx = xfer->data;
-
 	if(type != JABBER_IQ_RESULT) {
 		purple_debug_info("jabber",
 			    "jabber_si_xfer_connect_proxy_cb: type = error\n");
@@ -781,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) {
@@ -805,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);
@@ -835,7 +815,7 @@
 	JabberBytestreamsStreamhost *sh, *sh2;
 	int streamhost_count = 0;
 
-	jsx = xfer->data;
+	jsx = purple_xfer_get_protocol_data(xfer);
 	jsx->listen_data = NULL;
 
 	/* I'm not sure under which conditions this can happen
@@ -848,7 +828,7 @@
 	purple_xfer_unref(xfer);
 
 	iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS);
-	xmlnode_set_attrib(iq->node, "to", xfer->who);
+	xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 	query = xmlnode_get_child(iq->node, "query");
 
 	xmlnode_set_attrib(query, "sid", jsx->stream_id);
@@ -865,8 +845,8 @@
 
 		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);
-		g_snprintf(port, sizeof(port), "%hu", xfer->local_port);
+		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);
 
@@ -896,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) {
@@ -969,7 +949,7 @@
 
 	purple_xfer_ref(xfer);
 
-	jsx = xfer->data;
+	jsx = purple_xfer_get_protocol_data(xfer);
 
 	/* TODO: This should probably be done with an account option instead of
 	 *       piggy-backing on the TOR proxy type. */
@@ -979,7 +959,7 @@
 		purple_debug_info("jabber", "Skipping attempting local streamhost.\n");
 		jsx->listen_data = NULL;
 	} else
-		jsx->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM,
+		jsx->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE,
 				jabber_si_xfer_bytestreams_listen_cb, xfer);
 
 	if (jsx->listen_data == NULL) {
@@ -1017,7 +997,7 @@
 	gsize size)
 {
 	PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	if (size <= purple_xfer_get_bytes_remaining(xfer)) {
 		purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n",
@@ -1037,7 +1017,7 @@
 static gssize
 jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	guchar *buffer;
 	gsize size;
 	gsize tmp;
@@ -1060,7 +1040,7 @@
 	const gchar *sid = xmlnode_get_attrib(open, "sid");
 	PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who);
 	if (xfer) {
-		JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+		JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 		JabberIBBSession *sess =
 			jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer);
 
@@ -1105,7 +1085,7 @@
 static gssize
 jabber_si_xfer_ibb_write(const guchar *buffer, size_t len, PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	JabberIBBSession *sess = jsx->ibb_session;
 	gsize packet_size = len < jabber_ibb_session_get_max_data_size(sess) ?
 		len : jabber_ibb_session_get_max_data_size(sess);
@@ -1119,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 */
@@ -1149,7 +1129,7 @@
 static void
 jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id,
 		purple_xfer_get_remote_user(xfer), xfer);
@@ -1206,7 +1186,7 @@
 
 	for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) {
 		const char *var = xmlnode_get_attrib(field, "var");
-		JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+		JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 		if(var && !strcmp(var, "stream-method")) {
 			if((value = xmlnode_get_child(field, "value"))) {
@@ -1237,7 +1217,7 @@
 
 static void jabber_si_xfer_send_request(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	JabberIq *iq;
 	xmlnode *si, *file, *feature, *x, *field, *option, *value;
 	char buf[32];
@@ -1247,10 +1227,10 @@
 
 	purple_xfer_prepare_thumbnail(xfer, "jpeg,png");
 #endif
-	xfer->filename = g_path_get_basename(xfer->local_filename);
+	purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
 
 	iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
-	xmlnode_set_attrib(iq->node, "to", xfer->who);
+	xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 	si = xmlnode_new_child(iq->node, "si");
 	xmlnode_set_namespace(si, "http://jabber.org/protocol/si");
 	jsx->stream_id = jabber_get_next_id(jsx->js);
@@ -1259,8 +1239,8 @@
 
 	file = xmlnode_new_child(si, "file");
 	xmlnode_set_namespace(file, NS_SI_FILE_TRANSFER);
-	xmlnode_set_attrib(file, "name", xfer->filename);
-	g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size);
+	xmlnode_set_attrib(file, "name", purple_xfer_get_filename(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 */
 
@@ -1309,7 +1289,7 @@
 
 static void jabber_si_xfer_free(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	if (jsx) {
 		JabberStream *js = jsx->js;
@@ -1324,10 +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);
@@ -1356,7 +1335,7 @@
 		/* XXX: free other stuff */
 		g_free(jsx->rxqueue);
 		g_free(jsx);
-		xfer->data = NULL;
+		purple_xfer_set_protocol_data(xfer, NULL);
 	}
 }
 
@@ -1367,7 +1346,7 @@
  */
 static void jabber_si_xfer_cancel_send(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	/* if there is an IBB session active, send close on that */
 	if (jsx->ibb_session) {
@@ -1380,7 +1359,7 @@
 
 static void jabber_si_xfer_request_denied(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	JabberStream *js = jsx->js;
 
 	/*
@@ -1391,7 +1370,7 @@
 		JabberIq *iq;
 		xmlnode *error, *child;
 		iq = jabber_iq_new(js, JABBER_IQ_ERROR);
-		xmlnode_set_attrib(iq->node, "to", xfer->who);
+		xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 		jabber_iq_set_id(iq, jsx->iq_id);
 
 		error = xmlnode_new_child(iq->node, "error");
@@ -1412,7 +1391,7 @@
 
 static void jabber_si_xfer_cancel_recv(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	/* if there is an IBB session active, send close */
 	if (jsx->ibb_session) {
 		jabber_ibb_session_close(jsx->ibb_session);
@@ -1432,7 +1411,7 @@
 		JabberCapabilities capabilities, gpointer data)
 {
 	PurpleXfer *xfer = (PurpleXfer *) data;
-	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 
 	if (capabilities & JABBER_CAP_IBB) {
 		purple_debug_info("jabber",
@@ -1458,8 +1437,8 @@
 
 static void do_transfer_send(PurpleXfer *xfer, const char *resource)
 {
-	JabberSIXfer *jsx = xfer->data;
-	char **who_v = g_strsplit(xfer->who, "/", 2);
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
+	char **who_v = g_strsplit(purple_xfer_get_remote_user(xfer), "/", 2);
 	char *who;
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr = NULL;
@@ -1508,7 +1487,7 @@
 
 static void jabber_si_xfer_init(PurpleXfer *xfer)
 {
-	JabberSIXfer *jsx = xfer->data;
+	JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
 	JabberIq *iq;
 	if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
 		JabberBuddy *jb;
@@ -1516,7 +1495,7 @@
 		char *resource;
 		GList *resources = NULL;
 
-		if(NULL != (resource = jabber_get_resource(xfer->who))) {
+		if(NULL != (resource = jabber_get_resource(purple_xfer_get_remote_user(xfer)))) {
 			/* they've specified a resource, no need to ask or
 			 * default or anything, just do it */
 
@@ -1525,7 +1504,7 @@
 			return;
 		}
 
-		jb = jabber_buddy_find(jsx->js, xfer->who, TRUE);
+		jb = jabber_buddy_find(jsx->js, purple_xfer_get_remote_user(xfer), TRUE);
 
 		if (jb) {
 			GList *l;
@@ -1549,11 +1528,11 @@
 			char *msg;
 
 			if(!jb) {
-				msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who);
+				msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), purple_xfer_get_remote_user(xfer));
 			} else if(jb->subscription & JABBER_SUB_TO) {
-				msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who);
+				msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), purple_xfer_get_remote_user(xfer));
 			} else {
-				msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who);
+				msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), purple_xfer_get_remote_user(xfer));
 			}
 
 			purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg);
@@ -1566,7 +1545,7 @@
 		} else {
 			/* we've got multiple resources, we need to pick one to send to */
 			GList *l;
-			char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), xfer->who);
+			char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), purple_xfer_get_remote_user(xfer));
 			PurpleRequestFields *fields = purple_request_fields_new();
 			PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0);
 			PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
@@ -1582,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, xfer->who, NULL, xfer);
+					purple_connection_get_account(jsx->js->gc), purple_xfer_get_remote_user(xfer), NULL, xfer);
 
 			g_free(msg);
 		}
@@ -1592,7 +1571,7 @@
 		xmlnode *si, *feature, *x, *field, *value;
 
 		iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT);
-		xmlnode_set_attrib(iq->node, "to", xfer->who);
+		xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
 		if(jsx->iq_id)
 			jabber_iq_set_id(iq, jsx->iq_id);
 		else
@@ -1636,12 +1615,13 @@
 	PurpleXfer *xfer;
 	JabberSIXfer *jsx;
 
-	js = gc->proto_data;
+	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)
 	{
-		xfer->data = jsx = g_new0(JabberSIXfer, 1);
+		jsx = g_new0(JabberSIXfer, 1);
+		purple_xfer_set_protocol_data(xfer, jsx);
 		jsx->js = js;
 		jsx->local_streamhost_fd = -1;
 
@@ -1696,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))
@@ -1713,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;
@@ -1774,10 +1743,10 @@
 	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);
 
-	xfer->data = jsx;
+	purple_xfer_set_protocol_data(xfer, jsx);
 
 	purple_xfer_set_filename(xfer, filename);
 	if(filesize > 0)
--- a/libpurple/protocols/jabber/useravatar.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/useravatar.c	Mon Oct 31 01:25:36 2011 +0000
@@ -377,7 +377,7 @@
 				JabberBuddyAvatarUpdateURLInfo *info = g_new0(JabberBuddyAvatarUpdateURLInfo, 1);
 				info->js = js;
 
-				url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE,
+				url_data = purple_util_fetch_url(url, TRUE, NULL, TRUE,
 										  MAX_HTTP_BUDDYICON_BYTES,
 										  do_buddy_avatar_update_fromurl, info);
 				if (url_data) {
--- a/libpurple/protocols/jabber/usermood.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/jabber/usertune.c	Mon Oct 31 01:25:36 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);
@@ -117,7 +117,7 @@
 
 void jabber_tune_set(PurpleConnection *gc, const PurpleJabberTuneInfo *tuneinfo) {
 	xmlnode *publish, *tunenode;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	publish = xmlnode_new("publish");
 	xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/tune");
--- a/libpurple/protocols/msn/contact.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/contact.c	Mon Oct 31 01:25:36 2011 +0000
@@ -968,7 +968,7 @@
 	purple_debug_misc("msn", "Got the Address Book!\n");
 
 	if (msn_parse_addressbook(session, resp->xml)) {
-		msn_send_privacy(session->account->gc);
+		msn_send_privacy(purple_account_get_connection(session->account));
 		msn_notification_dump_contact(session);
 	} else {
 		/* This is making us loop infinitely when we fail to parse the
@@ -1251,7 +1251,7 @@
 		body = g_markup_escape_text(user->invite_message, -1);
 
 		/* Ignore the cast, we treat it as const anyway. */
-		tmp = (char *)purple_connection_get_display_name(session->account->gc);
+		tmp = (char *)purple_connection_get_display_name(purple_account_get_connection(session->account));
 		tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup("");
 
 		invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp);
--- a/libpurple/protocols/msn/error.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/error.c	Mon Oct 31 01:25:36 2011 +0000
@@ -274,7 +274,7 @@
 	if (debug)
 		purple_debug_warning("msn", "error %d: %s\n", type, buf);
 	else
-		purple_notify_error(session->account->gc, NULL, buf, NULL);
+		purple_notify_error(purple_account_get_connection(session->account), NULL, buf, NULL);
 	g_free(buf);
 }
 
--- a/libpurple/protocols/msn/httpconn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/httpconn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -285,8 +285,10 @@
 	httpconn = data;
 	servconn = httpconn->servconn;
 
-	if (servconn->type == MSN_SERVCONN_NS)
-		servconn->session->account->gc->last_received = time(NULL);
+	if (servconn->type == MSN_SERVCONN_NS) {
+		PurpleConnection *gc = purple_account_get_connection(servconn->session->account);
+		purple_connection_update_last_received(gc);
+	}
 
 	len = read(httpconn->fd, buf, sizeof(buf) - 1);
 	if (len < 0 && errno == EAGAIN)
--- a/libpurple/protocols/msn/msg.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/msg.c	Mon Oct 31 01:25:36 2011 +0000
@@ -627,7 +627,7 @@
 	const char *passport;
 	const char *value;
 
-	gc = cmdproc->session->account->gc;
+	gc = purple_account_get_connection(cmdproc->session->account);
 
 	body = msn_message_get_bin_data(msg, &body_len);
 	body_enc = g_markup_escape_text(body, body_len);
@@ -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));
@@ -713,7 +713,7 @@
 	PurpleConnection *gc;
 	char *passport;
 
-	gc = cmdproc->session->account->gc;
+  	gc = purple_account_get_connection(cmdproc->session->account);
 	passport = msg->remote_user;
 
 	if (msn_message_get_header_value(msg, "TypingUser") == NULL)
@@ -762,7 +762,7 @@
 
 	if (swboard->conv == NULL) {
 		if (chat)
-			swboard->conv = purple_find_chat(account->gc, swboard->chat_id);
+			swboard->conv = purple_find_chat(purple_account_get_connection(account), swboard->chat_id);
 		else {
 			swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
 									who, account);
@@ -970,7 +970,7 @@
 			msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj);
 		}
 
-		msn_object_destroy(obj);
+		msn_object_destroy(obj, FALSE);
 		obj =   NULL;
 		who =   NULL;
 		sha1 = NULL;
@@ -991,21 +991,23 @@
 		/* Nudge */
 		PurpleAccount *account;
 		const char *user;
+		PurpleConnection *gc;
 
 		account = cmdproc->session->account;
 		user = msg->remote_user;
+		gc = purple_account_get_connection(account);
 
 		if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
 			MsnSwitchBoard *swboard = cmdproc->data;
 			if (swboard->current_users > 1 ||
 				((swboard->conv != NULL) &&
 				 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-				purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE);
+				purple_prpl_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE);
 
 			else
-				purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
+				purple_prpl_got_attention(gc, user, MSN_NUDGE);
 		} else {
-			purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
+			purple_prpl_got_attention(gc, user, MSN_NUDGE);
 		}
 
 	} else if (!strcmp(id, "2")) {
@@ -1025,7 +1027,7 @@
 		slplink = msn_session_get_slplink(session, who);
 		msn_slplink_request_object(slplink, data, got_wink_cb, NULL, obj);
 
-		msn_object_destroy(obj);
+		msn_object_destroy(obj, FALSE);
 
 
 	} else if (!strcmp(id, "3")) {
@@ -1045,7 +1047,7 @@
 		slplink = msn_session_get_slplink(session, who);
 		msn_slplink_request_object(slplink, data, got_voiceclip_cb, NULL, obj);
 
-		msn_object_destroy(obj);
+		msn_object_destroy(obj, FALSE);
 
 	} else if (!strcmp(id, "4")) {
 		/* Action */
--- a/libpurple/protocols/msn/msn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -119,7 +119,7 @@
 	MsnSwitchBoard *swboard;
 
 	msg = msn_message_new_nudge();
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM);
 
 	msn_switchboard_send_msg(swboard, msg, TRUE);
@@ -326,7 +326,7 @@
 	MsnSession *session;
 	MsnTransaction *trans;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	cmdproc = session->notification->cmdproc;
 
 	if (entry == NULL || *entry == '\0')
@@ -384,7 +384,7 @@
 	const char *mobile_number = NULL;
 	gsize payload_len;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	cmdproc = session->notification->cmdproc;
 
 	page = msn_page_new();
@@ -647,7 +647,7 @@
 	MsnSession *session;
 
 	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	purple_request_input(gc, NULL, _("Set your home phone number."), NULL,
 					   msn_user_get_home_phone(session->user), FALSE, FALSE, NULL,
@@ -664,7 +664,7 @@
 	MsnSession *session;
 
 	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	purple_request_input(gc, NULL, _("Set your work phone number."), NULL,
 					   msn_user_get_work_phone(session->user), FALSE, FALSE, NULL,
@@ -681,7 +681,7 @@
 	MsnSession *session;
 
 	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
 					   msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL,
@@ -719,7 +719,7 @@
 	MsnSession *session;
 	char *title;
 
-	session = pc->proto_data;
+	session = purple_connection_get_protocol_data(pc);
 
 	title = g_strdup_printf(_("Blocked Text for %s"), session->account->username);
 	if (session->blocked_text == NULL) {
@@ -743,7 +743,7 @@
 	MsnSession *session;
 
 	gc = (PurpleConnection *) action->context;
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	if (!session->passport_info.email_enabled) {
 		purple_notify_error(gc, NULL,
@@ -810,11 +810,11 @@
 	MsnTransaction *trans;
 
 	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	cmdproc = session->notification->cmdproc;
 
-	if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
-	    account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
+	if (purple_account_get_privacy_type(account) == PURPLE_PRIVACY_ALLOW_ALL ||
+	    purple_account_get_privacy_type(account) == PURPLE_PRIVACY_DENY_USERS)
 		trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
 	else
 		trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
@@ -840,7 +840,7 @@
 	account = purple_buddy_get_account(buddy);
 	gc = purple_account_get_connection(account);
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_switchboard_new(session);
 	msn_switchboard_request(swboard);
@@ -869,7 +869,7 @@
 static void
 t_msn_xfer_cancel_send(PurpleXfer *xfer)
 {
-	MsnSlpLink *slplink = xfer->data;
+	MsnSlpLink *slplink = purple_xfer_get_protocol_data(xfer);
 	msn_slplink_unref(slplink);
 }
 
@@ -879,13 +879,13 @@
 	MsnSession *session;
 	PurpleXfer *xfer;
 
-	session = gc->proto_data;
-
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+	session = purple_connection_get_protocol_data(gc);
+
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
 
 	g_return_val_if_fail(xfer != NULL, NULL);
 
-	xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who));
+	purple_xfer_set_protocol_data(xfer, msn_slplink_ref(msn_session_get_slplink(session, who)));
 
 	purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
 	purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send);
@@ -918,7 +918,7 @@
 	g_free(normal);
 
 	if (ret) {
-		MsnSession *session = gc->proto_data;
+		MsnSession *session = purple_connection_get_protocol_data(gc);
 		if (session) {
 			MsnUser *user = msn_userlist_find_user(session->userlist, who);
 			if (user) {
@@ -1078,7 +1078,7 @@
 			if (psm != NULL && *psm) {
 				purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm);
 			} else {
-				purple_notify_user_info_add_pair(user_info, _("Status"), tmp2);
+				purple_notify_user_info_add_pair_html(user_info, _("Status"), tmp2);
 			}
 
 			g_free(tmp2);
@@ -1091,17 +1091,17 @@
 				}
 			} else {
 				if (purple_presence_is_idle(presence)) {
-					purple_notify_user_info_add_pair(user_info, _("Status"),
-						_("Idle"));
+					purple_notify_user_info_add_pair_plaintext(user_info,
+							_("Status"), _("Idle"));
 				} else {
-					purple_notify_user_info_add_pair(user_info, _("Status"),
-						purple_status_get_name(status));
+					purple_notify_user_info_add_pair_plaintext(user_info,
+							_("Status"), purple_status_get_name(status));
 				}
 			}
 		}
 
 		if (currentmedia) {
-			purple_notify_user_info_add_pair(user_info, mediatype, currentmedia);
+			purple_notify_user_info_add_pair_html(user_info, mediatype, currentmedia);
 			g_free(currentmedia);
 		}
 	}
@@ -1119,23 +1119,26 @@
 	{
 		const char *phone;
 
-		purple_notify_user_info_add_pair(user_info, _("Has you"),
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Has you"),
 									   ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No")));
 
-		purple_notify_user_info_add_pair(user_info, _("Blocked"),
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Blocked"),
 									   ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
 
 		phone = msn_user_get_home_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
+		if (phone != NULL) {
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), phone);
+		}
 
 		phone = msn_user_get_work_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
+		if (phone != NULL) {
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), phone);
+		}
 
 		phone = msn_user_get_mobile_phone(user);
-		if (phone != NULL)
-			purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
+		if (phone != NULL) {
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), phone);
+		}
 	}
 }
 
@@ -1213,7 +1216,7 @@
 	PurplePluginAction *act;
 
 	gc = (PurpleConnection *) context;
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	act = purple_plugin_action_new(_("Set Friendly Name..."),
 								 msn_show_set_friendly_name);
@@ -1333,7 +1336,7 @@
 
 	if (!purple_ssl_is_supported())
 	{
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 			_("SSL support is needed for MSN. Please install a supported "
 			  "SSL library."));
@@ -1350,9 +1353,10 @@
 
 	session = msn_session_new(account);
 
-	gc->proto_data = 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_protocol_data(gc, session);
+	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);
 
@@ -1374,7 +1378,7 @@
 	}
 
 	if (!msn_session_connect(session, host, port, http_method))
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to connect"));
 }
@@ -1384,13 +1388,13 @@
 {
 	MsnSession *session;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	g_return_if_fail(session != NULL);
 
 	msn_session_destroy(session);
 
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 }
 
 static gboolean
@@ -1450,7 +1454,7 @@
 static void msn_emoticon_destroy(MsnEmoticon *emoticon)
 {
 	if (emoticon->obj)
-		msn_object_destroy(emoticon->obj);
+		msn_object_destroy(emoticon->obj, FALSE);
 	g_free(emoticon->smile);
 	g_free(emoticon);
 }
@@ -1523,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;
@@ -1536,7 +1540,7 @@
 	account = purple_connection_get_account(gc);
 	username = purple_account_get_username(account);
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	swboard = msn_session_find_swboard(session, who);
 
 	if (!strncmp("tel:+", who, 5)) {
@@ -1640,7 +1644,7 @@
 
 		purple_debug_info("msn", "prepare to send offline Message\n");
 
-		friendname = msn_encode_mime(account->username);
+		friendname = msn_encode_mime(purple_account_get_username(account));
 		msn_oim_prep_send_msg_info(session->oim,
 			purple_account_get_username(account),
 			friendname, who, msgtext);
@@ -1663,7 +1667,7 @@
 	MsnMessage *msg;
 
 	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	/*
 	 * TODO: I feel like this should be "if (state != PURPLE_TYPING)"
@@ -1712,7 +1716,7 @@
 
 	if (gc != NULL)
 	{
-		session = gc->proto_data;
+		session = purple_connection_get_protocol_data(gc);
 		msn_change_status(session);
 	}
 }
@@ -1722,7 +1726,7 @@
 {
 	MsnSession *session;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	msn_change_status(session);
 }
@@ -1852,7 +1856,7 @@
 	MsnSession *session;
 	MsnUserList *userlist;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	if (!session->logged_in)
@@ -1869,7 +1873,7 @@
 	MsnUserList *userlist;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 	user = msn_userlist_find_user(userlist, who);
 
@@ -1897,7 +1901,7 @@
 	MsnUserList *userlist;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 	user = msn_userlist_find_user(userlist, who);
 
@@ -1924,7 +1928,7 @@
 	MsnUserList *userlist;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	if (!session->logged_in)
@@ -1947,7 +1951,7 @@
 	MsnUserList *userlist;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	if (!session->logged_in)
@@ -1976,7 +1980,7 @@
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_session_find_swboard_with_id(session, id);
 
@@ -2001,7 +2005,7 @@
 	MsnSwitchBoard *swboard;
 	PurpleConversation *conv;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_session_find_swboard_with_id(session, id);
 
@@ -2038,7 +2042,7 @@
 	GString *emoticons = NULL;
 
 	account = purple_connection_get_account(gc);
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	username = purple_account_get_username(account);
 	swboard = msn_session_find_swboard_with_id(session, id);
 
@@ -2104,7 +2108,7 @@
 	MsnSession *session;
 	MsnTransaction *trans;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	if (!session->http_method)
 	{
@@ -2122,7 +2126,7 @@
 {
 	MsnSession *session;
 
-	session = pc->proto_data;
+	session = purple_connection_get_protocol_data(pc);
 
 	msn_update_contact(session, name, MSN_UPDATE_ALIAS, alias);
 }
@@ -2134,7 +2138,7 @@
 	MsnSession *session;
 	MsnUserList *userlist;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name);
@@ -2147,7 +2151,7 @@
 	MsnSession *session;
 	const char *gname;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	g_return_if_fail(session != NULL);
 	g_return_if_fail(session->userlist != NULL);
@@ -2171,7 +2175,7 @@
 	MsnSwitchBoard *swboard;
 	PurpleConversation *conv;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_session_find_swboard(session, who);
 
@@ -2207,7 +2211,7 @@
 	MsnSession *session;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	user = session->user;
 
 	msn_user_set_buddy_icon(user, img);
@@ -2221,7 +2225,7 @@
 	MsnSession *session;
 	const char *gname;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	gname = purple_group_get_name(group);
 
 	purple_debug_info("msn", "Remove group %s\n", gname);
@@ -2262,7 +2266,7 @@
 		{
 			char *nicktext = g_markup_escape_text(alias, -1);
 			tmp = g_strdup_printf("<font sml=\"msn\">%s</font>", nicktext);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
+			purple_notify_user_info_add_pair_html(user_info, _("Nickname"), tmp);
 			g_free(tmp);
 			g_free(nicktext);
 		}
@@ -2361,7 +2365,7 @@
 
 	if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0)
 	{
-		purple_notify_user_info_add_pair(user_info,
+		purple_notify_user_info_add_pair_html(user_info,
 				_("Error retrieving profile"), NULL);
 
 		purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
@@ -2680,7 +2684,7 @@
 	if (user_url != NULL)
 	{
 		tmp = g_strdup_printf("<a href=\"%s\">%s</a>", user_url, user_url);
-		purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp);
+		purple_notify_user_info_add_pair_html(user_info, _("Homepage"), tmp);
 		g_free(tmp);
 		g_free(user_url);
 
@@ -2703,9 +2707,9 @@
 		char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http&#58;&#47;&#47;spaces.live.com&#47;profile.aspx&#63;cid&#61;0\"");
 		PurpleBuddy *b = purple_find_buddy
 				(purple_connection_get_account(info_data->gc), info_data->name);
-		purple_notify_user_info_add_pair(user_info,
+		purple_notify_user_info_add_pair_html(user_info,
 				_("Error retrieving profile"), NULL);
-		purple_notify_user_info_add_pair(user_info, NULL,
+		purple_notify_user_info_add_pair_plaintext(user_info, NULL,
 				((p && b) ? _("The user has not created a public profile.") :
 					(p ? _("MSN reported not being able to find the user's profile. "
 							"This either means that the user does not exist, "
@@ -2720,7 +2724,7 @@
 	purple_notify_user_info_add_section_break(user_info);
 	tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>",
 			PROFILE_URL, info_data->name, _("View web profile"));
-	purple_notify_user_info_add_pair(user_info, NULL, tmp);
+	purple_notify_user_info_add_pair_html(user_info, NULL, tmp);
 	g_free(tmp);
 
 #if PHOTO_SUPPORT
@@ -2739,7 +2743,7 @@
 	/* Try to put the photo in there too, if there's one */
 	if (photo_url_text)
 	{
-		url_data = purple_util_fetch_url_len(photo_url_text, FALSE, NULL, FALSE,
+		url_data = purple_util_fetch_url(photo_url_text, FALSE, NULL, FALSE,
 		                                     MAX_HTTP_BUDDYICON_BYTES,
 		                                     msn_got_photo, info2_data);
 		session->url_datas = g_slist_prepend(session->url_datas, url_data);
@@ -2801,7 +2805,7 @@
 			purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len);
 			id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
 			g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id);
-			purple_notify_user_info_prepend_pair(user_info, NULL, buf);
+			purple_notify_user_info_prepend_pair_html(user_info, NULL, buf);
 		}
 	}
 
@@ -2838,7 +2842,7 @@
 
 	url_data = purple_util_fetch_url(url, FALSE,
 	                                 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
-	                                 TRUE, msn_got_info, data);
+	                                 TRUE, -1, msn_got_info, data);
 	session->url_datas = g_slist_prepend(session->url_datas, url_data);
 
 	g_free(url);
@@ -2927,6 +2931,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),	/* struct_size */
 	OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE,
 	NULL,                               /* user_splits */
 	NULL,                               /* protocol_options */
@@ -2948,7 +2953,7 @@
 	msn_set_status,                     /* set_away */
 	msn_set_idle,                       /* set_idle */
 	NULL,                               /* change_passwd */
-	NULL,                               /* add_buddy */
+	msn_add_buddy,                      /* add_buddy */
 	NULL,                               /* add_buddies */
 	msn_rem_buddy,                      /* remove_buddy */
 	NULL,                               /* remove_buddies */
@@ -2967,7 +2972,6 @@
 	msn_keepalive,                      /* keepalive */
 	NULL,                               /* register_user */
 	NULL,                               /* get_cb_info */
-	NULL,                               /* get_cb_away */
 	msn_alias_buddy,                    /* alias_buddy */
 	msn_group_buddy,                    /* group_buddy */
 	msn_rename_group,                   /* rename_group */
@@ -2992,15 +2996,12 @@
 	NULL,                               /* unregister_user */
 	msn_send_attention,                 /* send_attention */
 	msn_attention_types,                /* attention_types */
-	sizeof(PurplePluginProtocolInfo),	/* struct_size */
 	msn_get_account_text_table,         /* get_account_text_table */
 	NULL,                               /* initiate_media */
 	NULL,                               /* get_media_caps */
 	NULL,                               /* get_moods */
 	msn_set_public_alias,               /* set_public_alias */
-	msn_get_public_alias,               /* get_public_alias */
-	msn_add_buddy,                      /* add_buddy_with_invite */
-	NULL                                /* add_buddies_with_invite */
+	msn_get_public_alias                /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/msn/nexus.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/nexus.c	Mon Oct 31 01:25:36 2011 +0000
@@ -390,7 +390,7 @@
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
 
 	username = purple_account_get_username(session->account);
-	password = purple_connection_get_password(session->account->gc);
+	password = purple_connection_get_password(purple_account_get_connection(session->account));
 	if (g_utf8_strlen(password, -1) > 16) {
 		/* max byte size for 16 utf8 characters is 64 + 1 for the null */
 		gchar truncated[65];
--- a/libpurple/protocols/msn/notification.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/notification.c	Mon Oct 31 01:25:36 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"))
@@ -1390,7 +1390,7 @@
 
 	session = cmdproc->session;
 	account = session->account;
-	gc = account->gc;
+	gc = purple_account_get_connection(account);
 
 	rru = cmd->params[1];
 	url = cmd->params[2];
@@ -2011,7 +2011,7 @@
 	const char *unread;
 
 	session = cmdproc->session;
-	gc = session->account->gc;
+	gc = purple_account_get_connection(session->account);
 
 	if (strcmp(msg->remote_user, "Hotmail"))
 		/* This isn't an official message. */
@@ -2062,7 +2062,7 @@
 	const char *mdata, *unread;
 
 	session = cmdproc->session;
-	gc = session->account->gc;
+	gc = purple_account_get_connection(session->account);
 
 	if (strcmp(msg->remote_user, "Hotmail"))
 		/* This isn't an official message. */
@@ -2134,7 +2134,7 @@
 	char *from, *subject, *tmp;
 
 	session = cmdproc->session;
-	gc = session->account->gc;
+	gc = purple_account_get_connection(session->account);
 
 	if (strcmp(msg->remote_user, "Hotmail"))
 		/* This isn't an official message. */
@@ -2219,7 +2219,7 @@
 		}
 
 		if (*buf != '\0')
-			purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL);
+			purple_notify_info(purple_account_get_connection(cmdproc->session->account), NULL, buf, NULL);
 	}
 
 	g_hash_table_destroy(table);
--- a/libpurple/protocols/msn/object.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/object.c	Mon Oct 31 01:25:36 2011 +0000
@@ -103,7 +103,7 @@
 	if (obj->creator == NULL || obj->size == 0 || obj->type == 0
 	 || obj->sha1d == NULL) {
 		purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-		msn_object_destroy(obj);
+		msn_object_destroy(obj, FALSE);
 		return NULL;
 	}
 
@@ -111,12 +111,12 @@
 		/* Location/friendly are required for non-buddyicon objects */
 		if (obj->type != MSN_OBJECT_USERTILE) {
 			purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-			msn_object_destroy(obj);
+			msn_object_destroy(obj, FALSE);
 			return NULL;
 		/* Buddy icon object can contain Url/Url1 instead */
 		} else if (obj->url == NULL || obj->url1 == NULL) {
 			purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-			msn_object_destroy(obj);
+			msn_object_destroy(obj, FALSE);
 			return NULL;
 		}
 	}
@@ -193,10 +193,13 @@
 }
 
 void
-msn_object_destroy(MsnObject *obj)
+msn_object_destroy(MsnObject *obj, gboolean only_remote)
 {
 	g_return_if_fail(obj != NULL);
 
+	if (only_remote && obj->local)
+		return;
+
 	g_free(obj->creator);
 	g_free(obj->location);
 	g_free(obj->friendly);
--- a/libpurple/protocols/msn/object.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/object.h	Mon Oct 31 01:25:36 2011 +0000
@@ -86,9 +86,10 @@
 /**
  * Destroys an MsnObject structure.
  *
- * @param obj The object structure.
+ * @param obj         The object structure.
+ * @param only_remote Only destroy non-local objects.
  */
-void msn_object_destroy(MsnObject *obj);
+void msn_object_destroy(MsnObject *obj, gboolean only_remote);
 
 /**
  * Outputs a string representation of an MsnObject.
--- a/libpurple/protocols/msn/oim.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/oim.c	Mon Oct 31 01:25:36 2011 +0000
@@ -695,7 +695,7 @@
 	purple_debug_info("msn", "oim Date:{%s},passport{%s}\n",
 	                  date, passport);
 
-	serv_got_im(rdata->oim->session->account->gc, passport, decode_msg, 0,
+	serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, decode_msg, 0,
 	            stamp);
 
 	/*Now get the oim message ID from the oim_list.
@@ -785,7 +785,7 @@
 
 		/* XXX/khc: pretty sure this is wrong */
 		if (count > 0)
-			purple_notify_emails(session->account->gc, count, FALSE, NULL,
+			purple_notify_emails(purple_account_get_connection(session->account), count, FALSE, NULL,
 				NULL, passports, urls, NULL, NULL);
 		g_free(unread);
 	}
--- a/libpurple/protocols/msn/sbconn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/sbconn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -121,6 +121,8 @@
 			}
 #endif
 		}
+	} else {
+		msn_transaction_set_saveable(trans, FALSE);
 	}
 
 	trans->payload = payload;
--- a/libpurple/protocols/msn/servconn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/servconn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -421,8 +421,10 @@
 
 	servconn = data;
 
-	if (servconn->type == MSN_SERVCONN_NS)
-		servconn->session->account->gc->last_received = time(NULL);
+	if (servconn->type == MSN_SERVCONN_NS) {
+		PurpleConnection *gc = purple_account_get_connection(servconn->session->account);
+		purple_connection_update_last_received(gc);
+	}
 
 	len = read(servconn->fd, buf, sizeof(buf) - 1);
 	if (len < 0 && errno == EAGAIN)
--- a/libpurple/protocols/msn/session.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/session.c	Mon Oct 31 01:25:36 2011 +0000
@@ -420,7 +420,7 @@
 
 	msn_session_disconnect(session);
 
-	purple_connection_error_reason(gc, reason, msg);
+	purple_connection_error(gc, reason, msg);
 
 	g_free(msg);
 }
@@ -459,7 +459,7 @@
 	if (session->logged_in)
 		return;
 
-	gc = session->account->gc;
+	gc = purple_account_get_connection(session->account);
 
 	session->login_step = step;
 
--- a/libpurple/protocols/msn/slp.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/slp.c	Mon Oct 31 01:25:36 2011 +0000
@@ -253,7 +253,7 @@
 			data->session = session;
 			data->remote_user = user->passport;
 			data->sha1 = info;
-			url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE, 200*1024,
+			url_data = purple_util_fetch_url(url, TRUE, NULL, TRUE, 200*1024,
 			                                     fetched_user_display, data);
 			session->url_datas = g_slist_prepend(session->url_datas, url_data);
 		} else {
@@ -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);
@@ -364,7 +366,7 @@
 	fn = purple_xfer_get_filename(xfer);
 	fp = purple_xfer_get_local_filename(xfer);
 
-	slplink = xfer->data;
+	slplink = purple_xfer_get_protocol_data(xfer);
 
 	g_return_if_fail(slplink != NULL);
 	g_return_if_fail(fp != NULL);
@@ -384,7 +386,7 @@
 	purple_xfer_set_read_fnc(xfer, msn_xfer_read);
 	purple_xfer_set_write_fnc(xfer, msn_xfer_write);
 
-	xfer->data = slpcall;
+	purple_xfer_set_protocol_data(xfer, slpcall);
 
 	context = gen_context(xfer, fn, fp);
 
--- a/libpurple/protocols/msn/slpcall.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Mon Oct 31 01:25:36 2011 +0000
@@ -113,7 +113,7 @@
 	if (slpcall->xfer != NULL) {
 		if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE)
 			g_byte_array_free(slpcall->u.incoming_data, TRUE);
-		slpcall->xfer->data = NULL;
+		purple_xfer_set_protocol_data(slpcall->xfer, NULL);
 		purple_xfer_unref(slpcall->xfer);
 	}
 
@@ -485,7 +485,7 @@
 			if (img)
 				purple_imgstore_ref(img);
 		}
-		msn_object_destroy(obj);
+		msn_object_destroy(obj, FALSE);
 
 		if (img != NULL) {
 			/* DATA PREP */
@@ -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);
@@ -550,7 +547,7 @@
 			slpcall->xfer = xfer;
 			purple_xfer_ref(slpcall->xfer);
 
-			xfer->data = slpcall;
+			purple_xfer_set_protocol_data(xfer, slpcall);
 
 			if (file_context->preview) {
 				purple_xfer_set_thumbnail(xfer, file_context->preview,
@@ -731,7 +728,9 @@
 
 			dc->listen_data = purple_network_listen_range(
 				0, 0,
+				AF_UNSPEC,
 				SOCK_STREAM,
+				TRUE,
 				msn_dc_listen_socket_created_cb,
 				dc
 			);
@@ -832,7 +831,9 @@
 
 		dc->listen_data = purple_network_listen_range(
 			0, 0,
+			AF_UNSPEC,
 			SOCK_STREAM,
+			TRUE,
 			msn_dc_listen_socket_created_cb,
 			dc
 		);
@@ -1141,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/slplink.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/slplink.c	Mon Oct 31 01:25:36 2011 +0000
@@ -465,7 +465,7 @@
 					purple_xfer_ref(xfer);
 					purple_xfer_start(xfer,	-1, NULL, 0);
 
-					if (xfer->data == NULL) {
+					if (purple_xfer_get_protocol_data(xfer) == NULL) {
 						purple_xfer_unref(xfer);
 						msn_slpmsg_destroy(slpmsg);
 						g_return_val_if_reached(NULL);
--- a/libpurple/protocols/msn/slpmsg.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/slpmsg.c	Mon Oct 31 01:25:36 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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/slpmsg.h	Mon Oct 31 01:25:36 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/switchboard.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Mon Oct 31 01:25:36 2011 +0000
@@ -312,7 +312,7 @@
 
 			swboard->chat_id = msn_switchboard_get_chat_id();
 			swboard->flag |= MSN_SB_FLAG_IM;
-			swboard->conv = serv_got_joined_chat(account->gc,
+			swboard->conv = serv_got_joined_chat(purple_account_get_connection(account),
 												 swboard->chat_id,
 												 "MSN Chat");
 
@@ -750,7 +750,7 @@
 	PurpleConnection *gc;
 	MsnSwitchBoard *swboard;
 
-	gc = cmdproc->session->account->gc;
+	gc = purple_account_get_connection(cmdproc->session->account);
 	swboard = cmdproc->data;
 
 	if (swboard->current_users > 1)
--- a/libpurple/protocols/msn/user.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/user.c	Mon Oct 31 01:25:36 2011 +0000
@@ -76,7 +76,7 @@
 	}
 
 	if (user->msnobj != NULL)
-		msn_object_destroy(user->msnobj);
+		msn_object_destroy(user->msnobj, FALSE);
 
 	g_free(user->passport);
 	g_free(user->friendly_name);
@@ -406,7 +406,7 @@
 
 	gc = purple_account_get_connection(account);
 	if (gc != NULL)
-		session = gc->proto_data;
+		session = purple_connection_get_protocol_data(gc);
 
 	if ((session != NULL) && (user = msn_userlist_find_user(session->userlist, name)) != NULL)
 	{
@@ -566,7 +566,7 @@
 		return;
 	}
 
-	if (!buddy_icon_cached(account->gc, obj)) {
+	if (!buddy_icon_cached(purple_account_get_connection(account), obj)) {
 		MsnUserList *userlist;
 
 		userlist = user->userlist;
@@ -588,8 +588,8 @@
 {
 	g_return_if_fail(user != NULL);
 
-	if (user->msnobj != NULL && !msn_object_find_local(msn_object_get_sha1(obj)))
-		msn_object_destroy(user->msnobj);
+	if (user->msnobj != NULL)
+		msn_object_destroy(user->msnobj, TRUE);
 
 	user->msnobj = obj;
 
--- a/libpurple/protocols/msn/userlist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/userlist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -54,7 +54,7 @@
 
 	if (PURPLE_CONNECTION_IS_VALID(pa->gc))
 	{
-		MsnSession *session = pa->gc->proto_data;
+		MsnSession *session = purple_connection_get_protocol_data(pa->gc);
 		MsnUserList *userlist = session->userlist;
 		PurpleAccount *account = purple_connection_get_account(pa->gc);
 
@@ -79,7 +79,7 @@
 
 	if (PURPLE_CONNECTION_IS_VALID(pa->gc))
 	{
-		MsnSession *session = pa->gc->proto_data;
+		MsnSession *session = purple_connection_get_protocol_data(pa->gc);
 		MsnUserList *userlist = session->userlist;
 		MsnCallbackState *state = msn_callback_state_new(session);
 
--- a/libpurple/protocols/msn/xfer.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/xfer.c	Mon Oct 31 01:25:36 2011 +0000
@@ -42,7 +42,7 @@
 
 	purple_debug_info("msn", "xfer_init\n");
 
-	slpcall = xfer->data;
+	slpcall = purple_xfer_get_protocol_data(xfer);
 
 	/* Send Ok */
 	content = g_strdup_printf("SessionID: %lu\r\n\r\n",
@@ -62,9 +62,9 @@
 	char *content;
 
 	g_return_if_fail(xfer != NULL);
-	g_return_if_fail(xfer->data != NULL);
 
-	slpcall = xfer->data;
+	slpcall = purple_xfer_get_protocol_data(xfer);
+	g_return_if_fail(slpcall != NULL);
 
 	if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
 	{
@@ -102,7 +102,7 @@
 
 	g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1);
 
-	slpcall = xfer->data;
+	slpcall = purple_xfer_get_protocol_data(xfer);
 	/* Not sure I trust it'll be there */
 	g_return_val_if_fail(slpcall != NULL, -1);
 
@@ -126,7 +126,7 @@
 
 	g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1);
 
-	slpcall = xfer->data;
+	slpcall = purple_xfer_get_protocol_data(xfer);
 	/* Not sure I trust it'll be there */
 	g_return_val_if_fail(slpcall != NULL, -1);
 
@@ -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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/msn/xfer.h	Mon Oct 31 01:25:36 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/actions.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/actions.c	Mon Oct 31 01:25:36 2011 +0000
@@ -43,7 +43,7 @@
  */
 static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields )
 {
-	struct MXitSession*		session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session	= purple_connection_get_protocol_data( gc ) ;
 	PurpleRequestField*		field	= NULL;
 	const char*				name	= NULL;
 	const char*				bday	= NULL;
@@ -84,13 +84,6 @@
 		g_string_append( attributes, attrib );
 		acount++;
 
-		/* force hidden if disabled */
-		if ( profile->hidden == FALSE ) {
-			g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROFILE_TYPE_BOOL, "1" );
-			g_string_append( attributes, attrib );
-			acount++;
-		}
-
 		/* update birthday */
 		g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) );
 		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday );
@@ -165,7 +158,7 @@
 
 		/* update where am i */
 		name = purple_request_fields_get_string( fields, "whereami" );
-		if ( !name)
+		if ( !name )
 			profile->whereami[0] = '\0';
 		else
 			g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) );
@@ -207,7 +200,7 @@
 static void mxit_profile_action( PurplePluginAction* action )
 {
 	PurpleConnection*			gc		= (PurpleConnection*) action->context;
-	struct MXitSession*			session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*			session	= purple_connection_get_protocol_data( gc );
 	struct MXitProfile*			profile	= session->profile;
 
 	PurpleRequestFields*		fields	= NULL;
@@ -304,7 +297,7 @@
  */
 static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields )
 {
-	struct MXitSession*		session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
 	const char*				pin		= NULL;
 	const char*				pin2	= NULL;
 	const char*				err		= NULL;
@@ -366,7 +359,7 @@
 static void mxit_change_pin_action( PurplePluginAction* action )
 {
 	PurpleConnection*			gc		= (PurpleConnection*) action->context;
-	struct MXitSession*			session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*			session	= purple_connection_get_protocol_data( gc );
 
 	PurpleRequestFields*		fields	= NULL;
 	PurpleRequestFieldGroup*	group	= NULL;
@@ -375,16 +368,16 @@
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" );
 
 	fields = purple_request_fields_new();
-	group = purple_request_field_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	group = purple_request_field_group_new( NULL );
+	purple_request_fields_add_group( fields, group );
 
 	/* pin */
-	field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE );
+	field = purple_request_field_string_new( "pin", _( "PIN" ), purple_account_get_password( session->acc ), FALSE );
 	purple_request_field_string_set_masked( field, TRUE );
 	purple_request_field_group_add_field( group, field );
 
 	/* verify pin */
-	field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), session->acc->password, FALSE );
+	field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), purple_account_get_password( session->acc ), FALSE );
 	purple_request_field_string_set_masked( field, TRUE );
 	purple_request_field_group_add_field( group, field );
 
@@ -402,7 +395,7 @@
 static void mxit_splash_action( PurplePluginAction* action )
 {
 	PurpleConnection*		gc		= (PurpleConnection*) action->context;
-	struct MXitSession*		session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
 
 	if ( splash_current( session ) != NULL )
 		splash_display( session );
@@ -439,7 +432,7 @@
 static void mxit_suggested_friends_action( PurplePluginAction* action )
 {
 	PurpleConnection*		gc				= (PurpleConnection*) action->context;
-	struct MXitSession*		session			= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
 	const char*				profilelist[]	= {
 				CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
 				CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
@@ -456,7 +449,7 @@
  */
 static void mxit_user_search_cb( PurpleConnection *gc, const char *input )
 {
-	struct MXitSession*		session			= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
 	const char*				profilelist[]	= {
 				CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
 				CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
@@ -479,10 +472,10 @@
 		_( "Search for a MXit contact" ),
 		_( "Type search information" ),
 		NULL, FALSE, FALSE, NULL,
-		_("_Search"), G_CALLBACK( mxit_user_search_cb ),
-		_("_Cancel"), NULL,
+		_( "_Search" ), G_CALLBACK( mxit_user_search_cb ),
+		_( "_Cancel" ), NULL,
 		purple_connection_get_account( gc ), NULL, NULL,
-		gc);
+		gc );
 }
 
 
--- a/libpurple/protocols/mxit/cipher.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/cipher.c	Mon Oct 31 01:25:36 2011 +0000
@@ -1,7 +1,7 @@
 /*
  *					MXit Protocol libPurple Plugin
  *
- *					-- user password encryption --
+ *						-- encryption --
  *
  *				Pieter Loubser	<libpurple@mxit.com>
  *
@@ -31,30 +31,70 @@
 #include	"aes.h"
 
 
-/* password encryption */
+/* encryption */
 #define		INITIAL_KEY		"6170383452343567"
 #define		SECRET_HEADER	"<mxit/>"
+#define		ENCRYPT_HEADER	"<mxitencrypted ver=\"5.2\"/>"
+
+
+/*------------------------------------------------------------------------
+ * Add ISO10126 Padding to the data.
+ *
+ *  @param data		The data to pad.
+ */
+static void padding_add( GString* data )
+{
+	unsigned int blocks = ( data->len / 16 ) + 1;
+	unsigned int padding = ( blocks * 16 ) - data->len;
+
+	g_string_set_size( data, blocks * 16 );
+	data->str[data->len - 1] = padding;
+}
 
 
 /*------------------------------------------------------------------------
- * Pad the secret data using ISO10126 Padding.
+ * Remove ISO10126 Padding from the data.
  *
- *  @param secret	The data to pad (caller must ensure buffer has enough space for padding)
- *  @return			The total number of 128-bit blocks used
+ *  @param data		The data from which to remove padding.
  */
-static int pad_secret_data( char* secret )
+static void padding_remove( GString* data )
 {
-	int		blocks	= 0;
-	int		passlen;
-	int		padding;
+	unsigned int padding;
+
+	if ( data->len == 0 )
+		return;
+
+	padding = data->str[data->len - 1];
+	g_string_truncate( data, data->len - padding );
+}
+
 
-	passlen = strlen( secret );
-	blocks = ( passlen / 16 ) + 1;
-	padding = ( blocks * 16 ) - passlen;
-	secret[passlen] = 0x50;
-	secret[(blocks * 16) - 1] = padding;
+/*------------------------------------------------------------------------
+ * Generate the Transport-Layer crypto key.
+ *  (Note: this function is not-thread safe)
+ *
+ *  @param session	The MXit Session object
+ *	@return			The transport-layer crypto key.
+ */
+static char* transport_layer_key( struct MXitSession* session )
+{
+	static char	key[16 + 1];
+	const char*	password		= purple_account_get_password( session->acc );
+	int			passlen			= strlen( password );
 
-	return blocks;
+	/* initialize with initial key */
+	g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
+
+	/* client key (8 bytes) */
+	memcpy( key, session->clientkey, strlen( session->clientkey ) );
+
+	/* add last 8 characters of the PIN (no padding if less characters) */
+	if ( passlen <= 8 )
+		memcpy( key + 8, password, passlen );
+	else
+		memcpy( key + 8, password + ( passlen - 8 ), 8 );
+
+	return key;
 }
 
 
@@ -67,42 +107,131 @@
  */
 char* mxit_encrypt_password( struct MXitSession* session )
 {
-	char		key[64];
+	char		key[16 + 1];
 	char		exkey[512];
-	char		pass[64];
+	GString*	pass			= NULL;
 	char		encrypted[64];
 	char*		base64;
-	int			blocks;
-	int			size;
 	int			i;
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" );
 
 	memset( encrypted, 0x00, sizeof( encrypted ) );
-	memset( exkey, 0x00, sizeof( exkey ) );
-	memset( pass, 0x58, sizeof( pass ) );
-	pass[sizeof( pass ) - 1] = '\0';
 
-	/* build the custom AES encryption key */
+	/* build the AES encryption key */
 	g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
 	memcpy( key, session->clientkey, strlen( session->clientkey ) );
 	ExpandKey( (unsigned char*) key, (unsigned char*) exkey );
 
-	/* build the custom data to be encrypted */
-	g_strlcpy( pass, SECRET_HEADER, sizeof( pass ) );
-	strcat( pass, session->acc->password );
+	/* build the secret data to be encrypted: SECRET_HEADER + password */
+	pass = g_string_new( SECRET_HEADER );
+	g_string_append( pass, purple_account_get_password( session->acc) );
+	padding_add( pass );		/* add ISO10126 padding */
 
-	/* pad the secret data */
-	blocks = pad_secret_data( pass );
-	size = blocks * 16;
-
-	/* now encrypt the password. we encrypt each block separately (ECB mode) */
-	for ( i = 0; i < size; i += 16 )
-		Encrypt( (unsigned char*) pass + i, (unsigned char*) exkey, (unsigned char*) encrypted + i );
+	/* now encrypt the secret. we encrypt each block separately (ECB mode) */
+	for ( i = 0; i < pass->len; i += 16 )
+		Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) encrypted + i );
 
 	/* now base64 encode the encrypted password */
-	base64 = purple_base64_encode( (unsigned char*) encrypted, size );
+	base64 = purple_base64_encode( (unsigned char*) encrypted, pass->len );
+
+	g_string_free( pass, TRUE );
 
 	return base64;
 }
 
+
+/*------------------------------------------------------------------------
+ * Decrypt a message using transport-layer encryption.
+ *
+ *  @param session	The MXit session object
+ *	@param message	The encrypted message data (is base64-encoded).
+ *  @return			The decrypted message.  Must be g_free'd when no longer needed.
+ */
+char* mxit_decrypt_message( struct MXitSession* session, char* message )
+{
+	guchar*		raw_message;
+	gsize		raw_len;
+	char		exkey[512];
+	GString*	decoded		= NULL;
+	int			i;
+
+	/* remove optional header: <mxitencrypted ver="5.2"/> */
+	if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 )
+		message += strlen( ENCRYPT_HEADER );
+
+	/* base64 decode the message */
+	raw_message = purple_base64_decode( message, &raw_len );
+
+	/* build the AES key */
+	ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
+
+	/* AES decrypt each block */
+	decoded = g_string_sized_new( raw_len );
+	for ( i = 0; i < raw_len; i += 16 ) {
+		char	block[16];
+
+		Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block );
+		g_string_append_len( decoded, block, 16 );
+	}
+	g_free( raw_message );
+
+	/* check that the decrypted message starts with header: <mxit/> */
+	if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) {
+		g_string_free( decoded, TRUE );
+		return NULL;			/* message could not be decrypted */
+	}
+
+	/* remove ISO10126 padding */
+	padding_remove( decoded );
+
+	/* remove encryption header */
+	g_string_erase( decoded, 0, strlen( SECRET_HEADER ) );
+
+	return g_string_free( decoded, FALSE );
+}
+
+
+/*------------------------------------------------------------------------
+ * Encrypt a message using transport-layer encryption.
+ *
+ *  @param session	The MXit session object
+ *	@param message	The message data.
+ *  @return			The encrypted message.  Must be g_free'd when no longer needed.
+ */
+char* mxit_encrypt_message( struct MXitSession* session, char* message )
+{
+	GString*	raw_message	= NULL;
+	char		exkey[512];
+	GString*	encoded		= NULL;
+	gchar*		base64;
+	int			i;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message );
+
+	/* append encryption header to message data */
+	raw_message = g_string_new( SECRET_HEADER );
+	g_string_append( raw_message, message );
+	padding_add( raw_message );		/* add ISO10126 padding */
+
+	/* build the AES key */
+	ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
+
+	/* AES encrypt each block */
+	encoded = g_string_sized_new( raw_message->len );
+	for ( i = 0; i < raw_message->len; i += 16 ) {
+		char	block[16];
+
+		Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block );
+		g_string_append_len( encoded, block, 16 );
+	}
+	g_string_free( raw_message, TRUE );
+
+	/* base64 encode the encrypted message */
+	base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len );
+	g_string_free( encoded, TRUE );
+
+	purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 );
+
+	return base64;
+}
--- a/libpurple/protocols/mxit/cipher.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/cipher.h	Mon Oct 31 01:25:36 2011 +0000
@@ -1,7 +1,7 @@
 /*
  *					MXit Protocol libPurple Plugin
  *
- *					-- user password encryption --
+ *						-- encryption --
  *
  *				Pieter Loubser	<libpurple@mxit.com>
  *
@@ -32,5 +32,7 @@
 
 char* mxit_encrypt_password( struct MXitSession* session );
 
+char* mxit_decrypt_message( struct MXitSession* session, char* message );
+char* mxit_encrypt_message( struct MXitSession* session, char* message );
 
 #endif		/* _MXIT_CIPHER_H_ */
--- a/libpurple/protocols/mxit/filexfer.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/filexfer.c	Mon Oct 31 01:25:36 2011 +0000
@@ -97,11 +97,11 @@
  */
 static void mxit_xfer_free( PurpleXfer* xfer )
 {
-	struct mxitxfer*	mx		= (struct mxitxfer*) xfer->data;;
+	struct mxitxfer*	mx	= purple_xfer_get_protocol_data( xfer );
 
 	if ( mx ) {
+		purple_xfer_set_protocol_data( xfer, NULL );
 		g_free( mx );
-		xfer->data = NULL;
 	}
 }
 
@@ -117,7 +117,7 @@
  */
 static void mxit_xfer_init( PurpleXfer* xfer )
 {
-	struct mxitxfer*	mx	= (struct mxitxfer*) xfer->data;
+	struct mxitxfer*	mx	= purple_xfer_get_protocol_data( xfer );
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_init\n" );
 
@@ -126,7 +126,7 @@
 
 		if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) {
 			/* the file is too big */
-			purple_xfer_error( xfer->type, xfer->account, xfer->who, _( "The file you are trying to send is too large!" ) );
+			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 );
 			return;
 		}
@@ -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,6 +151,7 @@
  */
 static void mxit_xfer_start( PurpleXfer* xfer )
 {
+	goffset			filesize;
 	unsigned char*	buffer;
 	int				size;
 	int				wrote;
@@ -163,10 +164,12 @@
 		 * a buffer and copy the file data into memory and then we can send it to
 		 * the contact. we will send the whole file with one go.
 		 */
-		buffer = g_malloc( xfer->bytes_remaining );
-		size = fread( buffer, xfer->bytes_remaining, 1, xfer->dest_fp );
+		filesize = purple_xfer_get_bytes_remaining( xfer );
+		buffer = g_malloc( filesize );
+		size = fread( buffer, filesize, 1, xfer->dest_fp );
+		// TODO: If (size != 1) -> file read error
 
-		wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining );
+		wrote = purple_xfer_write( xfer, buffer, filesize );
 		if ( wrote > 0 )
 			purple_xfer_set_bytes_sent( xfer, wrote );
 
@@ -215,7 +218,7 @@
  */
 static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer )
 {
-	struct mxitxfer*	mx	= (struct mxitxfer*) xfer->data;
+	struct mxitxfer*	mx	= purple_xfer_get_protocol_data( xfer );
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" );
 
@@ -245,7 +248,7 @@
  */
 static void mxit_xfer_request_denied( PurpleXfer* xfer )
 {
-	struct mxitxfer*	mx		= (struct mxitxfer*) xfer->data;
+	struct mxitxfer*	mx		= purple_xfer_get_protocol_data( xfer );
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_request_denied\n" );
 
@@ -295,7 +298,7 @@
  */
 PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 	PurpleXfer*			xfer	= NULL;
 	struct mxitxfer*	mx		= NULL;
 
@@ -305,7 +308,7 @@
 	/* create file info and attach it to the file transfer */
 	mx = g_new0( struct mxitxfer, 1 );
 	mx->session = session;
-	xfer->data = mx;
+	purple_xfer_set_protocol_data( xfer, mx );
 
 	/* configure callbacks (reference: "libpurple/ft.h") */
 	purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
@@ -362,7 +365,7 @@
 		mx = g_new0( struct mxitxfer, 1 );
 		mx->session = session;
 		memcpy( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN );
-		xfer->data = mx;
+		purple_xfer_set_protocol_data( xfer, mx );
 
 		purple_xfer_set_filename( xfer, filename );
 		if( filesize > 0 )
@@ -395,9 +398,9 @@
 	while ( item ) {
 		xfer = item->data;
 
-		if ( xfer->account == session->acc ) {
+		if ( purple_xfer_get_account( xfer ) == session->acc ) {
 			/* transfer is associated with this MXit account */
-			struct mxitxfer* mx	= xfer->data;
+			struct mxitxfer* mx	= purple_xfer_get_protocol_data( xfer );
 
 			/* does the fileid match? */
 			if ( ( mx ) && ( memcmp( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ) == 0 ) )
@@ -431,12 +434,13 @@
 	/* find the file-transfer object */
 	xfer = find_mxit_xfer( session, fileid );
 	if ( xfer ) {
-		mx = xfer->data;
+		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 );
 		fwrite( data, datalen, 1, xfer->dest_fp );
+		// TODO: Handle error from fwrite()
 		purple_xfer_unref( xfer );
 		purple_xfer_set_completed( xfer, TRUE );
 		purple_xfer_end( xfer );
--- a/libpurple/protocols/mxit/formcmds.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/formcmds.c	Mon Oct 31 01:25:36 2011 +0000
@@ -86,7 +86,6 @@
 static void mxit_cb_ii_returned(PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message)
 {
 	struct ii_url_request*	iireq		= (struct ii_url_request*) user_data;
-	char*					ii_data;
 	int*					intptr		= NULL;
 	int						id;
 
@@ -106,12 +105,8 @@
 		goto done;
 	}
 
-	/* make a copy of the data */
-	ii_data = g_malloc(len);
-	memcpy(ii_data, (const char*) url_text, len);
-
-	/* we now have the inline image, store it in the imagestore */
-	id = purple_imgstore_add_with_id(ii_data, len, NULL);
+	/* we now have the inline image, store a copy in the imagestore */
+	id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
 
 	/* map the inline image id to purple image id */
 	intptr = g_malloc(sizeof(int));
@@ -253,8 +248,8 @@
 
 /*------------------------------------------------------------------------
  * Process a Reply MXit command.
- *  [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|id=12345:]
- *  [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|id=12345:]
+ *  [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
+ *  [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
  *
  *  @param mx			The received message data object
  *  @param hash			The MXit command <key,value> map
@@ -265,22 +260,26 @@
 	char* selmsg;
 	char* nm;
 
-	selmsg = g_hash_table_lookup(hash, "selmsg");			/* find the selection message */
-	replymsg = g_hash_table_lookup(hash, "replymsg");		/* find the reply message */
+	selmsg = g_hash_table_lookup(hash, "selmsg");			/* selection message */
+	replymsg = g_hash_table_lookup(hash, "replymsg");		/* reply message */
 	nm = g_hash_table_lookup(hash, "nm");					/* name parameter */
-	if ((selmsg) && (replymsg) && (nm)) {
+
+	if ((selmsg == NULL) || (replymsg == NULL))
+		return;		/* these parameters are required */
+
+	if (nm) {		/* indicates response must be a structured response */
 		gchar*	seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
-		gchar*	replycmd = g_strdup_printf("::type=reply|nm=%s|res=%s|err=0:", nm, replymsg);
+		gchar*	replycmd = g_strdup_printf("type=reply|nm=%s|res=%s|err=0", nm, replymsg);
 
-		mxit_add_html_link( mx, replycmd, seltext );
+		mxit_add_html_link( mx, replycmd, TRUE, seltext );
 
 		g_free(seltext);
 		g_free(replycmd);
 	}
-	else if ((selmsg) && (replymsg)) {
+	else {
 		gchar*	seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
 
-		mxit_add_html_link( mx, purple_url_decode(replymsg), seltext );
+		mxit_add_html_link( mx, purple_url_decode(replymsg), FALSE, seltext );
 
 		g_free(seltext);
 	}
@@ -317,6 +316,7 @@
 
 /*------------------------------------------------------------------------
  * Process an inline image MXit command.
+ *  [::op=img|dat=ASDF23408asdflkj2309flkjsadf%3d%3d|algn=1|w=120|h=12|t=100|replymsg=text:]
  *
  *  @param mx			The received message data object
  *  @param hash			The MXit command <key,value> map
@@ -362,7 +362,7 @@
 				purple_debug_info(MXIT_PLUGIN_ID, "sending request for inline image '%s'\n", iireq->url);
 
 				/* request the image (reference: "libpurple/util.h") */
-				purple_util_fetch_url_request(iireq->url, TRUE, NULL, TRUE, NULL, FALSE, mxit_cb_ii_returned, iireq);
+				purple_util_fetch_url(iireq->url, TRUE, NULL, TRUE, -1, mxit_cb_ii_returned, iireq);
 				mx->img_count++;
 			}
 		}
@@ -372,7 +372,7 @@
 	reply = g_hash_table_lookup(hash, "replymsg");
 	if (reply) {
 		g_string_append_printf(msg, "\n");
-		mxit_add_html_link(mx, reply, _( "click here" ));
+		mxit_add_html_link(mx, reply, FALSE, _( "click here" ));
 	}
 }
 
--- a/libpurple/protocols/mxit/http.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/http.c	Mon Oct 31 01:25:36 2011 +0000
@@ -273,7 +273,7 @@
 	/* source is the file descriptor of the new connection */
 	if ( source < 0 ) {
 		purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect failed: %s\n", error_message );
-		purple_connection_error( req->session->con, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) );
+		purple_connection_error( req->session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) );
 		return;
 	}
 
--- a/libpurple/protocols/mxit/login.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/login.c	Mon Oct 31 01:25:36 2011 +0000
@@ -49,29 +49,32 @@
  */
 static struct MXitSession* mxit_create_object( PurpleAccount* account )
 {
+	PurpleConnection*	con			= purple_account_get_connection( account );
 	struct MXitSession*	session		= NULL;
-	PurpleConnection*	con			= NULL;
 
 	/* currently the wapsite does not handle a '+' in front of the username (mxitid) so we just strip it */
-	if ( account->username[0] == '+' ) {
-		char*		fixed;
+	{
+		const char* username	= purple_account_get_username( account );
 
-		/* cut off the '+' */
-		fixed = g_strdup( &account->username[1] );
-		purple_account_set_username( account, fixed );
-		g_free( fixed );
+		if ( username[0] == '+' ) {
+			char* fixed	= g_strdup( &username[1] );
+			purple_account_set_username( account, fixed );
+			g_free( fixed );
+		}
 	}
 
 	session = g_new0( struct MXitSession, 1 );
+	session->con = con;
+	session->acc = account;
 
 	/* configure the connection (reference: "libpurple/connection.h") */
-	con = purple_account_get_connection( account );
-	con->proto_data = session;
-	con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS;
-	session->con = con;
-
-	/* add account */
-	session->acc = account;
+	purple_connection_set_protocol_data( con, session );
+	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 ) );
@@ -165,7 +168,7 @@
 	/* source is the file descriptor of the new connection */
 	if ( source < 0 ) {
 		purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect failed: %s\n", error_message );
-		purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect to the MXit server. Please check your server settings." ) );
 		return;
 	}
 
@@ -173,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 );
 }
@@ -202,7 +205,7 @@
 		/* socket connection */
 		data = purple_proxy_connect( session->con, session->acc, session->server, session->port, mxit_cb_connect, session );
 		if ( !data ) {
-			purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect to the MXit server. Please check your server settings." ) );
 			return;
 		}
 	}
@@ -221,7 +224,7 @@
  */
 static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields )
 {
-	struct MXitSession*		session		= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session		= purple_connection_get_protocol_data( gc );
 	struct MXitProfile*		profile		= session->profile;
 	const char*				str;
 	const char*				pin;
@@ -303,7 +306,7 @@
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_cancel\n" );
 
 	/* disconnect */
-	purple_account_disconnect( gc->account );
+	purple_account_disconnect( purple_connection_get_account( gc ) );
 }
 
 
@@ -391,7 +394,7 @@
 
 	if ( !url_text ) {
 		/* no reply from the WAP site */
-		purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Error contacting the MXit WAP site. Please try again later." ) );
 		return;
 	}
 
@@ -400,7 +403,7 @@
 
 	if ( !parts ) {
 		/* wapserver error */
-		purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "MXit is currently unable to process the request. Please try again later." ) );
 		return;
 	}
 
@@ -410,26 +413,26 @@
 				/* valid reply! */
 				break;
 			case '1' :
-				purple_connection_error( session->con, _( "Wrong security code entered. Please try again later." ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Wrong security code entered. Please try again later." ) );
 				return;
 			case '2' :
-				purple_connection_error( session->con, _( "Your session has expired. Please try again later." ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Your session has expired. Please try again later." ) );
 				return;
 			case '5' :
-				purple_connection_error( session->con, _( "Invalid country selected. Please try again." ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid country selected. Please try again." ) );
 				return;
 			case '6' :
-				purple_connection_error( session->con, _( "The MXit ID you entered is not registered. Please register first." ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "The MXit ID you entered is not registered. Please register first." ) );
 				return;
 			case '7' :
-				purple_connection_error( session->con, _( "The MXit ID you entered is already registered. Please choose another." ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "The MXit ID you entered is already registered. Please choose another." ) );
 				/* this user's account already exists, so we need to change the registration login flag to be login */
 				purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
 				return;
 			case '3' :
 			case '4' :
 			default :
-				purple_connection_error( session->con, _( "Internal error. Please try again later." ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Internal error. Please try again later." ) );
 				return;
 	}
 
@@ -507,7 +510,7 @@
  */
 static void mxit_cb_captcha_ok( PurpleConnection* gc, PurpleRequestFields* fields )
 {
-	struct MXitSession*		session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
 	PurpleUtilFetchUrlData*	url_data;
 	PurpleRequestField*		field;
 	const char*				captcha_resp;
@@ -548,10 +551,23 @@
 	state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
 
 	url = g_strdup_printf( "%s?type=getpid&sessionid=%s&login=%s&ver=%i.%i.%i&clientid=%s&cat=%s&chalresp=%s&cc=%s&loc=%s&path=%i&brand=%s&model=%s&h=%i&w=%i&ts=%li",
-			session->logindata->wapserver, session->logindata->sessionid, purple_url_encode( session->acc->username ), PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CLIENT_ID, MXIT_CP_ARCH,
-			captcha_resp, session->logindata->cc, session->logindata->locale, ( state == MXIT_STATE_REGISTER1 ) ? 0 : 1, MXIT_CP_PLATFORM, MXIT_CP_OS,
-			MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
-	url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo2, session );
+			session->logindata->wapserver,
+			session->logindata->sessionid,
+			purple_url_encode( purple_account_get_username( session->acc ) ),
+			PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION,
+			MXIT_CLIENT_ID,
+			MXIT_CP_ARCH,
+			captcha_resp,
+			session->logindata->cc,
+			session->logindata->locale,
+			( state == MXIT_STATE_REGISTER1 ) ? 0 : 1,
+			MXIT_CP_PLATFORM,
+			MXIT_CP_OS,
+			MXIT_CAPTCHA_HEIGHT,
+			MXIT_CAPTCHA_WIDTH,
+			time( NULL )
+	);
+	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
 	purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
@@ -571,7 +587,7 @@
  */
 static void mxit_cb_captcha_cancel( PurpleConnection* gc, PurpleRequestFields* fields )
 {
-	struct MXitSession*		session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
 
 	/* free up the login resources */
 	free_logindata( session->logindata );
@@ -611,7 +627,7 @@
 
 	if ( !url_text ) {
 		/* no reply from the WAP site */
-		purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Error contacting the MXit WAP site. Please try again later." ) );
 		return;
 	}
 
@@ -620,7 +636,7 @@
 
 	if ( ( !parts ) || ( parts[0][0] != '0' ) ) {
 		/* server could not find the user */
-		purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "MXit is currently unable to process the request. Please try again later." ) );
 		return;
 	}
 
@@ -658,7 +674,7 @@
 			/* oops, this is not good, time to bail */
 			break;
 		}
-		purple_request_field_list_add( field, country[1], g_strdup( country[0] ) );
+		purple_request_field_list_add_icon( field, country[1], NULL, g_strdup( country[0] ) );
 		if ( strcmp( country[1], parts[6] ) == 0 ) {
 			/* based on the user's IP, this is his current country code, so we default to it */
 			purple_request_field_list_add_selected( field, country[1] );
@@ -679,7 +695,7 @@
 			/* oops, this is not good, time to bail */
 			break;
 		}
-		purple_request_field_list_add( field, locale[1], g_strdup( locale[0] ) );
+		purple_request_field_list_add_icon( field, locale[1], NULL, g_strdup( locale[0] ) );
 		g_strfreev( locale );
 	}
 	purple_request_field_list_add_selected( field, "English" );
@@ -715,7 +731,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 ) );
-	url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo1, session );
+	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
 	purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
@@ -743,7 +759,7 @@
 	 * if we don't have any info saved from a previous login, we need to get it from the MXit WAP site.
 	 * we do cache it, so this step is only done on the very first login for each account.
 	 */
-	if ( ( session->distcode == NULL ) || ( strlen( session->distcode ) == 0 ) ) {
+	if ( ( session->distcode == NULL ) || ( !*session->distcode ) ) {
 		/* this must be the very first login, so we need to retrieve the user information */
 		get_clientinfo( session );
 	}
@@ -764,9 +780,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/markup.c	Mon Oct 31 01:25:36 2011 +0000
@@ -124,10 +124,11 @@
  * Adds a link to a message
  *
  *  @param mx				The Markup message object
- *	@param linkname			This is the what will be returned when the link gets clicked
- *	@param displayname		This is the name for the link which will be displayed in the UI
+ *	@param replydata		This is the what will be returned when the link gets clicked
+ *	@param isStructured		Indicates that the reply is a structured reply
+ *	@param displaytext		This is the text for the link which will be displayed in the UI
  */
-void mxit_add_html_link( struct RXMsgData* mx, const char* linkname, const char* displayname )
+void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext )
 {
 #ifdef	MXIT_LINK_CLICK
 	char	retstr[256];
@@ -135,15 +136,24 @@
 	char	link[256];
 	int		len;
 
-	len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%s", MXIT_LINK_KEY, purple_account_get_username( mx->session->acc ),
-											purple_account_get_protocol_id( mx->session->acc ), mx->from, linkname );
+	/*
+	 * The link content is encoded as follows:
+	 *  MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA
+	 */
+	len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%i|%s",
+			MXIT_LINK_KEY,
+			purple_account_get_username( mx->session->acc ),
+			purple_account_get_protocol_id( mx->session->acc ),
+			mx->from,
+			isStructured ? 1 : 0,
+			replydata );
 	retstr64 = purple_base64_encode( (const unsigned char*) retstr, len );
 	g_snprintf( link, sizeof( link ), "%s%s", MXIT_LINK_PREFIX, retstr64 );
 	g_free( retstr64 );
 
-	g_string_append_printf( mx->msg, "<a href=\"%s\">%s</a>", link, displayname );
+	g_string_append_printf( mx->msg, "<a href=\"%s\">%s</a>", link, displaytext );
 #else
-	g_string_append_printf( mx->msg, "<b>%s</b>", linkname );
+	g_string_append_printf( mx->msg, "<b>%s</b>", replydata );
 #endif
 }
 
@@ -618,7 +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 ) );
-	url_data = purple_util_fetch_url_request( url, TRUE, NULL, TRUE, NULL, FALSE, emoticon_returned, mx );
+	url_data = purple_util_fetch_url( url, TRUE, NULL, TRUE, -1, emoticon_returned, mx );
 	g_free( url );
 }
 
@@ -735,6 +745,7 @@
 	gboolean	tag_bold	= FALSE;
 	gboolean	tag_under	= FALSE;
 	gboolean	tag_italic	= FALSE;
+	int			font_size	= 0;
 
 #ifdef MXIT_DEBUG_MARKUP
 	purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message );
@@ -823,7 +834,7 @@
 					if ( ch ) {
 						/* end found */
 						*ch = '\0';
-						mxit_add_html_link( mx, &message[i + 1], &message[i + 1] );
+						mxit_add_html_link( mx, &message[i + 1], FALSE, &message[i + 1] );
 						*ch = '$';
 						i += ( ch - &message[i + 1] ) + 1;
 					}
@@ -862,59 +873,54 @@
 					}
 					break;
 			case '.' :
-					if ( !( msgflags & CP_MSG_EMOTICON ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-					else if ( i + 1 >= len ) {
+					if ( i + 1 >= len ) {
 						/* message too short */
 						g_string_append_c( mx->msg, '.' );
 						break;
 					}
 
-					switch ( message[i+1] ) {
-						case '+' :
-								/* increment text size */
-								g_string_append( mx->msg, "<font size=\"+1\">" );
-								i++;
-								break;
-						case '-' :
-								/* decrement text size */
-								g_string_append( mx->msg, "<font size=\"-1\">" );
-								i++;
-								break;
-						case '{' :
-								/* custom emoticon */
-								if ( i + 2 >= len ) {
-									/* message too short */
-									g_string_append_c( mx->msg, '.' );
-									break;
-								}
+					if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) {
+						/* custom emoticon */
+						if ( i + 2 >= len ) {
+							/* message too short */
+							g_string_append_c( mx->msg, '.' );
+							break;
+						}
+
+						parse_emoticon_str( &message[i+2], tmpstr1 );
+						if ( tmpstr1[0] != '\0' ) {
+							mx->got_img = TRUE;
+
+							if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
+								/* emoticon found in the cache, so we do not have to request it from the WAPsite */
+							}
+							else {
+								/* request emoticon from the WAPsite */
+								mx->img_count++;
+								emoticon_request( mx, tmpstr1 );
+							}
 
-								parse_emoticon_str( &message[i+2], tmpstr1 );
-								if ( tmpstr1[0] != '\0' ) {
-									mx->got_img = TRUE;
+							g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
+							i += strlen( tmpstr1 ) + 2;
+						}
+						else
+							g_string_append_c( mx->msg, '.' );
+					}
+					else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) {
+						/* increment text size */
+						font_size++;
+						g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
+						i++;
+					}
+					else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) {
+						/* decrement text size */
+						font_size--;
+						g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
+						i++;
+					}
+					else
+						g_string_append_c( mx->msg, '.' );
 
-									if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
-										/* emoticon found in the cache, so we do not have to request it from the WAPsite */
-									}
-									else {
-										/* request emoticon from the WAPsite */
-										mx->img_count++;
-										emoticon_request( mx, tmpstr1 );
-									}
-
-									g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
-									i += strlen( tmpstr1 ) + 2;
-								}
-								else
-									g_string_append_c( mx->msg, '.' );
-
-								break;
-						default :
-								g_string_append_c( mx->msg, '.' );
-								break;
-					}
 					break;
 			case '\\' :
 					if ( i + 1 >= len ) {
--- a/libpurple/protocols/mxit/markup.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/markup.h	Mon Oct 31 01:25:36 2011 +0000
@@ -31,7 +31,7 @@
 
 void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags );
 char* mxit_convert_markup_tx( const char* message, int* msgtype );
-void mxit_add_html_link( struct RXMsgData* mx, const char* linkname, const char* displayname );
+void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext );
 void mxit_show_message( struct RXMsgData* mx );
 
 void mxit_free_emoticon_cache( struct MXitSession* session );
--- a/libpurple/protocols/mxit/multimx.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/multimx.c	Mon Oct 31 01:25:36 2011 +0000
@@ -277,7 +277,11 @@
 	GHashTable *components;
 	struct multimx* multimx = NULL;
 
-	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' by '%s'\n", contact->alias, creator);
+	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' (roomid='%s') by '%s'\n", contact->alias, contact->username, creator);
+
+	/* Check if the room already exists (ie, already joined or invite pending) */
+	if (find_room_by_username(session, contact->username) != NULL)
+		return;
 
 	/* Create a new room */
 	multimx = room_create(session, contact->username, contact->alias, STATE_INVITED);
@@ -307,7 +311,7 @@
 	multimx = find_room_by_username(session, contact->username);
 	if (multimx == NULL) {
 		multimx = room_create(session, contact->username, contact->alias, TRUE);
-		}
+	}
 	else if (multimx->state == STATE_INVITED) {
 		/* After successfully accepting an invitation */
 		multimx->state = STATE_JOINED;
@@ -454,7 +458,7 @@
  */
 void mxit_chat_join(PurpleConnection *gc, GHashTable *components)
 {
-	struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+	struct MXitSession* session = purple_connection_get_protocol_data(gc);
 	const char* roomname = NULL;
 	struct multimx* multimx = NULL;
 
@@ -496,7 +500,7 @@
  */
 void mxit_chat_reject(PurpleConnection *gc, GHashTable* components)
 {
-	struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+	struct MXitSession* session = purple_connection_get_protocol_data(gc);
 	const char* roomname = NULL;
 	struct multimx* multimx = NULL;
 
@@ -539,7 +543,7 @@
  */
 void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *username)
 {
-	struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+	struct MXitSession* session = purple_connection_get_protocol_data(gc);
 	struct multimx* multimx = NULL;
 	PurpleBuddy* buddy;
 	PurpleConversation *convo;
@@ -585,7 +589,7 @@
  */
 void mxit_chat_leave(PurpleConnection *gc, int id)
 {
-	struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+	struct MXitSession* session = purple_connection_get_protocol_data(gc);
 	struct multimx* multimx = NULL;
 
 	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i leave\n", id);
@@ -616,7 +620,7 @@
  */
 int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
 {
-	struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+	struct MXitSession* session = purple_connection_get_protocol_data(gc);
 	struct multimx* multimx = NULL;
 	const char* nickname;
 
--- a/libpurple/protocols/mxit/mxit.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/mxit.c	Mon Oct 31 01:25:36 2011 +0000
@@ -58,7 +58,7 @@
 static void* mxit_link_click( const char* link64 )
 {
 	PurpleAccount*		account;
-	PurpleConnection*	con;
+	PurpleConnection*	gc;
 	gchar**				parts		= NULL;
 	gchar*				link		= NULL;
 	gsize				len;
@@ -75,10 +75,10 @@
 	link = (gchar*) purple_base64_decode( link64 + strlen( MXIT_LINK_PREFIX ), &len );
 	purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link );
 
-	parts = g_strsplit( link, "|", 5 );
+	parts = g_strsplit( link, "|", 6 );
 
 	/* check if this is a valid mxit link */
-	if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) ) {
+	if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) || ( !parts[5] ) ) {
 		/* this is not for us */
 		goto skip;
 	}
@@ -91,15 +91,15 @@
 	account = purple_accounts_find( parts[1], parts[2] );
 	if ( !account )
 		goto skip;
-	con = purple_account_get_connection( account );
-	if ( !con )
+	gc = purple_account_get_connection( account );
+	if ( !gc )
 		goto skip;
 
 	/* determine if it's a command-response to send */
-	is_command = g_str_has_prefix( parts[4], "::type=reply|" );
+	is_command = ( atoi( parts[4] ) == 1 );
 
 	/* send click message back to MXit */
-	mxit_send_message( con->proto_data, parts[3], parts[4], FALSE, is_command );
+	mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command );
 
 	g_free( link );
 	link = NULL;
@@ -129,7 +129,7 @@
 /*------------------------------------------------------------------------
  * Register MXit to receive URI click notifications from the UI
  */
-void mxit_register_uri_handler(void)
+void mxit_register_uri_handler( void )
 {
 	not_link_ref_count++;
 	if ( not_link_ref_count == 1 ) {
@@ -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;
@@ -198,7 +198,7 @@
 	if ( !buddy )
 		return;
 
-	contact = purple_buddy_get_protocol_data(buddy);
+	contact = purple_buddy_get_protocol_data( buddy );
 	if ( !contact )
 		return;
 
@@ -214,7 +214,7 @@
 		case MXIT_TYPE_INFO :
 				tmp = g_strdup_printf("<font color=\"#999999\">%s</font>\n", _( "Loading menu..." ));
 				serv_got_im( session->con, who, tmp, PURPLE_MESSAGE_NOTIFY, time( NULL ) );
-				g_free(tmp);
+				g_free( tmp );
 				mxit_send_message( session, who, " ", FALSE, FALSE );
 		default :
 				break;
@@ -268,7 +268,7 @@
  */
 static const char* mxit_list_emblem( PurpleBuddy* buddy )
 {
-	struct contact*	contact = purple_buddy_get_protocol_data(buddy);
+	struct contact*	contact = purple_buddy_get_protocol_data( buddy );
 
 	if ( !contact )
 		return NULL;
@@ -309,19 +309,18 @@
  */
 char* mxit_status_text( PurpleBuddy* buddy )
 {
-	struct contact*	contact = purple_buddy_get_protocol_data(buddy);
+	char* text = NULL;
+	struct contact*	contact = purple_buddy_get_protocol_data( buddy );
 
 	if ( !contact )
 		return NULL;
 
-	if ( contact->statusMsg ) {
-		/* status message */
-		return g_strdup( contact-> statusMsg );
-	}
-	else {
-		/* mood */
-		return g_strdup( mxit_convert_mood_to_name( contact->mood ) );
-	}
+	if ( contact->statusMsg )							/* status message */
+		text = g_strdup( contact-> statusMsg );
+	else if ( contact->mood != MXIT_MOOD_NONE )			/* mood */
+		text = g_strdup( mxit_convert_mood_to_name( contact->mood ) );
+
+	return text;
 }
 
 
@@ -334,34 +333,33 @@
  */
 static void mxit_tooltip( PurpleBuddy* buddy, PurpleNotifyUserInfo* info, gboolean full )
 {
-	struct contact*	contact = purple_buddy_get_protocol_data(buddy);
+	struct contact*	contact = purple_buddy_get_protocol_data( buddy );
 
 	if ( !contact )
 		return;
 
 	/* status (reference: "libpurple/notify.h") */
 	if ( contact->presence != MXIT_PRESENCE_OFFLINE )
-		purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
 
 	/* status message */
-	if ( contact->statusMsg )
-		purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
+	if ( contact->statusMsg ) {
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg );
+	}
 
 	/* mood */
 	if ( contact->mood != MXIT_MOOD_NONE )
-		purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
 
 	/* subscription type */
 	if ( contact->subtype != 0 )
-		purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
 
 	/* rejection message */
 	if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) )
-		purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg );
-
-	/* hidden number */
-	if ( contact->flags & MXIT_CFLAG_HIDDEN )
-		purple_notify_user_info_add_pair( info, _( "Hidden Number" ), _( "Yes" ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Rejection Message" ), contact->msg );
 }
 
 
@@ -372,7 +370,7 @@
  */
 static void mxit_close( PurpleConnection* gc )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 
 	/* disable signals */
 	mxit_disable_signals( session );
@@ -408,7 +406,7 @@
 {
 	purple_debug_info( MXIT_PLUGIN_ID, "Sending message '%s' to buddy '%s'\n", message, who );
 
-	mxit_send_message( gc->proto_data, who, message, TRUE, FALSE );
+	mxit_send_message( purple_connection_get_protocol_data( gc ), who, message, TRUE, FALSE );
 
 	return 1;		/* echo to conversation window */
 }
@@ -422,14 +420,14 @@
  */
 static void mxit_set_status( PurpleAccount* account, PurpleStatus* status )
 {
-	struct MXitSession*		session =	purple_account_get_connection( account )->proto_data;
+	struct MXitSession*		session =	purple_connection_get_protocol_data( purple_account_get_connection( account ) );
 	const char*				statusid;
 	int						presence;
 	char*					statusmsg1;
 	char*					statusmsg2;
 
 	/* Handle mood changes */
-	if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+	if ( purple_status_type_get_primitive(purple_status_get_type( status ) ) == PURPLE_STATUS_MOOD ) {
 		const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME );
 		int mood;
 
@@ -492,7 +490,7 @@
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_free_buddy\n" );
 
-	contact = purple_buddy_get_protocol_data(buddy);
+	contact = purple_buddy_get_protocol_data( buddy );
 	if ( contact ) {
 		if ( contact->statusMsg )
 			g_free( contact->statusMsg );
@@ -503,7 +501,7 @@
 		g_free( contact );
 	}
 
-	purple_buddy_set_protocol_data(buddy, NULL);
+	purple_buddy_set_protocol_data( buddy, NULL );
 }
 
 
@@ -515,7 +513,7 @@
  */
 static void mxit_keepalive( PurpleConnection *gc )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 
 	/* if not logged in, there is nothing to do */
 	if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) )
@@ -543,7 +541,7 @@
  */
 static void mxit_set_buddy_icon( PurpleConnection *gc, PurpleStoredImage *img )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 
 	if ( img == NULL )
 		mxit_set_avatar( session, NULL, 0 );
@@ -562,7 +560,7 @@
 {
 	PurpleBuddy*			buddy;
 	struct contact*			contact;
-	struct MXitSession*		session			= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
 	const char*				profilelist[]	= { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
 												CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN,
 												CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
@@ -612,14 +610,10 @@
  */
 static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored )
 {
-	PurpleBuddy*		buddy;
+	PurpleBuddy*		buddy		= (PurpleBuddy *) node;
+	PurpleConnection*	gc			= purple_account_get_connection( purple_buddy_get_account( buddy ) );
+	struct MXitSession*	session		= purple_connection_get_protocol_data( gc );
 	struct contact*		contact;
-	PurpleConnection*	gc;
-	struct MXitSession*	session;
-
-	buddy = (PurpleBuddy *)node;
-	gc = purple_account_get_connection( purple_buddy_get_account( buddy ) );
-	session = gc->proto_data;
 
 	contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node );
 	if ( !contact )
@@ -653,15 +647,28 @@
 	if ( ( contact->subtype == MXIT_SUBTYPE_DELETED ) || ( contact->subtype == MXIT_SUBTYPE_REJECTED ) || ( contact->subtype == MXIT_SUBTYPE_NONE ) ) {
 		/* contact is in Deleted, Rejected or None state */
 		act = purple_menu_action_new( _( "Re-Invite" ), PURPLE_CALLBACK( mxit_reinvite ), NULL, NULL );
-		m = g_list_append(m, act);
+		m = g_list_append( m, act );
 	}
 
 	return m;
 }
 
+
+/*------------------------------------------------------------------------
+ * Return Chat-room default settings.
+ *
+ *  @return		Chat defaults list
+ */
+static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *chat_name )
+{
+    return g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free );
+}
+
+
 /*========================================================================================================================*/
 
 static PurplePluginProtocolInfo proto_info = {
+	sizeof( PurplePluginProtocolInfo ),		/* struct_size */
 	OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,			/* options */
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
@@ -680,7 +687,7 @@
 	mxit_status_types,		/* status types				[roster.c] */
 	mxit_blist_menu,		/* blist_node_menu */
 	mxit_chat_info,			/* chat_info				[multimx.c] */
-	NULL,					/* chat_info_defaults */
+	mxit_chat_info_defaults,/* chat_info_defaults */
 	mxit_login,				/* login					[login.c] */
 	mxit_close,				/* close */
 	mxit_send_im,			/* send_im */
@@ -690,7 +697,7 @@
 	mxit_set_status,		/* set_status */
 	NULL,					/* set_idle */
 	NULL,					/* change_passwd */
-	NULL,					/* add_buddy				[roster.c] */
+	mxit_add_buddy,			/* add_buddy				[roster.c] */
 	NULL,					/* add_buddies */
 	mxit_remove_buddy,		/* remove_buddy				[roster.c] */
 	NULL,					/* remove_buddies */
@@ -709,7 +716,6 @@
 	mxit_keepalive,			/* keepalive */
 	mxit_register,			/* register_user */
 	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
 	mxit_buddy_alias,		/* alias_buddy				[roster.c] */
 	mxit_buddy_group,		/* group_buddy				[roster.c] */
 	mxit_rename_group,		/* rename_group				[roster.c] */
@@ -734,15 +740,12 @@
 	NULL,					/* unregister_user */
 	NULL,					/* send_attention */
 	NULL,					/* attention_types */
-	sizeof( PurplePluginProtocolInfo ),		/* struct_size */
 	mxit_get_text_table,	/* get_account_text_table */
 	mxit_media_initiate,	/* initiate_media */
 	mxit_media_caps,		/* get_media_caps */
 	mxit_get_moods,			/* get_moods */
 	NULL,					/* set_public_alias */
-	NULL,					/* get_public_alias */
-	mxit_add_buddy,			/* add_buddy_with_invite */
-	NULL					/* add_buddies_with_invite */
+	NULL					/* get_public_alias */
 };
 
 
--- a/libpurple/protocols/mxit/mxit.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/mxit.h	Mon Oct 31 01:25:36 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) */
@@ -191,7 +192,7 @@
 void mxit_enable_signals( struct MXitSession* session );
 
 #ifdef	MXIT_LINK_CLICK
-void mxit_register_uri_handler(void);
+void mxit_register_uri_handler( void );
 #endif
 
 
--- a/libpurple/protocols/mxit/profile.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/profile.c	Mon Oct 31 01:25:36 2011 +0000
@@ -115,16 +115,16 @@
 	struct tm now, bdate;
 	int age;
 
-	if ( ( !date ) || ( strlen( date ) == 0 ) )
+	if ( ( !date ) || ( !*date ) )
 		return 0;
 
 	/* current time */
-	t = time(NULL);
+	t = time( NULL );
 	localtime_r( &t, &now );
 
 	/* decode hdate */
 	memset( &bdate, 0, sizeof( struct tm ) );
-	purple_str_to_time(date, FALSE, &bdate, NULL, NULL);
+	purple_str_to_time( date, FALSE, &bdate, NULL, NULL );
 
 	/* calculate difference */
 	age = now.tm_year - bdate.tm_year;
@@ -170,54 +170,56 @@
 
 	buddy = purple_find_buddy( session->acc, username );
 	if ( buddy ) {
-		purple_notify_user_info_add_pair( info, _( "Alias" ), purple_buddy_get_alias( buddy ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Alias" ), purple_buddy_get_alias( buddy ) );
 		purple_notify_user_info_add_section_break( info );
-		contact = purple_buddy_get_protocol_data(buddy);
+		contact = purple_buddy_get_protocol_data( buddy );
 	}
 
-	purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname );
+	purple_notify_user_info_add_pair_plaintext( info, _( "Display Name" ), profile->nickname );
 
 	tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) );
-	purple_notify_user_info_add_pair( info, _( "Birthday" ), tmp );
+	purple_notify_user_info_add_pair_plaintext( info, _( "Birthday" ), tmp );
 	g_free( tmp );
 
-	purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
+	purple_notify_user_info_add_pair_plaintext( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
 
 	/* optional information */
-	purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname );
-	purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname );
-	purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry );
+	purple_notify_user_info_add_pair_plaintext( info, _( "First Name" ), profile->firstname );
+	purple_notify_user_info_add_pair_plaintext( info, _( "Last Name" ), profile->lastname );
+
+	purple_notify_user_info_add_pair_plaintext( info, _( "Country" ), profile->regcountry );
 
-	if ( strlen( profile->aboutme ) > 0 )
-		purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme );
-	if ( strlen( profile->whereami ) > 0 )
-		purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami );
+	if ( *profile->aboutme )
+		purple_notify_user_info_add_pair_plaintext( info, _( "About Me" ), profile->aboutme );
+
+	if ( *profile->whereami )
+		purple_notify_user_info_add_pair_plaintext( info, _( "Where I Live" ), profile->whereami );
 
 	purple_notify_user_info_add_section_break( info );
 
 	if ( contact ) {
 		/* presence */
-		purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
 
 		/* last online */
 		if ( contact->presence == MXIT_PRESENCE_OFFLINE )
-			purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
+			purple_notify_user_info_add_pair_plaintext( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
 
 		/* mood */
 		if ( contact->mood != MXIT_MOOD_NONE )
-			purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
+			purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
 		else
-			purple_notify_user_info_add_pair( info, _( "Mood" ), _( "None" ) );
+			purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), _( "None" ) );
 
 		/* status message */
-		if ( contact->statusMsg )
-			purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
+		if ( contact->statusMsg ) {
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg );
+		}
 
 		/* subscription type */
-		purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
-
-		/* hidden number */
-		purple_notify_user_info_add_pair( info, _( "Hidden Number" ), ( contact->flags & MXIT_CFLAG_HIDDEN ) ? _( "Yes" ) : _( "No" ) );
+		purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
 	}
 	else {
 		/* this is an invite */
@@ -226,17 +228,21 @@
 			/* invite found */
 
 			if ( contact->msg )
-				purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg );
+				purple_notify_user_info_add_pair_plaintext( info, _( "Invite Message" ), contact->msg );
 
 			if ( contact->imgid ) {
 				/* this invite has a avatar */
 				char* img_text;
 				img_text = g_strdup_printf( "<img id='%d'>", contact->imgid );
-				purple_notify_user_info_add_pair( info, _( "Photo" ), img_text );
+				purple_notify_user_info_add_pair_html( info, _( "Photo" ), img_text );
+				g_free(img_text);
 			}
 
-			if ( contact->statusMsg )
-				purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
+			if ( contact->statusMsg ) {
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg );
+			}
 		}
 	}
 
@@ -284,6 +290,7 @@
 
 	/* define columns */
 	column = purple_notify_searchresults_column_new( _( "UserId" ) );
+	purple_notify_searchresult_column_set_visible( column, FALSE );
 	purple_notify_searchresults_column_add( results, column );
 	column = purple_notify_searchresults_column_new( _( "Display Name" ) );
 	purple_notify_searchresults_column_add( results, column );
@@ -298,7 +305,7 @@
 	column = purple_notify_searchresults_column_new( _( "Where I live" ) );
 	purple_notify_searchresults_column_add( results, column );
 
-	while (entries != NULL) {
+	while ( entries != NULL ) {
 		struct MXitProfile* profile	= ( struct MXitProfile *) entries->data;
 		GList*	row;
 		gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) );
@@ -328,5 +335,5 @@
 
 	purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL );
 
-	g_free( text);
+	g_free( text );
 }
--- a/libpurple/protocols/mxit/profile.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/profile.h	Mon Oct 31 01:25:36 2011 +0000
@@ -50,7 +50,6 @@
 
 	int			flags;								/* user's profile flags */
 	gint64		lastonline;							/* user's last-online timestamp */
-	gboolean	hidden;								/* set if the user's mxitid should remain hidden */
 };
 
 struct MXitSession;
--- a/libpurple/protocols/mxit/protocol.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.c	Mon Oct 31 01:25:36 2011 +0000
@@ -86,7 +86,7 @@
 void mxit_strip_domain( char* username )
 {
 	if ( g_str_has_suffix( username, "@m" ) )
-		username[ strlen(username) - 2 ] = '\0';
+		username[ strlen( username ) - 2 ] = '\0';
 }
 
 
@@ -311,7 +311,7 @@
 #endif
 
 	/* send the HTTP request */
-	session->http_out_req = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session );
+	session->http_out_req = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_http_rx, session );
 
 	g_free( url );
 	if ( part )
@@ -408,7 +408,7 @@
 		res = mxit_write_sock_packet( session->fd, data, datalen );
 		if ( res < 0 ) {
 			/* we must have lost the connection, so terminate it so that we can reconnect */
-			purple_connection_error( session->con, _( "We have lost the connection to MXit. Please reconnect." ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "We have lost the connection to MXit. Please reconnect." ) );
 		}
 	}
 	else {
@@ -458,7 +458,7 @@
 	packet->headerlen = 0;
 
 	/* create generic packet header */
-	hlen = snprintf( header, sizeof( header ), "id=%s%c", session->acc->username, CP_REC_TERM );			/* client msisdn */
+	hlen = snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc), CP_REC_TERM );			/* client msisdn */
 
 	if ( session->http ) {
 		/* http connection only */
@@ -530,7 +530,7 @@
 		if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
 			/* ack timeout! so we close the connection here */
 			purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
-			purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Timeout while waiting for a response from the MXit server." ) );
 		}
 		return;
 	}
@@ -704,9 +704,9 @@
 	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
 
 	/* Voice and Video supported */
-	if (mxit_audio_enabled() && mxit_video_enabled())
-		features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO);
-	else if (mxit_audio_enabled())
+	if ( mxit_audio_enabled() && mxit_video_enabled() )
+		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
+	else if ( mxit_audio_enabled() )
 		features |= MXIT_CF_VOICE;
 
 	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
@@ -748,9 +748,9 @@
 	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
 
 	/* Voice and Video supported */
-	if (mxit_audio_enabled() && mxit_video_enabled())
-		features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO);
-	else if (mxit_audio_enabled())
+	if ( mxit_audio_enabled() && mxit_video_enabled() )
+		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
+	else if ( mxit_audio_enabled() )
 		features |= MXIT_CF_VOICE;
 
 	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
@@ -835,7 +835,7 @@
 
 	/* add attributes */
 	for ( i = 0; i < nr_attrib; i++ )
-		datalen += sprintf(	data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+		datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
 
 	/* queue packet for transmission */
 	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
@@ -868,7 +868,7 @@
 
 	/* add attributes */
 	for ( i = 1; i < nr_attrib * 3; i+=3 )
-		datalen += sprintf(	data + datalen, "%c%s%c%s%c%s",		/* \1name\1type\1value  */
+		datalen += sprintf( data + datalen, "%c%s%c%s%c%s",		/* \1name\1type\1value  */
 								CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
 
 	/* queue packet for transmission */
@@ -900,7 +900,7 @@
 
 	/* add attributes */
 	for ( i = 0; i < nr_attrib; i++ )
-		datalen += sprintf(	data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+		datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
 
 	/* queue packet for transmission */
 	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
@@ -929,7 +929,7 @@
 
 	/* add attributes */
 	for ( i = 0; i < nr_attrib; i++ )
-		datalen += sprintf(	data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+		datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
 
 	/* queue packet for transmission */
 	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
@@ -1175,7 +1175,7 @@
 
 	/* add usernames */
 	for ( i = 0; i < nr_usernames; i++ )
-		datalen += sprintf(	data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+		datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
 
 	/* queue packet for transmission */
 	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
@@ -1204,7 +1204,7 @@
 
 	/* add usernames */
 	for ( i = 0; i < nr_usernames; i++ )
-		datalen += sprintf(	data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+		datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
 
 	/* queue packet for transmission */
 	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
@@ -1448,7 +1448,7 @@
 	PurpleStatus*	status;
 	int				presence;
 	const char*		statusmsg;
-	const char*		profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_HIDENUMBER, CP_PROFILE_FULLNAME,
+	const char*		profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
 									CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
 									CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_FLAGS };
 
@@ -1516,6 +1516,7 @@
 {
 	struct RXMsgData*	mx			= NULL;
 	char*				message		= NULL;
+	char*				sender		= NULL;
 	int					msglen		= 0;
 	int					msgflags	= 0;
 	int					msgtype		= 0;
@@ -1529,10 +1530,11 @@
 	msglen = strlen( message );
 
 	/* strip off dummy domain */
-	mxit_strip_domain( records[0]->fields[0]->data );
+	sender = records[0]->fields[0]->data;
+	mxit_strip_domain( sender );
 
 #ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", records[0]->fields[0]->data );
+	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
 #endif
 
 	/* decode message flags (if any) */
@@ -1540,33 +1542,42 @@
 		msgflags = atoi( records[0]->fields[4]->data );
 	msgtype = atoi( records[0]->fields[2]->data );
 
-	if ( msgflags & CP_MSG_ENCRYPTED ) {
-		/* this is an encrypted message. we do not currently support those so ignore it */
+	if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
+		/* this is a password encrypted message. we do not currently support those so ignore it */
 		PurpleBuddy*	buddy;
 		const char*		name;
 		char			msg[128];
 
-		buddy = purple_find_buddy( session->acc, records[0]->fields[0]->data );
+		buddy = purple_find_buddy( session->acc, sender );
 		if ( buddy )
 			name = purple_buddy_get_alias( buddy );
 		else
-			name = records[0]->fields[0]->data;
+			name = sender;
 		g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
 		mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
 		return;
 	}
+	else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
+		/* this is a transport-layer encrypted message. */
+		message = mxit_decrypt_message( session, message );
+		if ( !message ) {
+			/* could not be decrypted */
+			serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
+			return;
+		}
+	}
 
 	if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
 		/* delivery notification is requested */
 		if ( records[0]->fcount >= 4 )
-			mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
+			mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
 	}
 
 	/* create and initialise new markup struct */
 	mx = g_new0( struct RXMsgData, 1 );
 	mx->msg = g_string_sized_new( msglen );
 	mx->session = session;
-	mx->from = g_strdup( records[0]->fields[0]->data );
+	mx->from = g_strdup( sender );
 	mx->timestamp = atoi( records[0]->fields[1]->data );
 	mx->got_img = FALSE;
 	mx->chatid = -1;
@@ -1597,6 +1608,10 @@
 		 * so the image received callback function will eventually display
 		 * the message. */
 	}
+
+	/* cleanup */
+	if ( msgflags & CP_MSG_TL_ENCRYPTED )
+		g_free( message );
 }
 
 
@@ -1633,7 +1648,7 @@
 
 		if ( rec->fcount >= 5 ) {
 			/* there is a personal invite message attached */
-			if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) )
+			if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) )
 				contact->msg = strdup( rec->fields[4]->data );
 		}
 
@@ -1810,10 +1825,6 @@
 			/* gender */
 			profile->male = ( fvalue[0] == '1' );
 		}
-		else if ( strcmp( CP_PROFILE_HIDENUMBER, fname ) == 0 ) {
-			/* hide number */
-			profile->hidden = ( fvalue[0] == '1' );
-		}
 		else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
 			/* nickname */
 			g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
@@ -1879,7 +1890,7 @@
 		contact = get_mxit_invite_contact( session, mxitId );
 		if ( contact ) {
 			/* this is an invite, so update its profile info */
-			if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
+			if ( ( statusMsg ) && ( *statusMsg ) ) {
 				/* update the status message */
 				if ( contact->statusMsg )
 					g_free( contact->statusMsg );
@@ -1890,7 +1901,7 @@
 			if ( contact->profile )
 				g_free( contact->profile );
 			contact->profile = profile;
-			if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) {
+			if ( ( avatarId ) && ( *avatarId ) ) {
 				/* avatar must be requested for this invite before we can display it */
 				mxit_get_avatar( session, mxitId, avatarId );
 				if ( contact->avatarId )
@@ -1908,7 +1919,7 @@
 			if ( avatarId )
 				mxit_update_buddy_avatar( session, mxitId, avatarId );
 
-			if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
+			if ( ( statusMsg ) && ( *statusMsg ) ) {
 				/* update the status message */
 				PurpleBuddy*		buddy	= NULL;
 
@@ -2125,13 +2136,13 @@
 					contact = get_mxit_invite_contact( session, chunk.mxitid );
 					if ( contact ) {
 						/* this is an invite (add image to the internal image store) */
-						contact->imgid = purple_imgstore_add_with_id( chunk.data, chunk.length, NULL );
+						contact->imgid = purple_imgstore_add_with_id( g_memdup( chunk.data, chunk.length ), chunk.length, NULL );
 						/* show the profile */
 						mxit_show_profile( session, chunk.mxitid, contact->profile );
 					}
 					else {
 						/* this is a contact's avatar, so update it */
-						purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length), chunk.length, chunk.avatarid );
+						purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length ), chunk.length, chunk.avatarid );
 					}
 				}
 			}
@@ -2192,7 +2203,7 @@
 		session->port = atoi( host[2] );
 	}
 	else {
-		purple_connection_error( session->con, _( "Cannot perform redirect using the specified protocol" ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) );
 		goto redirect_fail;
 	}
 
@@ -2270,7 +2281,7 @@
 
 		case CP_CMD_PRESENCE :
 				/* presence update */
-				mxit_parse_cmd_presence(session, &packet->records[2], packet->rcount - 3 );
+				mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 );
 				break;
 
 		case CP_CMD_RX_MSG :
@@ -2361,7 +2372,7 @@
 
 	if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) {
 		/* we are not currently logged in, so we need to reconnect */
-		purple_connection_error( session->con, _( errdesc ) );
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( errdesc ) );
 	}
 
 	/* packet command */
@@ -2375,12 +2386,12 @@
 				}
 				else {
 					snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
-					purple_connection_error( session->con, errmsg );
+					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg );
 					return -1;
 				}
 		case CP_CMD_LOGOUT :
 				snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
-				purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
 				return -1;
 		case CP_CMD_CONTACT :
 				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
@@ -2643,7 +2654,7 @@
 
 		if ( packet.rcount < 2 ) {
 			/* bad packet */
-			purple_connection_error( session->con, _( "Invalid packet received from MXit." ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) );
 			free_rx_packet( &packet );
 			continue;
 		}
@@ -2708,12 +2719,12 @@
 		len = read( session->fd, &ch, 1 );
 		if ( len < 0 ) {
 			/* connection error */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
 			return;
 		}
 		else if ( len == 0 ) {
 			/* connection closed */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
 			return;
 		}
 		else {
@@ -2723,7 +2734,7 @@
 				session->rx_lbuf[session->rx_i] = '\0';
 				session->rx_res = atoi( &session->rx_lbuf[3] );
 				if ( session->rx_res > CP_MAX_PACKET ) {
-					purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
+					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
 				}
 				session->rx_state = RX_STATE_DATA;
 				session->rx_i = 0;
@@ -2734,7 +2745,7 @@
 				session->rx_i++;
 				if ( session->rx_i >= sizeof( session->rx_lbuf ) ) {
 					/* malformed packet length record (too long) */
-					purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
+					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
 					return;
 				}
 			}
@@ -2745,12 +2756,12 @@
 		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
 		if ( len < 0 ) {
 			/* connection error */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
 			return;
 		}
 		else if ( len == 0 ) {
 			/* connection closed */
-			purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
 			return;
 		}
 		else {
@@ -2808,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.h	Mon Oct 31 01:25:36 2011 +0000
@@ -155,7 +155,10 @@
 /* message flags */
 #define		CP_MSG_NOTIFY_DELIVERY	0x0002					/* request delivery notification */
 #define		CP_MSG_NOTIFY_READ		0x0004					/* request read notification */
-#define		CP_MSG_ENCRYPTED		0x0010					/* message is encrypted */
+#define		CP_MSG_PWD_ENCRYPTED	0x0010					/* message is password encrypted */
+#define		CP_MSG_TL_ENCRYPTED		0x0020					/* message is transport encrypted */
+#define		CP_MSG_RPLY_PWD_ENCRYPT	0x0040					/* reply should be password encrypted */
+#define		CP_MSG_RPLY_TL_ENCRYPT	0x0080					/* reply should be transport encrypted */
 #define		CP_MSG_MARKUP			0x0200					/* message may contain markup */
 #define		CP_MSG_EMOTICON			0x0400					/* message may contain custom emoticons */
 
@@ -179,7 +182,7 @@
 /* extended profile attribute fields */
 #define		CP_PROFILE_BIRTHDATE	"birthdate"				/* Birthdate (String - ISO 8601 format) */
 #define		CP_PROFILE_GENDER		"gender"				/* Gender (Boolean - 0=female, 1=male) */
-#define		CP_PROFILE_HIDENUMBER	"hidenumber"			/* Hide Number (Boolean - 0=false, 1=true) */
+// #define		CP_PROFILE_HIDENUMBER	"hidenumber"			/* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */
 #define		CP_PROFILE_FULLNAME		"fullname"				/* Fullname (UTF8 String) */
 #define		CP_PROFILE_STATUS		"statusmsg"				/* Status Message (UTF8 String) */
 #define		CP_PROFILE_PREVSTATUS	"prevstatusmsgs"		/* Previous Status Messages (UTF8 String) */
--- a/libpurple/protocols/mxit/roster.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/roster.c	Mon Oct 31 01:25:36 2011 +0000
@@ -82,9 +82,9 @@
 	}
 
 	/* add Mood option */
-	type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE,
+	type = purple_status_type_new_with_attrs( PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE,
 		PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new( PURPLE_TYPE_STRING ),
-		NULL);
+		NULL );
 	statuslist = g_list_append( statuslist, type );
 
 	return statuslist;
@@ -135,21 +135,21 @@
 
 /* moods (reference: libpurple/status.h) */
 static PurpleMood mxit_moods[] = {
-	{"angry",		N_("Angry"),		NULL},
-	{"excited",		N_("Excited"),		NULL},
-	{"grumpy",		N_("Grumpy"),		NULL},
-	{"happy",		N_("Happy"),		NULL},
-	{"in_love",		N_("In love"),		NULL},
-	{"invincible",	N_("Invincible"),	NULL},
-	{"sad",			N_("Sad"),			NULL},
-	{"hot",			N_("Hot"),			NULL},
-	{"sick",		N_("Sick"),			NULL},
-	{"sleepy",		N_("Sleepy"),		NULL},
-	{"bored",		N_("Bored"),		NULL},
-	{"cold",		N_("Cold"),			NULL},
-	{"confused",	N_("Confused"),		NULL},
-	{"hungry",		N_("Hungry"),		NULL},
-	{"stressed",	N_("Stressed"),		NULL},
+	{ "angry",		N_( "Angry" ),		NULL },
+	{ "excited",	N_( "Excited" ),	NULL },
+	{ "grumpy",		N_( "Grumpy" ),		NULL },
+	{ "happy",		N_( "Happy" ),		NULL },
+	{ "in_love",	N_( "In love" ),	NULL },
+	{ "invincible",	N_( "Invincible" ),	NULL },
+	{ "sad",		N_( "Sad" ),		NULL },
+	{ "hot",		N_( "Hot" ),		NULL },
+	{ "sick",		N_( "Sick" ),		NULL },
+	{ "sleepy",		N_( "Sleepy" ),		NULL },
+	{ "bored",		N_( "Bored" ),		NULL },
+	{ "cold",		N_( "Cold" ),		NULL },
+	{ "confused",	N_( "Confused" ),	NULL },
+	{ "hungry",		N_( "Hungry" ),		NULL },
+	{ "stressed",	N_( "Stressed" ),	NULL },
 	/* Mark the last record. */
 	{ NULL, NULL, NULL }
 };
@@ -293,14 +293,15 @@
  */
 static PurpleBuddy* mxit_update_buddy_group( struct MXitSession* session, PurpleBuddy* buddy, PurpleGroup* group )
 {
-	struct contact*		contact			= NULL;
 	PurpleGroup*		current_group	= purple_buddy_get_group( buddy );
-	PurpleBuddy*		newbuddy		= NULL;
 
 	/* make sure the groups actually differs */
 	if ( strcmp( current_group->name, group->name ) != 0 ) {
 		/* groupnames does not match, so we need to make the update */
 
+		struct contact*		contact		= purple_buddy_get_protocol_data( buddy );
+		PurpleBuddy*		newbuddy	= NULL;
+
 		purple_debug_info( MXIT_PLUGIN_ID, "Moving '%s' from group '%s' to '%s'\n", buddy->alias, current_group->name, group->name );
 
 		/*
@@ -310,10 +311,10 @@
 		 * again. This is really not ideal and very irritating, but how else then?
 		 */
 
-		/* create new buddy */
+		/* create new buddy, and transfer 'contact' data */
 		newbuddy = purple_buddy_new( session->acc, buddy->name, buddy->alias );
-		newbuddy->proto_data = buddy->proto_data;
-		buddy->proto_data = NULL;
+		purple_buddy_set_protocol_data( newbuddy, contact );
+		purple_buddy_set_protocol_data( buddy, NULL );
 
 		/* remove the buddy */
 		purple_blist_remove_buddy( buddy );
@@ -322,7 +323,6 @@
 		purple_blist_add_buddy( newbuddy, NULL, group, NULL );
 
 		/* now re-instate his presence again */
-		contact = newbuddy->proto_data;
 		if ( contact ) {
 
 			/* update the buddy's status (reference: "libpurple/prpl.h") */
@@ -396,7 +396,7 @@
 
 		/* create new buddy */
 		buddy = purple_buddy_new( session->acc, contact->username, contact->alias );
-		purple_buddy_set_protocol_data(buddy, contact);
+		purple_buddy_set_protocol_data( buddy, contact );
 
 		/* add new buddy to list */
 		purple_blist_add_buddy( buddy, NULL, group, NULL );
@@ -728,7 +728,7 @@
  */
 void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 	GSList*				list	= NULL;
 	PurpleBuddy*		mxbuddy	= NULL;
 	unsigned int		i;
@@ -804,7 +804,7 @@
  */
 void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 	const gchar *		buddy_name = purple_buddy_get_name( buddy );
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_remove_buddy '%s'\n", buddy_name );
@@ -822,7 +822,7 @@
  */
 void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 	PurpleBuddy*		buddy	= NULL;
 	PurpleGroup*		group	= NULL;
 
@@ -856,7 +856,7 @@
  */
 void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 	PurpleBuddy*		buddy	= NULL;
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group );
@@ -883,7 +883,7 @@
  */
 void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies )
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data( gc );
 	PurpleBuddy*		buddy	= NULL;
 	GList*				item	= NULL;
 
--- a/libpurple/protocols/mxit/roster.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/roster.h	Mon Oct 31 01:25:36 2011 +0000
@@ -74,7 +74,7 @@
 
 
 /* MXit contact flags */
-#define		MXIT_CFLAG_HIDDEN			0x02
+//#define		MXIT_CFLAG_HIDDEN			0x02		/* (DEPRECATED) */
 #define		MXIT_CFLAG_GATEWAY			0x04
 #define		MXIT_CFLAG_FOCUS_SEND_BLANK	0x20000
 
@@ -96,7 +96,7 @@
 /* client protocol constants */
 #define		MXIT_CP_MAX_JID_LEN			64
 #define		MXIT_CP_MAX_GROUP_LEN		32
-#define		MXIT_CP_MAX_ALIAS_LEN		48
+#define		MXIT_CP_MAX_ALIAS_LEN		100
 
 #define		MXIT_DEFAULT_GROUP			"MXit"
 
@@ -106,8 +106,8 @@
  */
 struct contact {
 	char		username[MXIT_CP_MAX_JID_LEN+1];	/* unique contact name (with domain) */
-	char		alias[MXIT_CP_MAX_GROUP_LEN+1];		/* contact alias (what will be seen) */
-	char		groupname[MXIT_CP_MAX_ALIAS_LEN+1];	/* contact group name */
+	char		alias[MXIT_CP_MAX_ALIAS_LEN+1];		/* contact alias (what will be seen) */
+	char		groupname[MXIT_CP_MAX_GROUP_LEN+1];	/* contact group name */
 
 	short		type;								/* contact type */
 	short		mood;								/* contact current mood */
--- a/libpurple/protocols/mxit/splashscreen.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/splashscreen.c	Mon Oct 31 01:25:36 2011 +0000
@@ -144,7 +144,7 @@
  */
 static void splash_click_ok(PurpleConnection* gc, PurpleRequestFields* fields)
 {
-	struct MXitSession*	session	= (struct MXitSession*) gc->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data(gc);
 	const char* splashId;
 
 	/* Get current splash ID */
--- a/libpurple/protocols/mxit/voicevideo.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/mxit/voicevideo.c	Mon Oct 31 01:25:36 2011 +0000
@@ -63,7 +63,7 @@
  */
 PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who)
 {
-	struct MXitSession*	session	= purple_account_get_connection(account)->proto_data;
+	struct MXitSession*	session	= purple_connection_get_protocol_data(purple_account_get_connection(account));
 	PurpleBuddy*		buddy;
 	struct contact*		contact;
 	PurpleMediaCaps		capa	= PURPLE_MEDIA_CAPS_NONE;
@@ -71,7 +71,7 @@
 	purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_caps: buddy '%s'\n", who);
 
 	/* We need to have a voice/video server */
-	if (strlen(session->voip_server) == 0)
+	if (!*session->voip_server)
 		return PURPLE_MEDIA_CAPS_NONE;
 
 	/* find the buddy information for this contact (reference: "libpurple/blist.h") */
@@ -95,7 +95,7 @@
 
 	/* and only when they're online */
 	if (contact->presence == MXIT_PRESENCE_OFFLINE)
-		return MXIT_PRESENCE_OFFLINE;
+		return PURPLE_MEDIA_CAPS_NONE;
 
 	/* they support voice-only */
 	if (contact->capabilities & MXIT_PFLAG_VOICE)
--- a/libpurple/protocols/myspace/myspace.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Mon Oct 31 01:25:36 2011 +0000
@@ -254,7 +254,7 @@
 	g_return_val_if_fail(who != NULL, FALSE);
 	g_return_val_if_fail(text != NULL, FALSE);
 
-	from_username = session->account->username;
+	from_username = purple_account_get_username(session->account);
 
 	g_return_val_if_fail(from_username != NULL, FALSE);
 
@@ -429,11 +429,9 @@
 	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-		MsimSession *session;
 		PurpleAccount *account = purple_buddy_get_account(buddy);
 		PurpleConnection *gc = purple_account_get_connection(account);
-
-		session = (MsimSession *)gc->proto_data;
+		MsimSession *session = purple_connection_get_protocol_data(gc);
 
 		/* TODO: if (full), do something different? */
 
@@ -698,7 +696,7 @@
 	if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) {
 		purple_debug_info("msim", "bad nc length: %" G_GSIZE_MODIFIER
 				"x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH);
-		purple_connection_error_reason (session->gc,
+		purple_connection_error (session->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unexpected challenge length from server"));
 		return FALSE;
@@ -707,14 +705,14 @@
 	purple_connection_update_progress(session->gc, _("Logging in"), 2, 4);
 
 	response_len = 0;
-	response = msim_compute_login_response(nc, account->username, account->password, &response_len);
+	response = msim_compute_login_response(nc, purple_account_get_username(account), purple_account_get_password(account), &response_len);
 
 	g_free(nc);
 
 	ret = msim_send(session,
 			"login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM,
 			/* This is actually user's email address. */
-			"username", MSIM_TYPE_STRING, g_strdup(account->username),
+			"username", MSIM_TYPE_STRING, g_strdup(purple_account_get_username(account)),
 			/* GString will be freed in msim_msg_free() in msim_send(). */
 			"response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len),
 			"clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION,
@@ -754,8 +752,8 @@
 	 */
 
 	purple_debug_info("msim", "Unrecognized data on account for %s\n",
-			(session && session->account && session->account->username) ?
-			session->account->username : "(NULL)");
+			(session && session->account && purple_account_get_username(session->account)) ?
+			purple_account_get_username(session->account) : "(NULL)");
 	if (note) {
 		purple_debug_info("msim", "(Note: %s)\n", note);
 	}
@@ -835,7 +833,7 @@
 		purple_debug_info("msim",
 				"msim_check_alive: %zu > interval of %d, presumed dead\n",
 				delta, MSIM_KEEPALIVE_INTERVAL);
-		purple_connection_error_reason(session->gc,
+		purple_connection_error(session->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Lost connection with server"));
 
@@ -1840,7 +1838,7 @@
 				if (!purple_account_get_remember_password(session->account))
 					purple_account_set_password(session->account, NULL);
 #ifdef MSIM_MAX_PASSWORD_LENGTH
-				if (session->account->password && (strlen(session->account->password) > MSIM_MAX_PASSWORD_LENGTH)) {
+				if (purple_account_get_password(session->account) && (strlen(purple_account_get_password(session->account)) > MSIM_MAX_PASSWORD_LENGTH)) {
 					gchar *suggestion;
 
 					suggestion = g_strdup_printf(_("%s Your password is "
@@ -1848,7 +1846,7 @@
 							"maximum length of %d.  Please shorten your "
 							"password at http://profileedit.myspace.com/index.cfm?fuseaction=accountSettings.changePassword and try again."),
 							full_errmsg,
-							strlen(session->account->password),
+							strlen(purple_account_get_password(session->account)),
 							MSIM_MAX_PASSWORD_LENGTH);
 
 					/* Replace full_errmsg. */
@@ -1866,7 +1864,7 @@
 					purple_account_set_password(session->account, NULL);
 				break;
 		}
-		purple_connection_error_reason(session->gc, reason, full_errmsg);
+		purple_connection_error(session->gc, reason, full_errmsg);
 	} else {
 		purple_notify_error(session->account, _("MySpaceIM Error"), full_errmsg, NULL);
 	}
@@ -2022,12 +2020,12 @@
 	g_return_if_fail(source >= 0);  /* Note: 0 is a valid fd */
 
 	gc = (PurpleConnection *)(gc_uncasted);
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	/* libpurple/eventloop.h only defines these two */
 	if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) {
 		purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond);
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Invalid input condition"));
 		return;
@@ -2069,12 +2067,12 @@
 
 		tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	} else if (n == 0) {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Server closed the connection"));
 		return;
@@ -2092,7 +2090,7 @@
 		purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes"
 				"--null byte encountered?\n",
 				strlen(session->rxbuf + session->rxoff), n);
-		/*purple_connection_error_reason (gc,
+		/*purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				"Invalid message - null byte on input"); */
 		return;
@@ -2117,7 +2115,7 @@
 		msg = msim_parse(session->rxbuf);
 		if (!msg) {
 			purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n");
-			purple_connection_error_reason (gc,
+			purple_connection_error (gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to parse message"));
 			break;
@@ -2157,20 +2155,19 @@
 	g_return_if_fail(data != NULL);
 
 	gc = (PurpleConnection *)data;
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
 		gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
 				error_message);
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 			g_free(tmp);
 		return;
 	}
 
 	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);
 }
 
 /**
@@ -2186,13 +2183,13 @@
 	int port;
 
 	g_return_if_fail(acct != NULL);
-	g_return_if_fail(acct->username != NULL);
-
-	purple_debug_info("msim", "logging in %s\n", acct->username);
+	g_return_if_fail(purple_account_get_username(acct) != NULL);
+
+	purple_debug_info("msim", "logging in %s\n", purple_account_get_username(acct));
 
 	gc = purple_account_get_connection(acct);
-	gc->proto_data = msim_session_new(acct);
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC;
+	purple_connection_set_protocol_data(gc, msim_session_new(acct));
+	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
@@ -2219,7 +2216,7 @@
 	if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) {
 		/* TODO: try other ports if in auto mode, then save
 		 * working port and try that first next time. */
-		purple_connection_error_reason (gc,
+		purple_connection_error (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to connect"));
 		return;
@@ -2259,14 +2256,15 @@
 		buddies = g_slist_delete_link(buddies, buddies);
 	}
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	if (session == NULL)
 		return;
 
-	gc->proto_data = NULL;
-
-	if (session->gc->inpa) {
-		purple_input_remove(session->gc->inpa);
+	purple_connection_set_protocol_data(gc, NULL);
+
+	if (session->inpa) {
+		purple_input_remove(session->inpa);
+		session->inpa = 0;
 	}
 	if (session->fd >= 0) {
 		close(session->fd);
@@ -2304,7 +2302,7 @@
 
 	/* 'flags' has many options, not used here. */
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	message_msim = html_to_msim_markup(session, message);
 
@@ -2344,7 +2342,7 @@
 	g_return_val_if_fail(gc != NULL, 0);
 	g_return_val_if_fail(name != NULL, 0);
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	switch (state) {
 		case PURPLE_TYPING:
@@ -2430,7 +2428,7 @@
 	g_return_if_fail(gc != NULL);
 	g_return_if_fail(username != NULL);
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	/* Obtain uid of buddy. */
 	user = msim_find_user(session, username);
@@ -2487,6 +2485,7 @@
 static void
 msim_set_status(PurpleAccount *account, PurpleStatus *status)
 {
+	PurpleConnection *gc = purple_account_get_connection(account);
 	PurpleStatusType *type;
 	PurplePresence *pres;
 	MsimSession *session;
@@ -2495,7 +2494,7 @@
 	gchar *stripped;
 	gchar *unrecognized_msg;
 
-	session = (MsimSession *)account->gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	type = purple_status_get_type(status);
 	pres = purple_status_get_presence(status);
@@ -2544,7 +2543,7 @@
 
 	/* If we should be idle, set that status. Time is irrelevant here. */
 	if (purple_presence_is_idle(pres) && status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN)
-		msim_set_idle(account->gc, 1);
+		msim_set_idle(purple_account_get_connection(account), 1);
 }
 
 /**
@@ -2558,7 +2557,7 @@
 
 	g_return_if_fail(gc != NULL);
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	status = purple_account_get_active_status(session->account);
 
@@ -2628,7 +2627,7 @@
  * Add a buddy to user's buddy list.
  */
 static void
-msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
 {
 	MsimSession *session;
 	MsimMessage *msg;
@@ -2636,7 +2635,7 @@
 	MsimMessage *body;
 	const char *name, *gname;
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	name = purple_buddy_get_name(buddy);
 	gname = group ? purple_group_get_name(group) : NULL;
 
@@ -2709,7 +2708,7 @@
 	MsimMessage *persist_msg;
 	const char *name;
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	name = purple_buddy_get_name(buddy);
 
 	delbuddy_msg = msim_msg_new(
@@ -2766,7 +2765,7 @@
 	MsimSession *session;
 	MsimMessage *msg, *body;
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	/* Remove from buddy list */
 	msg = msim_msg_new(
@@ -2818,7 +2817,7 @@
 	MsimSession *session;
 	MsimMessage *msg, *body;
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	/*
 	 * Remove from our list of blocked contacts, so we know they
@@ -2865,7 +2864,7 @@
 		const char *username;
 
 		/* If the account does not exist, we can't look up the user. */
-		if (!account || !account->gc)
+		if (!account || !purple_account_get_connection(account))
 			return str;
 
 		id = atol(str);
@@ -2948,7 +2947,7 @@
 	g_return_val_if_fail(buf != NULL, -1);
 	g_return_val_if_fail(total_bytes >= 0, -1);
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	/* Loop until all data is sent, or a failure occurs. */
 	total_bytes_sent = 0;
@@ -3008,6 +3007,7 @@
  * Callbacks called by Purple, to access this plugin.
  */
 static PurplePluginProtocolInfo prpl_info = {
+	sizeof(PurplePluginProtocolInfo), /* struct_size */
 	/* options */
 	  OPT_PROTO_USE_POINTSIZE        /* specify font size in sane point size */
 	| OPT_PROTO_MAIL_CHECK,
@@ -3052,7 +3052,6 @@
 	NULL,              /* keepalive */
 	NULL,              /* register_user */
 	NULL,              /* get_cb_info */
-	NULL,              /* get_cb_away */
 	NULL,              /* alias_buddy */
 	NULL,              /* group_buddy */
 	NULL,              /* rename_group */
@@ -3077,15 +3076,12 @@
 	NULL,                  /* unregister_user */
 	msim_send_attention,   /* send_attention */
 	msim_attention_types,  /* attention_types */
-	sizeof(PurplePluginProtocolInfo), /* struct_size */
 	msim_get_account_text_table,              /* get_account_text_table */
 	NULL,                   /* initiate_media */
 	NULL,                   /* get_media_caps */
 	NULL,                   /* get_moods */
 	NULL,                   /* set_public_alias */
-	NULL,                   /* get_public_alias */
-	NULL,                   /* add_buddy_with_invite */
-	NULL                    /* add_buddies_with_invite */
+	NULL                    /* get_public_alias */
 };
 
 /**
@@ -3151,7 +3147,7 @@
 	gchar *group_name;
 
 	gc = (PurpleConnection *)action->context;
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	group_name = "MySpace Friends";
 
@@ -3530,6 +3526,7 @@
 msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params)
 {
 	PurpleAccount *account;
+	PurpleConnection *gc;
 	MsimSession *session;
 	GList *l;
 	gchar *uid_str, *cid_str;
@@ -3578,7 +3575,8 @@
 		return FALSE;
 	}
 
-	session = (MsimSession *)account->gc->proto_data;
+	gc = purple_account_get_connection(account);
+	session = purple_connection_get_protocol_data(gc);
 	g_return_val_if_fail(session != NULL, FALSE);
 
 	/* Lookup userid to username. TODO: push this down, to IM sending/contact
--- a/libpurple/protocols/myspace/session.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/myspace/session.h	Mon Oct 31 01:25:36 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/user.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/myspace/user.c	Mon Oct 31 01:25:36 2011 +0000
@@ -117,27 +117,33 @@
 	/* Useful to identify the account the tooltip refers to.
 	 *  Other prpls show this. */
 	if (user->username) {
-		purple_notify_user_info_add_pair(user_info, _("User"), user->username);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("User"), user->username);
 	}
 
 	/* a/s/l...the vitals */
 	if (user->age) {
 		char age[16];
 		g_snprintf(age, sizeof(age), "%d", user->age);
-		purple_notify_user_info_add_pair(user_info, _("Age"), age);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Age"), age);
 	}
 
 	if (user->gender && *user->gender) {
-		purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Gender"), user->gender);
 	}
 
 	if (user->location && *user->location) {
-		purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Location"), user->location);
 	}
 
 	/* Other information */
 	if (user->headline && *user->headline) {
-		purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Headline"), user->headline);
 	}
 
 	if (user->buddy != NULL) {
@@ -153,7 +159,9 @@
 
 			str = msim_format_now_playing(artist, title);
 			if (str && *str) {
-				purple_notify_user_info_add_pair(user_info, _("Song"), str);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Song"), str);
 			}
 			g_free(str);
 		}
@@ -163,7 +171,7 @@
 	if (user->total_friends) {
 		char friends[16];
 		g_snprintf(friends, sizeof(friends), "%d", user->total_friends);
-		purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Total Friends"), friends);
 	}
 
 	if (full) {
@@ -180,8 +188,11 @@
 		} else if (cv) {
 			client = g_strdup_printf("Build %d", cv);
 		}
-		if (client && *client)
-			purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
+		if (client && *client) {
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Client Version"), client);
+		}
 		g_free(client);
 	}
 
@@ -195,7 +206,7 @@
 		else
 			profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
 					user->id, _("View web profile"));
-		purple_notify_user_info_add_pair(user_info, NULL, profile);
+		purple_notify_user_info_add_pair_html(user_info, NULL, profile);
 		g_free(profile);
 	}
 }
@@ -373,7 +384,7 @@
 		if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
 			if (user->url_data != NULL)
 				purple_util_fetch_url_cancel(user->url_data);
-			user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
+			user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, -1, msim_downloaded_buddy_icon, (gpointer)user);
 		}
 	} else if (g_str_equal(key_str, "LastImageUpdated")) {
 		/* TODO: use somewhere */
@@ -401,7 +412,7 @@
  *
  * @param session
  * @param msg The user information reply, with any amount of information.
- * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
+ * @param user The structure to save to, or NULL to save in PurpleBuddy's protocol_data.
  *
  * Variable information is saved to the passed MsimUser structure. Permanent
  * information (UserID) is stored in the blist node of the buddy list (and
@@ -636,7 +647,7 @@
 	if (!body) {
 		purple_debug_info("msim_username_is_set_cb", "No body");
 		/* Error: No body! */
-		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+		purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
 	}
 	username = msim_msg_get_string(body, "UserName");
 	code = msim_msg_get_integer(body,"Code");
@@ -678,13 +689,13 @@
 					NULL)) {
 			/* Error! */
 			/* Can't set... Disconnect */
-			purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+			purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
 		}
 
 	} else {
 		/* Error! */
 		purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
-		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+		purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
 	}
 }
 
@@ -747,7 +758,7 @@
 
 	g_return_if_fail(gc != NULL);
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	user_msg = msim_msg_new(
 			"user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
@@ -782,7 +793,7 @@
 
 	if (!body) {
 		purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
-		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				_("An error occurred while trying to set the username.  "
 				"Please try again, or visit http://editprofile.myspace.com/index.cfm?"
 				"fuseaction=profile.username to set your username."));
@@ -840,7 +851,7 @@
 
 	g_return_if_fail(gc != NULL);
 
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
 
@@ -867,7 +878,7 @@
 	purple_debug_info("msim", "Don't set username");
 
 	/* Protocol won't log in now without a username set.. Disconnect */
-	purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
+	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
 }
 
 /**
--- a/libpurple/protocols/myspace/zap.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/myspace/zap.c	Mon Oct 31 01:25:36 2011 +0000
@@ -132,10 +132,10 @@
 	PurpleAttentionType *attn;
 	PurpleBuddy *buddy;
 
-	session = (MsimSession *)gc->proto_data;
+	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) {
@@ -175,7 +175,7 @@
 	/* Find the session */
 	account = purple_buddy_get_account(buddy);
 	gc = purple_account_get_connection(account);
-	session = (MsimSession *)gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	zap = GPOINTER_TO_INT(zap_num_ptr);
 
--- a/libpurple/protocols/novell/novell.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/novell/novell.c	Mon Oct 31 01:25:36 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:
@@ -140,7 +140,7 @@
 				reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
 		}
 
-		purple_connection_error_reason(gc, reason, err);
+		purple_connection_error(gc, reason, err);
 		g_free(err);
 	}
 }
@@ -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 {
@@ -1126,7 +1126,7 @@
 
 	if (_is_disconnect_error(err)) {
 
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Error communicating with server. Closing connection."));
 		return TRUE;
@@ -1404,15 +1404,15 @@
 	/* Set the Purple privacy setting */
 	if (user->default_deny) {
 		if (user->allow_list == NULL) {
-			gc->account->perm_deny = PURPLE_PRIVACY_DENY_ALL;
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_ALL);
 		} else {
-			gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_USERS);
 		}
 	} else {
 		if (user->deny_list == NULL) {
-			gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL;
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_ALL);
 		} else {
-			gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+			purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_USERS);
 		}
 	}
 
@@ -1424,9 +1424,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 +1437,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 +1456,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 +1473,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);
 	}
@@ -1515,20 +1515,27 @@
 	tag = _("User ID");
 	value = nm_user_record_get_userid(user_record);
 	if (value) {
-		purple_notify_user_info_add_pair(user_info, tag, value);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, tag, value);
 	}
 
-/*	tag = _("DN");
+#if 0
+	tag = _("DN");
 	value = nm_user_record_get_dn(user_record);
 	if (value) {
-		purple_notify_user_info_add_pair(user_info, tag, value);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, tag, value);
 	}
-*/
+#endif /* if 0 */
 
 	tag = _("Full name");
 	value = nm_user_record_get_full_name(user_record);
 	if (value) {
-		purple_notify_user_info_add_pair(user_info, tag, value);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, tag, value);
 	}
 
 	count = nm_user_record_get_property_count(user_record);
@@ -1538,7 +1545,9 @@
 			tag = _map_property_tag(nm_property_get_tag(property));
 			value = nm_property_get_value(property);
 			if (tag && value) {
-				purple_notify_user_info_add_pair(user_info, tag, value);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, tag, value);
 			}
 			nm_release_property(property);
 		}
@@ -1620,7 +1629,7 @@
 	buddy = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -1676,7 +1685,7 @@
 	NMUser *user;
 
 	gc = data;
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	user->conn->ssl_conn->data = NULL;
 
 	purple_connection_ssl_error (gc, error);
@@ -1693,7 +1702,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -1702,7 +1711,7 @@
 
 		if (_is_disconnect_error(rc)) {
 
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Error communicating with server. Closing connection."));
 		} else {
@@ -1727,7 +1736,7 @@
 	if (gc == NULL || gsc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if ((user == NULL) || (conn = user->conn) == NULL)
 		return;
 
@@ -1743,7 +1752,7 @@
 		conn->connected = TRUE;
 		purple_ssl_input_add(gsc, novell_ssl_recv_cb, gc);
 	} else {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to connect"));
 	}
@@ -2028,7 +2037,7 @@
 	{
 		if (!purple_account_get_remember_password(account))
 			purple_account_set_password(account, NULL);
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NAME_IN_USE,
 			_("You have signed on from another location"));
 	}
@@ -2184,7 +2193,7 @@
 		 */
 
 		/* ...but for now just error out with a nice message. */
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("Unable to connect to server. Please enter the "
 			  "address of the server to which you wish to connect."));
@@ -2197,7 +2206,7 @@
 	user = nm_initialize_user(name, server, port, account, _event_callback);
 	if (user && user->conn) {
 		/* save user */
-		gc->proto_data = user;
+		purple_connection_set_protocol_data(gc, user);
 
 		/* connect to the server */
 		purple_connection_update_progress(gc, _("Connecting"),
@@ -2213,7 +2222,7 @@
 													  user->conn->addr, user->conn->port,
 													  novell_ssl_connected_cb, novell_ssl_connect_error, gc);
 		if (user->conn->ssl_conn->data == NULL) {
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("SSL support unavailable"));
 		}
@@ -2229,7 +2238,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user) {
 		conn = user->conn;
 		if (conn && conn->ssl_conn) {
@@ -2237,7 +2246,7 @@
 		}
 		nm_deinitialize_user(user);
 	}
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 }
 
 static int
@@ -2257,7 +2266,7 @@
 		message_body == NULL || *message_body == '\0')
 		return 0;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return 0;
 
@@ -2343,7 +2352,7 @@
 	if (gc == NULL || name == NULL)
 		return 0;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return 0;
 
@@ -2377,7 +2386,7 @@
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user && (dn = nm_lookup_dn(user, who))) {
 		conf = nm_find_conversation(user, dn);
 		if (conf) {
@@ -2399,7 +2408,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2431,7 +2440,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2470,7 +2479,7 @@
 	if (gc == NULL || text == NULL)
 		return -1;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return -1;
 
@@ -2536,7 +2545,7 @@
 }
 
 static void
-novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group)
+novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group, const char *message)
 {
 	NMFolder *folder = NULL;
 	NMContact *contact;
@@ -2610,7 +2619,7 @@
 	if (gc == NULL || buddy == NULL || group == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user && (dn = nm_lookup_dn(user, purple_buddy_get_name(buddy)))) {
 		gname = purple_group_get_name(group);
 		if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0) {
@@ -2642,7 +2651,7 @@
 	if (gc == NULL || group == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user) {
 		NMFolder *folder = nm_find_folder(user, purple_group_get_name(group));
 
@@ -2667,7 +2676,7 @@
 	if (gc == NULL || name == NULL || alias == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user && (dn = nm_lookup_dn(user, name))) {
 
 		/* Alias all of instances of the contact */
@@ -2726,7 +2735,7 @@
 		old_group_name == NULL || new_group_name == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user && (dn = nm_lookup_dn(user, name))) {
 
 		/* Find the old folder */
@@ -2784,7 +2793,7 @@
 		return;
 	}
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user) {
 		const char *gname = purple_group_get_name(group);
 		/* Does new folder exist already? */
@@ -2830,7 +2839,7 @@
 		return;
 
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	if (gc == NULL || (user = gc->proto_data) == NULL)
+	if (gc == NULL || (user = purple_connection_get_protocol_data(gc)) == NULL)
 		return;
 
 	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
@@ -2860,10 +2869,13 @@
 					break;
 			}
 
-			purple_notify_user_info_add_pair(user_info, _("Status"), status_str);
-
-			if (text)
-				purple_notify_user_info_add_pair(user_info, _("Message"), text);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_str);
+
+			if (text) {
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Message"), text);
+			}
 		}
 	}
 }
@@ -2879,7 +2891,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2908,7 +2920,7 @@
 	if (gc == NULL || name == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user) {
 
 		user_record = nm_find_user_record(user, name);
@@ -2937,17 +2949,19 @@
 	if (buddy && account) {
 		PurpleConnection *gc = purple_account_get_connection(account);
 
-		if (gc && gc->proto_data) {
-			NMUser *user = gc->proto_data;
-
-			dn = nm_lookup_dn(user, purple_buddy_get_name(buddy));
-			if (dn) {
-				NMUserRecord *user_record = nm_find_user_record(user, dn);
-
-				if (user_record) {
-					text = nm_user_record_get_status_text(user_record);
-					if (text)
-						return g_strdup(text);
+		if (gc) {
+			NMUser *user = purple_connection_get_protocol_data(gc);
+
+			if (user) {
+				dn = nm_lookup_dn(user, purple_buddy_get_name(buddy));
+				if (dn) {
+					NMUserRecord *user_record = nm_find_user_record(user, dn);
+
+					if (user_record) {
+						text = nm_user_record_get_status_text(user_record);
+						if (text)
+							return g_strdup(text);
+					}
 				}
 			}
 		}
@@ -3023,7 +3037,7 @@
 		return;
 
 	gc = purple_account_get_connection(account);
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3070,14 +3084,14 @@
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
 	/* 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);
@@ -3114,14 +3128,14 @@
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
 	/* 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);
@@ -3158,7 +3172,7 @@
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3188,7 +3202,7 @@
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3223,7 +3237,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3239,7 +3253,7 @@
 		return;
 	}
 
-	switch (gc->account->perm_deny) {
+	switch (purple_account_get_privacy_type(purple_connection_get_account(gc))) {
 
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			rc = nm_send_set_privacy_default(user, FALSE,
@@ -3295,14 +3309,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) {
@@ -3316,7 +3330,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);
 					}
 				}
 			}
@@ -3337,14 +3351,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);
@@ -3359,7 +3373,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);
 					}
 				}
 
@@ -3451,7 +3465,7 @@
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3460,6 +3474,7 @@
 }
 
 static PurplePluginProtocolInfo prpl_info = {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	0,
 	NULL,						/* user_splits */
 	NULL,						/* protocol_options */
@@ -3500,7 +3515,6 @@
 	novell_keepalive,			/* keepalive */
 	NULL,						/* register_user */
 	NULL,						/* get_cb_info */
-	NULL,						/* get_cb_away */
 	novell_alias_buddy,			/* alias_buddy */
 	novell_group_buddy,			/* group_buddy */
 	novell_rename_group,		/* rename_group */
@@ -3525,15 +3539,12 @@
 	NULL,						/* unregister_user */
 	NULL,						/* send_attention */
 	NULL,						/* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,						/* get_account_text_table */
 	NULL,						/* initiate_media */
 	NULL,						/* get_media_caps */
 	NULL,						/* get_moods */
 	NULL,						/* set_public_alias */
-	NULL,						/* get_public_alias */
-	NULL,						/* add_buddy_with_invite */
-	NULL						/* add_buddies_with_invite */
+	NULL						/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/protocols/null/nullprpl.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/null/nullprpl.c	Mon Oct 31 01:25:36 2011 +0000
@@ -113,7 +113,7 @@
   PurpleConnection *gc = (PurpleConnection *)(data);
   GcFuncData *gcfdata = (GcFuncData *)userdata;
 
-  if (!strcmp(gc->account->protocol_id, NULLPRPL_ID))
+  if (!strcmp(purple_account_get_protocol_id(purple_connection_get_account(gc)), NULLPRPL_ID))
     gcfdata->fn(gcfdata->from, gc, gcfdata->userdata);
 }
 
@@ -138,11 +138,11 @@
   PurpleConnection *to = (PurpleConnection *)data;
   ChatFuncData *cfdata = (ChatFuncData *)userdata;
 
-  int id = cfdata->from_chat->id;
+  int id = purple_conv_chat_get_id(cfdata->from_chat);
   PurpleConversation *conv = purple_find_chat(to, id);
   if (conv) {
     PurpleConvChat *chat = purple_conversation_get_chat_data(conv);
-    cfdata->fn(cfdata->from_chat, chat, id, conv->name, cfdata->userdata);
+    cfdata->fn(cfdata->from_chat, chat, id, purple_conversation_get_name(conv), cfdata->userdata);
   }
 }
 
@@ -160,11 +160,11 @@
 
 static void discover_status(PurpleConnection *from, PurpleConnection *to,
                             gpointer userdata) {
-  const char *from_username = from->account->username;
-  const char *to_username = to->account->username;
+  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",
-                    to->account->username, from->account->username);
+                    purple_account_get_username(purple_connection_get_account(to)), purple_account_get_username(purple_connection_get_account(from)));
   discover_status(to, from, NULL);
 }
 
@@ -199,7 +199,7 @@
   PurpleConnection *gc = (PurpleConnection *)action->context;
   PurpleAccount *acct = purple_connection_get_account(gc);
   purple_debug_info("nullprpl", "showing 'Set User Info' dialog for %s\n",
-                    acct->username);
+                    purple_account_get_username(acct));
 
   purple_account_request_change_user_info(acct);
 }
@@ -225,7 +225,7 @@
 
 static char *nullprpl_status_text(PurpleBuddy *buddy) {
   purple_debug_info("nullprpl", "getting %s's status text for %s\n",
-                    buddy->name, buddy->account->username);
+                    buddy->name, purple_account_get_username(buddy->account));
 
   if (purple_find_buddy(buddy->account, buddy->name)) {
     PurplePresence *presence = purple_buddy_get_presence(buddy);
@@ -234,7 +234,7 @@
     const char *message = purple_status_get_attr_string(status, "message");
 
     char *text;
-    if (message && strlen(message) > 0)
+    if (message && *message)
       text = g_strdup_printf("%s: %s", name, message);
     else
       text = g_strdup(name);
@@ -258,19 +258,23 @@
     PurplePresence *presence = purple_buddy_get_presence(buddy);
     PurpleStatus *status = purple_presence_get_active_status(presence);
     char *msg = nullprpl_status_text(buddy);
-    purple_notify_user_info_add_pair(info, purple_status_get_name(status),
+	/* TODO: Check whether it's correct to call add_pair_html,
+	         or if we should be using add_pair_plaintext */
+    purple_notify_user_info_add_pair_html(info, purple_status_get_name(status),
                                      msg);
     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)
-        purple_notify_user_info_add_pair(info, _("User info"), user_info);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+        purple_notify_user_info_add_pair_html(info, _("User info"), user_info);
     }
 
   } else {
     /* they're not logged in */
-    purple_notify_user_info_add_pair(info, _("User info"), _("not logged in"));
+    purple_notify_user_info_add_pair_plaintext(info, _("User info"), _("not logged in"));
   }
 
   purple_debug_info("nullprpl", "showing %s tooltip for %s\n",
@@ -283,7 +287,7 @@
   PurpleStatusType *type;
 
   purple_debug_info("nullprpl", "returning status types for %s: %s, %s, %s\n",
-                    acct->username,
+                    purple_account_get_username(acct),
                     NULL_STATUS_ONLINE, NULL_STATUS_AWAY, NULL_STATUS_OFFLINE);
 
   type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
@@ -362,7 +366,7 @@
   PurpleConnection *gc = purple_account_get_connection(acct);
   GList *offline_messages;
 
-  purple_debug_info("nullprpl", "logging in %s\n", acct->username);
+  purple_debug_info("nullprpl", "logging in %s\n", purple_account_get_username(acct));
 
   purple_connection_update_progress(gc, _("Connecting"),
                                     0,   /* which connection step this is */
@@ -381,12 +385,12 @@
 
   /* fetch stored offline messages */
   purple_debug_info("nullprpl", "checking for offline messages for %s\n",
-                    acct->username);
-  offline_messages = g_hash_table_lookup(goffline_messages, acct->username);
+                    purple_account_get_username(acct));
+  offline_messages = g_hash_table_lookup(goffline_messages, purple_account_get_username(acct));
   while (offline_messages) {
     GOfflineMessage *message = (GOfflineMessage *)offline_messages->data;
     purple_debug_info("nullprpl", "delivering offline message to %s: %s\n",
-                      acct->username, message->message);
+                      purple_account_get_username(acct), message->message);
     serv_got_im(gc, message->from, message->message, message->flags,
                 message->mtime);
     offline_messages = g_list_next(offline_messages);
@@ -397,7 +401,7 @@
   }
 
   g_list_free(offline_messages);
-  g_hash_table_remove(goffline_messages, &acct->username);
+  g_hash_table_remove(goffline_messages, purple_account_get_username(acct));
 }
 
 static void nullprpl_close(PurpleConnection *gc)
@@ -409,7 +413,7 @@
 static int nullprpl_send_im(PurpleConnection *gc, const char *who,
                             const char *message, PurpleMessageFlags flags)
 {
-  const char *from_username = gc->account->username;
+  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);
@@ -419,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, gc->account->username)) {
+  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;
   }
@@ -457,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",
-                    gc->account->username, info);
+                    purple_account_get_username(purple_connection_get_account(gc)), info);
 }
 
 static const char *typing_state_to_string(PurpleTypingState typing) {
@@ -471,10 +475,10 @@
 
 static void notify_typing(PurpleConnection *from, PurpleConnection *to,
                           gpointer typing) {
-  const char *from_username = from->account->username;
+  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",
-                    to->account->username, from_username, action);
+                    purple_account_get_username(purple_connection_get_account(to)), from_username, action);
 
   serv_got_typing(to,
                   from_username,
@@ -485,7 +489,7 @@
 
 static unsigned int nullprpl_send_typing(PurpleConnection *gc, const char *name,
                                          PurpleTypingState typing) {
-  purple_debug_info("nullprpl", "%s %s\n", gc->account->username,
+  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;
@@ -497,7 +501,7 @@
   PurpleAccount *acct;
 
   purple_debug_info("nullprpl", "Fetching %s's user info for %s\n", username,
-                    gc->account->username);
+                    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);
@@ -510,7 +514,9 @@
     body = purple_account_get_user_info(acct);
   else
     body = _("No user info.");
-  purple_notify_user_info_add_pair(info, "Info", body);
+  /* TODO: Check whether it's correct to call add_pair_html,
+           or if we should be using add_pair_plaintext */
+  purple_notify_user_info_add_pair_html(info, "Info", body);
 
   /* show a buddy's user info in a nice dialog box */
   purple_notify_userinfo(gc,        /* connection the buddy info came through */
@@ -523,35 +529,35 @@
 static void nullprpl_set_status(PurpleAccount *acct, PurpleStatus *status) {
   const char *msg = purple_status_get_attr_string(status, "message");
   purple_debug_info("nullprpl", "setting %s's status to %s: %s\n",
-                    acct->username, purple_status_get_name(status), msg);
+                    purple_account_get_username(acct), purple_status_get_name(status), msg);
 
-  foreach_nullprpl_gc(report_status_change, get_nullprpl_gc(acct->username),
+  foreach_nullprpl_gc(report_status_change, get_nullprpl_gc(purple_account_get_username(acct)),
                       NULL);
 }
 
 static void nullprpl_set_idle(PurpleConnection *gc, int idletime) {
   purple_debug_info("nullprpl",
                     "purple reports that %s has been idle for %d seconds\n",
-                    gc->account->username, 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",
-                    gc->account->username);
+                    purple_account_get_username(purple_connection_get_account(gc)));
 }
 
 static void nullprpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
-                               PurpleGroup *group)
+                               PurpleGroup *group, const char *message)
 {
-  const char *username = gc->account->username;
+  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);
 
@@ -565,20 +571,20 @@
                                  username,
                                  NULL,   /* local account id (rarely used) */
                                  NULL,   /* alias */
-                                 NULL);  /* message */
+                                 message);  /* message */
     }
   }
 }
 
 static void nullprpl_add_buddies(PurpleConnection *gc, GList *buddies,
-                                 GList *groups) {
+                                 GList *groups, const char *message) {
   GList *buddy = buddies;
   GList *group = groups;
 
   purple_debug_info("nullprpl", "adding multiple buddies\n");
 
   while (buddy && group) {
-    nullprpl_add_buddy(gc, (PurpleBuddy *)buddy->data, (PurpleGroup *)group->data);
+    nullprpl_add_buddy(gc, (PurpleBuddy *)buddy->data, (PurpleGroup *)group->data, message);
     buddy = g_list_next(buddy);
     group = g_list_next(group);
   }
@@ -588,7 +594,7 @@
                                   PurpleGroup *group)
 {
   purple_debug_info("nullprpl", "removing %s from %s's buddy list\n",
-                    buddy->name, gc->account->username);
+                    buddy->name, purple_account_get_username(purple_connection_get_account(gc)));
 }
 
 static void nullprpl_remove_buddies(PurpleConnection *gc, GList *buddies,
@@ -614,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",
-                    gc->account->username, 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",
-                    gc->account->username, 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",
-                    gc->account->username, 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",
-                    gc->account->username, name);
+                    purple_account_get_username(purple_connection_get_account(gc)), name);
 }
 
 static void nullprpl_set_permit_deny(PurpleConnection *gc) {
@@ -642,9 +648,9 @@
                         int id, const char *room, gpointer userdata) {
   /*  tell their chat window that we joined */
   purple_debug_info("nullprpl", "%s sees that %s joined chat room %s\n",
-                    to->nick, from->nick, room);
+                    purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room);
   purple_conv_chat_add_user(to,
-                            from->nick,
+                            purple_conv_chat_get_nick(from),
                             NULL,   /* user-provided join message, IRC style */
                             PURPLE_CBFLAGS_NONE,
                             TRUE);  /* show a join message */
@@ -652,9 +658,9 @@
   if (from != to) {
     /* add them to our chat window */
     purple_debug_info("nullprpl", "%s sees that %s is in chat room %s\n",
-                      from->nick, to->nick, room);
+                      purple_conv_chat_get_nick(from), purple_conv_chat_get_nick(to), room);
     purple_conv_chat_add_user(from,
-                              to->nick,
+                              purple_conv_chat_get_nick(to),
                               NULL,   /* user-provided join message, IRC style */
                               PURPLE_CBFLAGS_NONE,
                               FALSE);  /* show a join message */
@@ -662,7 +668,7 @@
 }
 
 static void nullprpl_join_chat(PurpleConnection *gc, GHashTable *components) {
-  const char *username = gc->account->username;
+  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);
@@ -686,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 = gc->account->username;
+  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.",
@@ -713,9 +719,9 @@
 
 static void nullprpl_chat_invite(PurpleConnection *gc, int id,
                                  const char *message, const char *who) {
-  const char *username = gc->account->username;
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConversation *conv = purple_find_chat(gc, id);
-  const char *room = conv->name;
+  const char *room = purple_conversation_get_name(conv);
   PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID);
 
   purple_debug_info("nullprpl", "%s is inviting %s to join chat room %s\n",
@@ -746,9 +752,9 @@
   if (from != to) {
     /*  tell their chat window that we left */
     purple_debug_info("nullprpl", "%s sees that %s left chat room %s\n",
-                      to->nick, from->nick, room);
+                      purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room);
     purple_conv_chat_remove_user(to,
-                                 from->nick,
+                                 purple_conv_chat_get_nick(from),
                                  NULL);  /* user-provided message, IRC style */
   }
 }
@@ -756,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",
-                    gc->account->username, conv->name);
+                    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);
@@ -775,17 +781,17 @@
   to_username = args[0];
   message = args[1];
 
-  if (!to_username || strlen(to_username) == 0) {
+  if (!to_username || !*to_username) {
     *error = g_strdup(_("Whisper is missing recipient."));
     return PURPLE_CMD_RET_FAILED;
-  } else if (!message || strlen(message) == 0) {
+  } else if (!message || !*message) {
     *error = g_strdup(_("Whisper is missing message."));
     return PURPLE_CMD_RET_FAILED;
   }
 
-  from_username = conv->account->username;
+  from_username = purple_account_get_username(purple_conversation_get_account(conv));
   purple_debug_info("nullprpl", "%s whispers to %s in chat room %s: %s\n",
-                    from_username, to_username, conv->name, message);
+                    from_username, to_username, purple_conversation_get_name(conv), message);
 
   chat = purple_conversation_get_chat_data(conv);
   chat_buddy = purple_conv_chat_cb_find(chat, to_username);
@@ -807,7 +813,7 @@
     g_free(message_to);
 
     /* send the whisper */
-    serv_chat_whisper(to, chat->id, from_username, message);
+    serv_chat_whisper(to, purple_conv_chat_get_id(chat), from_username, message);
 
     return PURPLE_CMD_RET_OK;
   }
@@ -815,11 +821,11 @@
 
 static void nullprpl_chat_whisper(PurpleConnection *gc, int id, const char *who,
                                   const char *message) {
-  const char *username = gc->account->username;
+  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",
-                    username, who, conv->name, message);
+                    username, who, purple_conversation_get_name(conv), message);
 
   /* receive whisper on recipient's account */
   serv_got_chat_in(gc, id, who, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_WHISPER,
@@ -829,24 +835,24 @@
 static void receive_chat_message(PurpleConvChat *from, PurpleConvChat *to,
                                  int id, const char *room, gpointer userdata) {
   const char *message = (const char *)userdata;
-  PurpleConnection *to_gc = get_nullprpl_gc(to->nick);
+  PurpleConnection *to_gc = get_nullprpl_gc(purple_conv_chat_get_nick(to));
 
   purple_debug_info("nullprpl",
                     "%s receives message from %s in chat room %s: %s\n",
-                    to->nick, from->nick, room, message);
-  serv_got_chat_in(to_gc, id, from->nick, PURPLE_MESSAGE_RECV, message,
+                    purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room, message);
+  serv_got_chat_in(to_gc, id, purple_conv_chat_get_nick(from), PURPLE_MESSAGE_RECV, message,
                    time(NULL));
 }
 
 static int nullprpl_chat_send(PurpleConnection *gc, int id, const char *message,
                               PurpleMessageFlags flags) {
-  const char *username = gc->account->username;
+  const char *username = purple_account_get_username(purple_connection_get_account(gc));
   PurpleConversation *conv = purple_find_chat(gc, id);
 
   if (conv) {
     purple_debug_info("nullprpl",
                       "%s is sending message to chat room %s: %s\n", username,
-                      conv->name, message);
+                      purple_conversation_get_name(conv), message);
 
     /* send message to everyone in the chat room */
     foreach_gc_in_chat(receive_chat_message, gc, id, (gpointer)message);
@@ -862,14 +868,14 @@
 
 static void nullprpl_register_user(PurpleAccount *acct) {
  purple_debug_info("nullprpl", "registering account for %s\n",
-                   acct->username);
+                   purple_account_get_username(acct));
 }
 
 static void nullprpl_get_cb_info(PurpleConnection *gc, int id, const char *who) {
   PurpleConversation *conv = purple_find_chat(gc, id);
   purple_debug_info("nullprpl",
                     "retrieving %s's info for %s in chat room %s\n", who,
-                    gc->account->username, conv->name);
+                    purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv));
 
   nullprpl_get_info(gc, who);
 }
@@ -877,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",
-                   gc->account->username, 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",
-                    gc->account->username, 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",
-                    gc->account->username, 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",
-                    gc->account->username, who);
+                    purple_account_get_username(purple_connection_get_account(gc)), who);
 }
 
 /* normalize a username (e.g. remove whitespace, add default domain, etc.)
@@ -909,25 +915,25 @@
 static void nullprpl_set_buddy_icon(PurpleConnection *gc,
                                     PurpleStoredImage *img) {
  purple_debug_info("nullprpl", "setting %s's buddy icon to %s\n",
-                   gc->account->username,
+                   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",
-                    gc->account->username, group->name);
+                    purple_account_get_username(purple_connection_get_account(gc)), group->name);
 }
 
 
 static void set_chat_topic_fn(PurpleConvChat *from, PurpleConvChat *to,
                               int id, const char *room, gpointer userdata) {
   const char *topic = (const char *)userdata;
-  const char *username = from->conv->account->username;
+  const char *username = purple_account_get_username(purple_conversation_get_account(purple_conv_chat_get_conversation(from)));
   char *msg;
 
   purple_conv_chat_set_topic(to, username, topic);
 
-  if (topic && strlen(topic) > 0)
+  if (topic && *topic)
     msg = g_strdup_printf(_("%s sets topic to: %s"), username, topic);
   else
     msg = g_strdup_printf(_("%s clears topic"), username);
@@ -948,7 +954,7 @@
     return;
 
   purple_debug_info("nullprpl", "%s sets topic of chat room '%s' to '%s'\n",
-                    gc->account->username, conv->name, 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) ||
@@ -964,8 +970,8 @@
 }
 
 static PurpleRoomlist *nullprpl_roomlist_get_list(PurpleConnection *gc) {
-  const char *username = gc->account->username;
-  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;
@@ -988,8 +994,8 @@
   for (chats  = purple_get_chats(); chats; chats = g_list_next(chats)) {
     PurpleConversation *conv = (PurpleConversation *)chats->data;
     PurpleRoomlistRoom *room;
-    const char *name = conv->name;
-    int id = purple_conversation_get_chat_data(conv)->id;
+    const char *name = purple_conversation_get_name(conv);
+    int id = purple_conv_chat_get_id(purple_conversation_get_chat_data(conv));
 
     /* have we already added this room? */
     if (g_list_find_custom(seen_ids, name, (GCompareFunc)strcmp))
@@ -1013,14 +1019,17 @@
 }
 
 static void nullprpl_roomlist_cancel(PurpleRoomlist *list) {
+ PurpleAccount *account = purple_roomlist_get_account(list);
  purple_debug_info("nullprpl", "%s asked to cancel room list request\n",
-                   list->account->username);
+                   purple_account_get_username(account));
 }
 
 static void nullprpl_roomlist_expand_category(PurpleRoomlist *list,
                                               PurpleRoomlistRoom *category) {
+ PurpleAccount *account = purple_roomlist_get_account(list);
  purple_debug_info("nullprpl", "%s asked to expand room list category %s\n",
-                   list->account->username, category->name);
+                   purple_account_get_username(account),
+                   purple_roomlist_room_get_name(category));
 }
 
 /* nullprpl doesn't support file transfer...yet... */
@@ -1043,6 +1052,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+  sizeof(PurplePluginProtocolInfo),    /* struct_size */
   OPT_PROTO_NO_PASSWORD | OPT_PROTO_CHAT_TOPIC,  /* options */
   NULL,               /* user_splits, initialized in nullprpl_init() */
   NULL,               /* protocol_options, initialized in nullprpl_init() */
@@ -1091,7 +1101,6 @@
   NULL,                                /* keepalive */
   nullprpl_register_user,              /* register_user */
   nullprpl_get_cb_info,                /* get_cb_info */
-  NULL,                                /* get_cb_away */
   nullprpl_alias_buddy,                /* alias_buddy */
   nullprpl_group_buddy,                /* group_buddy */
   nullprpl_rename_group,               /* rename_group */
@@ -1116,15 +1125,12 @@
   NULL,                                /* unregister_user */
   NULL,                                /* send_attention */
   NULL,                                /* get_attention_types */
-  sizeof(PurplePluginProtocolInfo),    /* struct_size */
   NULL,                                /* get_account_text_table */
   NULL,                                /* initiate_media */
   NULL,                                /* get_media_caps */
   NULL,                                /* get_moods */
   NULL,                                /* set_public_alias */
-  NULL,                                /* get_public_alias */
-  NULL,                                /* add_buddy_with_invite */
-  NULL                                 /* add_buddies_with_invite */
+  NULL                                 /* get_public_alias */
 };
 
 static void nullprpl_init(PurplePlugin *plugin)
--- a/libpurple/protocols/oscar/authorization.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/authorization.c	Mon Oct 31 01:25:36 2011 +0000
@@ -49,7 +49,7 @@
 		purple_debug_info("oscar", "ssi: adding buddy %s to group %s\n",
 				   bname, gname);
 		aim_ssi_sendauthrequest(od, bname, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
-		if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))
+		if (!aim_ssi_itemlist_finditem(&od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))
 		{
 			aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
 
--- a/libpurple/protocols/oscar/clientlogin.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/clientlogin.c	Mon Oct 31 01:25:36 2011 +0000
@@ -182,7 +182,7 @@
 		/* Note to translators: %s in this string is a URL */
 		msg = generate_error_message(response_node,
 				get_start_oscar_session_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		return FALSE;
@@ -204,7 +204,7 @@
 				"missing statusCode: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_start_oscar_session_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		xmlnode_free(response_node);
@@ -232,7 +232,7 @@
 				"was %s: %s\n", tmp, response);
 
 		if ((code == 401 && status_detail != 1014) || code == 607)
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 					_("You have been connecting and disconnecting too "
 					  "frequently. Wait ten minutes and try again. If "
@@ -242,7 +242,7 @@
 			char *msg;
 			msg = generate_error_message(response_node,
 					get_start_oscar_session_url(od));
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
 			g_free(msg);
 		}
@@ -261,7 +261,7 @@
 				"something: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_start_oscar_session_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		xmlnode_free(response_node);
@@ -277,7 +277,7 @@
 				purple_debug_warning("oscar", "We haven't received a tlsCertName to use. We will not do SSL to BOS.\n");
 			} else {
 				purple_debug_error("oscar", "startOSCARSession was missing tlsCertName: %s\n", response);
-				purple_connection_error_reason(
+				purple_connection_error(
 					gc,
 					PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 					_("You required encryption in your account settings, but one of the servers doesn't support it."));
@@ -299,7 +299,7 @@
 				"something: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_start_oscar_session_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		g_free(*host);
@@ -337,7 +337,7 @@
 		tmp = g_strdup_printf(_("Error requesting %s: %s"),
 				get_start_oscar_session_url(od), error_message ?
 				error_message : _("The server returned an empty response"));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
@@ -384,7 +384,7 @@
 	g_free(signature);
 
 	/* Make the request */
-	od->url_data = purple_util_fetch_url_request_len_with_account(account,
+	od->url_data = purple_util_fetch_url_request(account,
 			url, TRUE, NULL, FALSE, NULL, FALSE, -1,
 			start_oscar_session_cb, od);
 	g_free(url);
@@ -395,7 +395,7 @@
  * and extracts the useful information.
  *
  * @param gc           The PurpleConnection.  If the response data does
- *                     not indicate then purple_connection_error_reason()
+ *                     not indicate then purple_connection_error()
  *                     will be called to close this connection.
  * @param response     The response data from the clientLogin request.
  * @param response_len The length of the above response, or -1 if
@@ -431,7 +431,7 @@
 				"response as XML: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_client_login_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		return FALSE;
@@ -455,7 +455,7 @@
 				"missing statusCode: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_client_login_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		xmlnode_free(response_node);
@@ -482,23 +482,23 @@
 			PurpleAccount *account = purple_connection_get_account(gc);
 			if (!purple_account_get_remember_password(account))
 				purple_account_set_password(account, NULL);
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 					_("Incorrect password"));
 		} else if (status_code == 330 && status_detail_code == 3015) {
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 					_("Server requested that you fill out a CAPTCHA in order to "
 					"sign in, but this client does not currently support CAPTCHAs."));
 		} else if (status_code == 401 && status_detail_code == 3019) {
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 					_("AOL does not allow your screen name to authenticate here"));
 		} else {
 			char *msg;
 			msg = generate_error_message(response_node,
 					get_client_login_url(od));
-			purple_connection_error_reason(gc,
+			purple_connection_error(gc,
 					PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
 			g_free(msg);
 		}
@@ -517,7 +517,7 @@
 				"something: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_client_login_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		xmlnode_free(response_node);
@@ -535,7 +535,7 @@
 				"something: %s\n", response);
 		msg = generate_error_message(response_node,
 				get_client_login_url(od));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 		g_free(*token);
@@ -572,7 +572,7 @@
 		tmp = g_strdup_printf(_("Error requesting %s: %s"),
 				get_client_login_url(od), error_message ?
 				error_message : _("The server returned an empty response"));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
@@ -646,7 +646,7 @@
 	g_string_free(body, TRUE);
 
 	/* Send the POST request  */
-	od->url_data = purple_util_fetch_url_request_len_with_account(
+	od->url_data = purple_util_fetch_url_request(
 			purple_connection_get_account(gc), get_client_login_url(od),
 			TRUE, NULL, FALSE, request->str, FALSE, -1,
 			client_login_cb, od);
--- a/libpurple/protocols/oscar/family_feedbag.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Mon Oct 31 01:25:36 2011 +0000
@@ -21,9 +21,9 @@
 /*
  * Family 0x0013 - Server-Side/Stored Information.
  *
- * Relatively new facility that allows certain types of information, such as
- * a user's buddy list, permit/deny list, and permit/deny preferences, to be
- * stored on the server, so that they can be accessed from any client.
+ * Deals with storing certain types of information, such as a user's buddy
+ * list, permit/deny list, and permit/deny preferences, on the server, so
+ * that they can be accessed from any client.
  *
  * We keep 2 copies of SSI data:
  * 1) An exact copy of what is stored on the AIM servers.
@@ -40,14 +40,41 @@
  *
  * This is entirely too complicated.
  * You don't know the half of it.
- *
  */
 
 #include "oscar.h"
+#include "oscarcommon.h"
 #include "debug.h"
 
 static int aim_ssi_addmoddel(OscarData *od);
 
+static void aim_ssi_item_free(struct aim_ssi_item *item)
+{
+	g_free(item->name);
+	aim_tlvlist_free(item->data);
+	g_free(item);
+}
+
+static void aim_ssi_item_set_name(struct aim_ssi_itemlist *list, struct aim_ssi_item *item, const char *name)
+{
+	gchar key[3000];
+
+	if (item->name) {
+		/* Remove old name from hash table */
+		snprintf(key, sizeof(key), "%hx%s", item->type, oscar_normalize(NULL, item->name));
+		g_hash_table_remove(list->idx_all_named_items, key);
+	}
+
+	g_free(item->name);
+	item->name = g_strdup(name);
+
+	if (name) {
+		/* Add new name to hash table */
+		snprintf(key, sizeof(key), "%hx%s", item->type, oscar_normalize(NULL, item->name));
+		g_hash_table_insert(list->idx_all_named_items, g_strdup(key), item);
+	}
+}
+
 /**
  * List types based on http://dev.aol.com/aim/oscar/#FEEDBAG (archive.org)
  * and http://iserverd.khstu.ru/oscar/ssi_item.html
@@ -113,7 +140,7 @@
  * @return Return a pointer to the modified item.
  */
 static void
-aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
+aim_ssi_itemlist_rebuildgroup(struct aim_ssi_itemlist *list, const char *name)
 {
 	int newlen;
 	struct aim_ssi_item *cur, *group;
@@ -125,11 +152,11 @@
 	/* Find the length for the new additional data */
 	newlen = 0;
 	if (group->gid == 0x0000) {
-		for (cur=list; cur; cur=cur->next)
+		for (cur=list->data; cur; cur=cur->next)
 			if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
 				newlen += 2;
 	} else {
-		for (cur=list; cur; cur=cur->next)
+		for (cur=list->data; cur; cur=cur->next)
 			if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
 				newlen += 2;
 	}
@@ -138,14 +165,14 @@
 	if (newlen > 0) {
 		guint8 *newdata;
 
-		newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8));
+		newdata = g_new(guint8, newlen);
 		newlen = 0;
 		if (group->gid == 0x0000) {
-			for (cur=list; cur; cur=cur->next)
+			for (cur=list->data; cur; cur=cur->next)
 				if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
 						newlen += aimutil_put16(newdata+newlen, cur->gid);
 		} else {
-			for (cur=list; cur; cur=cur->next)
+			for (cur=list->data; cur; cur=cur->next)
 				if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
 						newlen += aimutil_put16(newdata+newlen, cur->bid);
 		}
@@ -167,15 +194,12 @@
  * @param data The additional data for the new item.
  * @return A pointer to the newly created item.
  */
-static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data)
+static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_itemlist *list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data)
 {
 	gboolean exists;
 	struct aim_ssi_item *cur, *new;
 
-	new = g_new(struct aim_ssi_item, 1);
-
-	/* Set the name */
-	new->name = g_strdup(name);
+	new = g_new0(struct aim_ssi_item, 1);
 
 	/* Set the group ID# and buddy ID# */
 	new->gid = gid;
@@ -185,7 +209,7 @@
 			do {
 				new->gid += 0x0001;
 				exists = FALSE;
-				for (cur = *list; cur != NULL; cur = cur->next)
+				for (cur = list->data; cur != NULL; cur = cur->next)
 					if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) {
 						exists = TRUE;
 						break;
@@ -202,7 +226,7 @@
 			do {
 				new->bid += 0x0001;
 				exists = FALSE;
-				for (cur = *list; cur != NULL; cur = cur->next)
+				for (cur = list->data; cur != NULL; cur = cur->next)
 					if (cur->bid == new->bid || cur->gid == new->bid) {
 						exists = TRUE;
 						break;
@@ -214,7 +238,7 @@
 			do {
 				new->bid += 0x0001;
 				exists = FALSE;
-				for (cur = *list; cur != NULL; cur = cur->next)
+				for (cur = list->data; cur != NULL; cur = cur->next)
 					if (cur->bid == new->bid && cur->gid == new->gid) {
 						exists = TRUE;
 						break;
@@ -226,23 +250,29 @@
 	/* Set the type */
 	new->type = type;
 
+	/* Add it to the gid+bid hashtable */
+	g_hash_table_insert(list->idx_gid_bid, GINT_TO_POINTER((new->gid << 16) + new->bid), new);
+
+	/* Set the name - do this *AFTER* setting the type because type is used for the key */
+	aim_ssi_item_set_name(list, new, name);
+
 	/* Set the TLV list */
 	new->data = aim_tlvlist_copy(data);
 
 	/* Add the item to the list in the correct numerical position.  Fancy, eh? */
-	if (*list) {
-		if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
-			new->next = *list;
-			*list = new;
+	if (list->data) {
+		if ((new->gid < list->data->gid) || ((new->gid == list->data->gid) && (new->bid < list->data->bid))) {
+			new->next = list->data;
+			list->data = new;
 		} else {
 			struct aim_ssi_item *prev;
-			for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
+			for ((prev=list->data, cur=list->data->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
 			new->next = prev->next;
 			prev->next = new;
 		}
 	} else {
-		new->next = *list;
-		*list = new;
+		new->next = list->data;
+		list->data = new;
 	}
 
 	return new;
@@ -255,25 +285,31 @@
  * @param del A pointer to the item you want to remove from the list.
  * @return Return 0 if no errors, otherwise return the error number.
  */
-static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
+static int aim_ssi_itemlist_del(struct aim_ssi_itemlist *list, struct aim_ssi_item *del)
 {
-	if (!(*list) || !del)
+	gchar key[3000];
+
+	if (!(list->data) || !del)
 		return -EINVAL;
 
 	/* Remove the item from the list */
-	if (*list == del) {
-		*list = (*list)->next;
+	if (list->data == del) {
+		list->data = list->data->next;
 	} else {
 		struct aim_ssi_item *cur;
-		for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
+		for (cur=list->data; (cur->next && (cur->next!=del)); cur=cur->next);
 		if (cur->next)
 			cur->next = del->next;
 	}
 
+	/* Remove from the hashtables */
+	g_hash_table_remove(list->idx_gid_bid, GINT_TO_POINTER((del->gid << 16) + del->bid));
+
+	snprintf(key, sizeof(key), "%hx%s", del->type, oscar_normalize(NULL, del->name));
+	g_hash_table_remove(list->idx_all_named_items, key);
+
 	/* Free the removed item */
-	g_free(del->name);
-	aim_tlvlist_free(del->data);
-	g_free(del);
+	aim_ssi_item_free(del);
 
 	return 0;
 }
@@ -320,10 +356,10 @@
 	return 0;
 }
 
-static gboolean aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
+static gboolean aim_ssi_itemlist_valid(struct aim_ssi_itemlist *list, struct aim_ssi_item *item)
 {
 	struct aim_ssi_item *cur;
-	for (cur=list; cur; cur=cur->next)
+	for (cur=list->data; cur; cur=cur->next)
 		if (cur == item)
 			return TRUE;
 	return FALSE;
@@ -337,13 +373,10 @@
  * @param bid The buddy ID# of the desired item.
  * @return Return a pointer to the item if found, else return NULL;
  */
-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid)
+struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_itemlist *list, guint16 gid, guint16 bid)
 {
-	struct aim_ssi_item *cur;
-	for (cur=list; cur; cur=cur->next)
-		if ((cur->gid == gid) && (cur->bid == bid))
-			return cur;
-	return NULL;
+	guint32 id_key = (gid << 16) + bid;
+	return g_hash_table_lookup(list->idx_gid_bid, GINT_TO_POINTER(id_key));
 }
 
 /**
@@ -356,37 +389,30 @@
  * @param type The type of the desired item.
  * @return Return a pointer to the item if found, else return NULL.
  */
-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type)
+struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_itemlist *list, const char *gn, const char *bn, guint16 type)
 {
 	struct aim_ssi_item *cur;
-	if (!list)
+	gchar key[3000];
+
+	if (!list->data)
 		return NULL;
 
 	if (gn && bn) { /* For finding buddies in groups */
-		for (cur=list; cur; cur=cur->next)
+		g_return_val_if_fail(type == AIM_SSI_TYPE_BUDDY, NULL);
+		for (cur=list->data; cur; cur=cur->next)
 			if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
 				struct aim_ssi_item *curg;
-				for (curg=list; curg; curg=curg->next)
+				for (curg=list->data; curg; curg=curg->next)
 					if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(oscar_util_name_compare(curg->name, gn)))
 						return cur;
 			}
 
-	} else if (gn) { /* For finding groups */
-		for (cur=list; cur; cur=cur->next) {
-			if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(oscar_util_name_compare(cur->name, gn))) {
-				return cur;
-			}
-		}
-
-	} else if (bn) { /* For finding permits, denies, and ignores */
-		for (cur=list; cur; cur=cur->next) {
-			if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
-				return cur;
-			}
-		}
+	} else if (gn || bn) { /* For finding groups, permits, denies and ignores */
+		snprintf(key, sizeof(key), "%hx%s", type, oscar_normalize(NULL, gn ? gn : bn));
+		return g_hash_table_lookup(list->idx_all_named_items, key);
 
 	/* For stuff without names--permit deny setting, visibility mask, etc. */
-	} else for (cur=list; cur; cur=cur->next) {
+	} else for (cur=list->data; cur; cur=cur->next) {
 		if ((cur->type == type) && (!cur->name))
 			return cur;
 	}
@@ -401,7 +427,7 @@
  * @param bn The group name of the desired item.
  * @return Return a pointer to the name of the item if found, else return NULL;
  */
-struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn)
+struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_itemlist *list, const char *bn)
 {
 	if (!bn)
 		return NULL;
@@ -415,10 +441,10 @@
  * @param bn The buddy name of the desired item.
  * @return Return a pointer to the name of the item if found, else return NULL;
  */
-char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn)
+char *aim_ssi_itemlist_findparentname(struct aim_ssi_itemlist *list, const char *bn)
 {
 	struct aim_ssi_item *cur, *curg;
-	if (!list || !bn)
+	if (!list->data || !bn)
 		return NULL;
 	if (!(cur = aim_ssi_itemlist_exists(list, bn)))
 		return NULL;
@@ -433,7 +459,7 @@
  * @param list A pointer to the current list of items.
  * @return Return the current SSI permit deny setting, or 0 if no setting was found.
  */
-int aim_ssi_getpermdeny(struct aim_ssi_item *list)
+int aim_ssi_getpermdeny(struct aim_ssi_itemlist *list)
 {
 	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
 	if (cur) {
@@ -451,7 +477,7 @@
  * @param list A pointer to the current list of items.
  * @return Return the current set of preferences.
  */
-guint32 aim_ssi_getpresence(struct aim_ssi_item *list)
+guint32 aim_ssi_getpresence(struct aim_ssi_itemlist *list)
 {
 	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
 	if (cur) {
@@ -472,17 +498,23 @@
  *         alias, or NULL if the buddy has no alias.  You should free
  *         this returned value!
  */
-char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn)
+char *aim_ssi_getalias(struct aim_ssi_itemlist *list, const char *gn, const char *bn)
 {
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
-	if (cur) {
-		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);
-		if (tlv && tlv->length)
-			return g_strndup((const gchar *)tlv->value, tlv->length);
+	struct aim_ssi_item *item = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
+	if (item) {
+		return aim_ssi_getalias_from_item(item);
 	}
 	return NULL;
 }
 
+char *aim_ssi_getalias_from_item(struct aim_ssi_item *item)
+{
+	aim_tlv_t *tlv = aim_tlv_gettlv(item->data, 0x0131, 1);
+	if (tlv && tlv->length)
+		return g_strndup((const gchar *)tlv->value, tlv->length);
+	return NULL;
+}
+
 /**
  * Locally find the comment of the given buddy.
  *
@@ -493,7 +525,7 @@
  *         comment, or NULL if the buddy has no comment.  You should free
  *         this returned value!
  */
-char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn)
+char *aim_ssi_getcomment(struct aim_ssi_itemlist *list, const char *gn, const char *bn)
 {
 	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
 	if (cur) {
@@ -513,7 +545,7 @@
  * @param bn The name of the buddy.
  * @return 1 if you are waiting for authorization; 0 if you are not
  */
-gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn)
+gboolean aim_ssi_waitingforauth(struct aim_ssi_itemlist *list, const char *gn, const char *bn)
 {
 	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
 	if (cur) {
@@ -561,8 +593,8 @@
 
 	/* Deletions */
 	if (!od->ssi.pending) {
-		for (cur1=od->ssi.official; cur1 && (n < 15); cur1=cur1->next) {
-			if (!aim_ssi_itemlist_find(od->ssi.local, cur1->gid, cur1->bid)) {
+		for (cur1=od->ssi.official.data; cur1 && (n < 15); cur1=cur1->next) {
+			if (!aim_ssi_itemlist_find(&od->ssi.local, cur1->gid, cur1->bid)) {
 				n++;
 				new = g_new(struct aim_ssi_tmp, 1);
 				new->action = SNAC_SUBTYPE_FEEDBAG_DEL;
@@ -575,15 +607,15 @@
 					cur->next = new;
 				} else
 					od->ssi.pending = new;
-			       	aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
+					aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
 			}
 		}
 	}
 
 	/* Additions */
 	if (!od->ssi.pending) {
-		for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
-			if (!aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid)) {
+		for (cur1=od->ssi.local.data; cur1 && (n < 15); cur1=cur1->next) {
+			if (!aim_ssi_itemlist_find(&od->ssi.official, cur1->gid, cur1->bid)) {
 				n++;
 				new = g_new(struct aim_ssi_tmp, 1);
 				new->action = SNAC_SUBTYPE_FEEDBAG_ADD;
@@ -596,15 +628,15 @@
 					cur->next = new;
 				} else
 					od->ssi.pending = new;
-			       	aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
+					aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
 			}
 		}
 	}
 
 	/* Modifications */
 	if (!od->ssi.pending) {
-		for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
-			cur2 = aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid);
+		for (cur1=od->ssi.local.data; cur1 && (n < 15); cur1=cur1->next) {
+			cur2 = aim_ssi_itemlist_find(&od->ssi.official, cur1->gid, cur1->bid);
 			if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
 				n++;
 				new = g_new(struct aim_ssi_tmp, 1);
@@ -618,18 +650,18 @@
 					cur->next = new;
 				} else
 					od->ssi.pending = new;
-			       	aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
+					aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
 			}
 		}
 	}
 	if (debugstr->len > 0) {
 		purple_debug_info("oscar", "%s", debugstr->str);
 		if (purple_debug_is_verbose()) {
-	    		g_string_truncate(debugstr, 0);
-			for (cur1 = od->ssi.local; cur1; cur1 = cur1->next) 
+			g_string_truncate(debugstr, 0);
+			for (cur1 = od->ssi.local.data; cur1; cur1 = cur1->next)
 				aim_ssi_item_debug_append(debugstr, "\t", cur1);
 			purple_debug_misc("oscar", "Dumping item list of account %s:\n%s",
-				purple_connection_get_account(od->gc)->username, debugstr->str);
+				purple_account_get_username(purple_connection_get_account(od->gc)), debugstr->str);
 		}
 	}
 	g_string_free(debugstr, TRUE);
@@ -673,22 +705,18 @@
 	struct aim_ssi_item *cur, *del;
 	struct aim_ssi_tmp *curtmp, *deltmp;
 
-	cur = od->ssi.official;
+	cur = od->ssi.official.data;
 	while (cur) {
 		del = cur;
 		cur = cur->next;
-		g_free(del->name);
-		aim_tlvlist_free(del->data);
-		g_free(del);
+		aim_ssi_item_free(del);
 	}
 
-	cur = od->ssi.local;
+	cur = od->ssi.local.data;
 	while (cur) {
 		del = cur;
 		cur = cur->next;
-		g_free(del->name);
-		aim_tlvlist_free(del->data);
-		g_free(del);
+		aim_ssi_item_free(del);
 	}
 
 	curtmp = od->ssi.pending;
@@ -699,8 +727,8 @@
 	}
 
 	od->ssi.numitems = 0;
-	od->ssi.official = NULL;
-	od->ssi.local = NULL;
+	od->ssi.official.data = NULL;
+	od->ssi.local.data = NULL;
 	od->ssi.pending = NULL;
 	od->ssi.timestamp = (time_t)0;
 }
@@ -726,7 +754,7 @@
 	/* DESTROY any buddies that are directly in the master group. */
 	/* Do the same for buddies that are in a non-existant group. */
 	/* This will kind of mess up if you hit the item limit, but this function isn't too critical */
-	cur = od->ssi.local;
+	cur = od->ssi.local.data;
 	while (cur) {
 		next = cur->next;
 		if (!cur->name) {
@@ -734,8 +762,8 @@
 				aim_ssi_delbuddy(od, NULL, NULL);
 			else if (cur->type == AIM_SSI_TYPE_PERMIT || cur->type == AIM_SSI_TYPE_DENY || cur->type == AIM_SSI_TYPE_ICQDENY)
 				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);
+		} 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_delbuddy(od, cur->name, NULL);
 			g_free(alias);
@@ -744,7 +772,7 @@
 	}
 
 	/* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */
-	cur = od->ssi.local;
+	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))
 		{
@@ -785,16 +813,16 @@
 		return -EINVAL;
 
 	/* Find the parent */
-	if (!(parent = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
+	if (!(parent = aim_ssi_itemlist_finditem(&od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
 		/* Find the parent's parent (the master group) */
-		if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+		if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL)
 			aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
 
 		/* Add the parent */
 		parent = aim_ssi_itemlist_add(&od->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
 
 		/* Modify the parent's parent (the master group) */
-		aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL);
+		aim_ssi_itemlist_rebuildgroup(&od->ssi.local, NULL);
 	}
 
 	/* Create a TLV list for the new buddy */
@@ -812,7 +840,7 @@
 	aim_tlvlist_free(data);
 
 	/* Modify the parent group */
-	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+	aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
@@ -824,7 +852,7 @@
 	if (!od || !name || !od->ssi.received_data)
 		return -EINVAL;
 
-	if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+	if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL)
 		aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
 
 	aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, list_type, NULL);
@@ -839,7 +867,7 @@
 	if (!od)
 		return -EINVAL;
 
-	if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, list_type)))
+	if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, name, list_type)))
 		return -EINVAL;
 
 	aim_ssi_itemlist_del(&od->ssi.local, del);
@@ -862,14 +890,14 @@
 		return -EINVAL;
 
 	/* Find the buddy */
-	if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
+	if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
 		return -EINVAL;
 
 	/* Remove the item from the list */
 	aim_ssi_itemlist_del(&od->ssi.local, del);
 
 	/* Modify the parent group */
-	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+	aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
@@ -891,7 +919,7 @@
 		return -EINVAL;
 
 	/* Find the group */
-	if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
+	if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
 		return -EINVAL;
 
 	/* Don't delete the group if it's not empty */
@@ -903,7 +931,7 @@
 	aim_ssi_itemlist_del(&od->ssi.local, del);
 
 	/* Modify the parent group */
-	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+	aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
@@ -925,7 +953,7 @@
 	GSList *data;
 
 	/* Find the buddy */
-	buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY);
+	buddy = aim_ssi_itemlist_finditem(&od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY);
 	if (buddy == NULL)
 		return -EINVAL;
 
@@ -958,11 +986,11 @@
 	if (!od || !gn || !bn)
 		return -EINVAL;
 
-	if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
+	if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
 		return -EINVAL;
 
 	/* Either add or remove the 0x0131 TLV from the TLV chain */
-	if ((alias != NULL) && (strlen(alias) > 0))
+	if (alias && *alias)
 		aim_tlvlist_replace_str(&tmp->data, 0x0131, alias);
 	else
 		aim_tlvlist_remove(&tmp->data, 0x0131);
@@ -988,11 +1016,11 @@
 	if (!od || !gn || !bn)
 		return -EINVAL;
 
-	if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
+	if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
 		return -EINVAL;
 
 	/* Either add or remove the 0x0131 TLV from the TLV chain */
-	if ((comment != NULL) && (strlen(comment) > 0))
+	if (comment && *comment)
 		aim_tlvlist_replace_str(&tmp->data, 0x013c, comment);
 	else
 		aim_tlvlist_remove(&tmp->data, 0x013c);
@@ -1016,11 +1044,10 @@
 	if (!od || !oldgn || !newgn)
 		return -EINVAL;
 
-	if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
+	if (!(group = aim_ssi_itemlist_finditem(&od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
 		return -EINVAL;
 
-	g_free(group->name);
-	group->name = g_strdup(newgn);
+	aim_ssi_item_set_name(&od->ssi.local, group, newgn);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
@@ -1047,9 +1074,9 @@
 		return -EINVAL;
 
 	/* Find the PDINFO item, or add it if it does not exist */
-	if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
+	if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
 		/* Make sure the master group exists */
-		if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+		if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL)
 			aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
 
 		tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);
@@ -1079,9 +1106,9 @@
 		return -EINVAL;
 
 	/* Find the ICONINFO item, or add it if it does not exist */
-	if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
+	if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
 		/* Make sure the master group exists */
-		if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+		if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL)
 			aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
 
 		tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0xFFFF, AIM_SSI_TYPE_ICONINFO, NULL);
@@ -1139,9 +1166,9 @@
 		return -EINVAL;
 
 	/* Find the PRESENCEPREFS item, or add it if it does not exist */
-	if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
+	if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
 		/* Make sure the master group exists */
-		if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+		if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL)
 			aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
 
 		tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);
@@ -1257,7 +1284,7 @@
 		aim_tlvlist_free(data);
 	}
 	purple_debug_misc("oscar", "Reading items from tlvlist for account %s:\n%s",
-		purple_connection_get_account(od->gc)->username, debugstr->str);
+		purple_account_get_username(purple_connection_get_account(od->gc)), debugstr->str);
 	g_string_free(debugstr, TRUE);
 
 	/* Read in the timestamp */
@@ -1266,7 +1293,7 @@
 	if (!(snac->flags & 0x0001)) {
 		/* Make a copy of the list */
 		struct aim_ssi_item *cur;
-		for (cur=od->ssi.official; cur; cur=cur->next)
+		for (cur=od->ssi.official.data; cur; cur=cur->next)
 			aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
 
 		od->ssi.received_data = TRUE;
@@ -1416,18 +1443,16 @@
 			data = NULL;
 
 		/* Replace the 2 local items with the given one */
-		if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) {
+		if ((item = aim_ssi_itemlist_find(&od->ssi.local, gid, bid))) {
 			item->type = type;
-			g_free(item->name);
-			item->name = g_strdup(name);
+			aim_ssi_item_set_name(&od->ssi.local, item, name);
 			aim_tlvlist_free(item->data);
 			item->data = aim_tlvlist_copy(data);
 		}
 
-		if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) {
+		if ((item = aim_ssi_itemlist_find(&od->ssi.official, gid, bid))) {
 			item->type = type;
-			g_free(item->name);
-			item->name = g_strdup(name);
+			aim_ssi_item_set_name(&od->ssi.official, item, name);
 			aim_tlvlist_free(item->data);
 			item->data = aim_tlvlist_copy(data);
 		}
@@ -1461,9 +1486,9 @@
 		byte_stream_get16(bs);
 		byte_stream_advance(bs, byte_stream_get16(bs));
 
-		if ((del = aim_ssi_itemlist_find(od->ssi.local, gid, bid)))
+		if ((del = aim_ssi_itemlist_find(&od->ssi.local, gid, bid)))
 			aim_ssi_itemlist_del(&od->ssi.local, del);
-		if ((del = aim_ssi_itemlist_find(od->ssi.official, gid, bid)))
+		if ((del = aim_ssi_itemlist_find(&od->ssi.official, gid, bid)))
 			aim_ssi_itemlist_del(&od->ssi.official, del);
 
 		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
@@ -1504,7 +1529,8 @@
 			if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
 				/* Remove the item from the local list */
 				/* Make sure cur->item is still valid memory */
-				if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+				/* TODO: "Still valid memory"?  That's bad form. */
+				if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
 					cur->name = g_strdup(cur->item->name);
 					aim_ssi_itemlist_del(&od->ssi.local, cur->item);
 				}
@@ -1512,11 +1538,10 @@
 
 			} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
 				/* Replace the local item with the item from the official list */
-				if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+				if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
 					struct aim_ssi_item *cur1;
-					if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
-						g_free(cur->item->name);
-						cur->item->name = g_strdup(cur1->name);
+					if ((cur1 = aim_ssi_itemlist_find(&od->ssi.official, cur->item->gid, cur->item->bid))) {
+						aim_ssi_item_set_name(&od->ssi.official, cur->item, cur1->name);
 						aim_tlvlist_free(cur->item->data);
 						cur->item->data = aim_tlvlist_copy(cur1->data);
 					}
@@ -1525,7 +1550,7 @@
 
 			} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
 				/* Add the item back into the local list */
-				if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) {
+				if (aim_ssi_itemlist_valid(&od->ssi.official, cur->item)) {
 					aim_ssi_itemlist_add(&od->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
 				} else
 					cur->item = NULL;
@@ -1535,18 +1560,17 @@
 			/* Do the exact opposite */
 			if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
 			/* Add the local item to the official list */
-				if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+				if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
 					aim_ssi_itemlist_add(&od->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
 				} else
 					cur->item = NULL;
 
 			} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
 				/* Replace the official item with the item from the local list */
-				if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+				if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
 					struct aim_ssi_item *cur1;
-					if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
-						g_free(cur1->name);
-						cur1->name = g_strdup(cur->item->name);
+					if ((cur1 = aim_ssi_itemlist_find(&od->ssi.official, cur->item->gid, cur->item->bid))) {
+						aim_ssi_item_set_name(&od->ssi.official, cur1, cur->item->name);
 						aim_tlvlist_free(cur1->data);
 						cur1->data = aim_tlvlist_copy(cur->item->data);
 					}
@@ -1555,7 +1579,7 @@
 
 			} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
 				/* Remove the item from the official list */
-				if (aim_ssi_itemlist_valid(od->ssi.official, cur->item))
+				if (aim_ssi_itemlist_valid(&od->ssi.official, cur->item))
 					aim_ssi_itemlist_del(&od->ssi.official, cur->item);
 				cur->item = NULL;
 			}
--- a/libpurple/protocols/oscar/family_icbm.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Mon Oct 31 01:25:36 2011 +0000
@@ -1941,7 +1941,7 @@
 
 	account = purple_connection_get_account(od->gc);
 
-	statxml = g_strdup_printf(fmt, account->username);
+	statxml = g_strdup_printf(fmt, purple_account_get_username(account));
 	xmllen = strlen(statxml);
 
 	aim_icbm_makecookie(cookie);
@@ -2035,7 +2035,7 @@
 	/* if (!strcmp(account->username, sn))
 		icq_im_xstatus_request(od, sn); */
 
-	status = purple_presence_get_active_status(account->presence);
+	status = purple_presence_get_active_status(purple_account_get_presence(account));
 	if (!status)
 		return -EINVAL;
 
@@ -2051,7 +2051,7 @@
 	if (!msg)
 		return -EINVAL;
 
-	statxml = g_strdup_printf(fmt, account->username, title, msg);
+	statxml = g_strdup_printf(fmt, purple_account_get_username(account), title, msg);
 	len = strlen(statxml);
 
 	purple_debug_misc("oscar", "X-Status AutoReply: %s, %s\n", formatted_msg, msg);
--- a/libpurple/protocols/oscar/flap_connection.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Mon Oct 31 01:25:36 2011 +0000
@@ -487,7 +487,7 @@
 
 		if (tmp != NULL)
 		{
-			purple_connection_error_reason(od->gc, reason, tmp);
+			purple_connection_error(od->gc, reason, tmp);
 			g_free(tmp);
 		}
 	}
@@ -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/libaim.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/libaim.c	Mon Oct 31 01:25:36 2011 +0000
@@ -29,6 +29,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
@@ -50,7 +51,7 @@
 	oscar_set_status,		/* set_status */
 	oscar_set_idle,			/* set_idle */
 	oscar_change_passwd,	/* change_passwd */
-	NULL,					/* add_buddy */
+	oscar_add_buddy,		/* add_buddy */
 	NULL,					/* add_buddies */
 	oscar_remove_buddy,		/* remove_buddy */
 	NULL,					/* remove_buddies */
@@ -69,7 +70,6 @@
 	oscar_keepalive,		/* keepalive */
 	NULL,					/* register_user */
 	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
 	oscar_alias_buddy,		/* alias_buddy */
 	oscar_move_buddy,		/* group_buddy */
 	oscar_rename_group,		/* rename_group */
@@ -94,15 +94,12 @@
 	NULL,					/* unregister_user */
 	NULL,					/* send_attention */
 	NULL,					/* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,					/* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* get_media_caps */
 	NULL,					/* get_moods */
 	NULL,					/* set_public_alias */
-	NULL,					/* get_public_alias */
-	oscar_add_buddy,		/* add_buddy_with_invite */
-	NULL					/* add_buddies_with_invite */
+	NULL					/* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/oscar/libicq.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/libicq.c	Mon Oct 31 01:25:36 2011 +0000
@@ -38,6 +38,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
@@ -59,7 +60,7 @@
 	oscar_set_status,		/* set_status */
 	oscar_set_idle,			/* set_idle */
 	oscar_change_passwd,	/* change_passwd */
-	NULL,					/* add_buddy */
+	oscar_add_buddy,		/* add_buddy */
 	NULL,					/* add_buddies */
 	oscar_remove_buddy,		/* remove_buddy */
 	NULL,					/* remove_buddies */
@@ -78,7 +79,6 @@
 	oscar_keepalive,		/* keepalive */
 	NULL,					/* register_user */
 	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
 	oscar_alias_buddy,		/* alias_buddy */
 	oscar_move_buddy,		/* group_buddy */
 	oscar_rename_group,		/* rename_group */
@@ -103,16 +103,12 @@
 	NULL,					/* unregister_user */
 	NULL,					/* send_attention */
 	NULL,					/* get_attention_types */
-
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	icq_get_account_text_table, /* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* can_do_media */
 	oscar_get_purple_moods, /* get_moods */
 	NULL,					/* set_public_alias */
-	NULL,					/* get_public_alias */
-	oscar_add_buddy,		/* add_buddy_with_invite */
-	NULL					/* add_buddies_with_invite */
+	NULL					/* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/oscar/oft.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/oft.c	Mon Oct 31 01:25:36 2011 +0000
@@ -362,10 +362,10 @@
 
 	if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0)
 	{
+		int fd = conn->fd;
 		conn->sending_data_timer = 0;
-		conn->xfer->fd = conn->fd;
 		conn->fd = -1;
-		purple_xfer_start(conn->xfer, conn->xfer->fd, NULL, 0);
+		purple_xfer_start(conn->xfer, fd, NULL, 0);
 		return FALSE;
 	}
 
@@ -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);
@@ -589,7 +589,7 @@
 {
 	PeerConnection *conn;
 
-	conn = xfer->data;
+	conn = purple_xfer_get_protocol_data(xfer);
 	conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
 	peer_connection_trynext(conn);
 }
@@ -599,11 +599,11 @@
 {
 	PeerConnection *conn;
 
-	conn = xfer->data;
+	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;
@@ -617,7 +617,7 @@
 	PeerConnection *conn;
 
 	/* Update our rolling checksum.  Like Walmart, yo. */
-	conn = xfer->data;
+	conn = purple_xfer_get_protocol_data(xfer);
 	conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer,
 			size, conn->xferdata.recvcsum, purple_xfer_get_bytes_sent(xfer) & 1);
 }
@@ -651,9 +651,9 @@
 peer_oft_sendcb_init(PurpleXfer *xfer)
 {
 	PeerConnection *conn;
-	size_t size;
+	goffset size;
 
-	conn = xfer->data;
+	conn = purple_xfer_get_protocol_data(xfer);
 	conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
 
 	/* Make sure the file size can be represented in 32 bits */
@@ -665,9 +665,9 @@
 		size2 = purple_str_size_to_units(G_MAXUINT32);
 		tmp = g_strdup_printf(_("File %s is %s, which is larger than "
 				"the maximum size of %s."),
-				xfer->local_filename, size1, size2);
+				purple_xfer_get_local_filename(xfer), size1, size2);
 		purple_xfer_error(purple_xfer_get_type(xfer),
-				purple_xfer_get_account(xfer), xfer->who, tmp);
+				purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer), tmp);
 		g_free(size1);
 		g_free(size2);
 		g_free(tmp);
@@ -689,9 +689,9 @@
 	strncpy((gchar *)conn->xferdata.idstring, "Cool FileXfer", 31);
 	conn->xferdata.modtime = 0;
 	conn->xferdata.cretime = 0;
-	xfer->filename = g_path_get_basename(xfer->local_filename);
-	conn->xferdata.name_length = MAX(64, strlen(xfer->filename) + 1);
-	conn->xferdata.name = (guchar *)g_strndup(xfer->filename, conn->xferdata.name_length - 1);
+	purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
+	conn->xferdata.name_length = MAX(64, strlen(purple_xfer_get_filename(xfer)) + 1);
+	conn->xferdata.name = (guchar *)g_strndup(purple_xfer_get_filename(xfer), conn->xferdata.name_length - 1);
 
 	peer_oft_checksum_file(conn, xfer,
 			peer_oft_checksum_calculated_cb, G_MAXUINT32);
@@ -713,7 +713,7 @@
 {
 	PeerConnection *conn;
 
-	conn = xfer->data;
+	conn = purple_xfer_get_protocol_data(xfer);
 
 	/*
 	 * If we're done sending, intercept the socket from the core ft code
@@ -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);
 	}
@@ -742,7 +742,7 @@
 {
 	PeerConnection *conn;
 
-	conn = xfer->data;
+	conn = purple_xfer_get_protocol_data(xfer);
 
 	if (conn == NULL)
 		return;
--- a/libpurple/protocols/oscar/oscar.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Oct 31 01:25:36 2011 +0000
@@ -308,7 +308,7 @@
 		gchar *msg;
 		msg = g_strdup_printf(_("Unable to connect to authentication server: %s"),
 				error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 	}
 	else if (conn->type == SNAC_FAMILY_LOCATE)
@@ -316,7 +316,7 @@
 		gchar *msg;
 		msg = g_strdup_printf(_("Unable to connect to BOS server: %s"),
 				error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
 		g_free(msg);
 	}
 	else
@@ -578,7 +578,7 @@
 	gc = data;
 	od = purple_connection_get_protocol_data(gc);
 	report_idle = strcmp((const char *)value, "none") != 0;
-	presence = aim_ssi_getpresence(od->ssi.local);
+	presence = aim_ssi_getpresence(&od->ssi.local);
 
 	if (report_idle)
 		aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
@@ -600,7 +600,7 @@
 
 	gc = data;
 	od = purple_connection_get_protocol_data(gc);
-	presence = aim_ssi_getpresence(od->ssi.local);
+	presence = aim_ssi_getpresence(&od->ssi.local);
 
 	if (value)
 		aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES);
@@ -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();
@@ -735,28 +736,30 @@
 	if (!oscar_util_valid_name(purple_account_get_username(account))) {
 		gchar *buf;
 		buf = g_strdup_printf(_("Unable to sign on as %s because the username is invalid.  Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf);
 		g_free(buf);
 		return;
 	}
 
-	gc->flags |= PURPLE_CONNECTION_HTML;
-	if (oscar_util_valid_name_icq((purple_account_get_username(account)))) {
+	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);
 
 	encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
 	if (!purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) {
-		purple_connection_error_reason(
+		purple_connection_error(
 			gc,
 			PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 			_("You required encryption in your account settings, but encryption is not supported by your system."));
@@ -825,7 +828,7 @@
 		}
 
 		if (newconn->gsc == NULL && newconn->connect_data == NULL) {
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					_("Unable to connect"));
 			return;
 		}
@@ -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];
@@ -1048,7 +1051,7 @@
 
 	if (conn->gsc == NULL && conn->connect_data == NULL)
 	{
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
 		return 0;
 	}
 
@@ -1087,41 +1090,41 @@
 		switch (info->errorcode) {
 		case 0x01:
 			/* Unregistered username */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist"));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist"));
 			break;
 		case 0x05:
 			/* Incorrect password */
 			if (!purple_account_get_remember_password(account))
 				purple_account_set_password(account, NULL);
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password"));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password"));
 			break;
 		case 0x11:
 			/* Suspended account */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended"));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended"));
 			break;
 		case 0x02:
 		case 0x14:
 			/* service temporarily unavailable */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable."));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable."));
 			break;
 		case 0x18:
 			/* username connecting too frequently */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
 			break;
 		case 0x1c:
 		{
 			/* client too old */
 			g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"),
 					oscar_get_ui_info_string("website", PURPLE_WEBSITE));
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf);
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf);
 			break;
 		}
 		case 0x1d:
 			/* IP address connecting too frequently */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer."));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer."));
 			break;
 		default:
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason"));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason"));
 			break;
 		}
 		purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode);
@@ -1169,7 +1172,7 @@
 	g_free(host);
 	if (newconn->gsc == NULL && newconn->connect_data == NULL)
 	{
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
 		return 0;
 	}
 
@@ -1199,7 +1202,7 @@
 	PurpleConnection *gc = user_data;
 
 	/* Disconnect */
-	purple_connection_error_reason(gc,
+	purple_connection_error(gc,
 		PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 		_("The SecurID key entered is invalid"));
 }
@@ -1292,7 +1295,7 @@
 			purple_debug_warning("oscar", "We won't use SSL for FLAP type 0x%04hx.\n", redir->group);
 		} else if (strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) {
 			purple_debug_error("oscar", "FLAP server %s:%d of type 0x%04hx doesn't support encryption.", host, port, redir->group);
-			purple_connection_error_reason(
+			purple_connection_error(
 				gc,
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("You required encryption in your account settings, but one of the servers doesn't support it."));
@@ -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;
 }
@@ -2278,7 +2281,7 @@
 	return 0;
 }
 
-static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) {
+static int purple_parse_clientauto_ch4(OscarData *od, const char *who, guint16 reason, guint32 state, char *msg) {
 	PurpleConnection *gc = od->gc;
 
 	switch(reason) {
@@ -2286,16 +2289,20 @@
 			char *statusmsg, **splitmsg;
 			PurpleNotifyUserInfo *user_info;
 
+			statusmsg = oscar_icqstatus(state);
+
 			/* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
-			statusmsg = oscar_icqstatus(state);
+			/* TODO: Don't we need to escape each piece? */
 			splitmsg = g_strsplit(msg, "\r\n", 0);
 
 			user_info = purple_notify_user_info_new();
 
-			purple_notify_user_info_add_pair(user_info, _("UIN"), who);
-			purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Status"), statusmsg);
 			purple_notify_user_info_add_section_break(user_info);
-			purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
+			purple_notify_user_info_add_pair_html(user_info, NULL, g_strjoinv("<BR>", splitmsg));
 
 			g_free(statusmsg);
 			g_strfreev(splitmsg);
@@ -2309,16 +2316,20 @@
 			char *statusmsg, **splitmsg;
 			PurpleNotifyUserInfo *user_info;
 
+			statusmsg = oscar_icqstatus(state);
+
 			/* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
-			statusmsg = oscar_icqstatus(state);
+			/* TODO: Don't we need to escape each piece? */
 			splitmsg = g_strsplit(msg, "\r\n", 0);
 
 			user_info = purple_notify_user_info_new();
 
-			purple_notify_user_info_add_pair(user_info, _("UIN"), who);
-			purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Status"), statusmsg);
 			purple_notify_user_info_add_section_break(user_info);
-			purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
+			purple_notify_user_info_add_pair_html(user_info, NULL, g_strjoinv("<BR>", splitmsg));
 
 			g_free(statusmsg);
 			g_strfreev(splitmsg);
@@ -2808,7 +2819,7 @@
 	od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen;
 
 	aim_locate_setcaps(od, purple_caps);
-	oscar_set_info_and_status(account, TRUE, account->user_info, TRUE,
+	oscar_set_info_and_status(account, TRUE, purple_account_get_user_info(account), TRUE,
 							  purple_account_get_active_status(account));
 
 	return 1;
@@ -3168,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);
@@ -3716,7 +3727,7 @@
 	}
 
 	if (od->ssi.received_data) {
-		if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
+		if (!aim_ssi_itemlist_finditem(&od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
 			purple_debug_info("oscar",
 					   "ssi: adding buddy %s to group %s\n", bname, gname);
 			aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
@@ -3728,8 +3739,8 @@
 				purple_prpl_got_user_status(account, bname,
 						OSCAR_STATUS_ID_MOBILE, NULL);
 			}
-		} else if (aim_ssi_waitingforauth(od->ssi.local,
-		                                  aim_ssi_itemlist_findparentname(od->ssi.local, bname),
+		} else if (aim_ssi_waitingforauth(&od->ssi.local,
+		                                  aim_ssi_itemlist_findparentname(&od->ssi.local, bname),
 		                                  bname)) {
 			/* Not authorized -- Re-request authorization */
 			oscar_auth_sendrequest(gc, bname, msg);
@@ -3767,7 +3778,7 @@
 	OscarData *od = purple_connection_get_protocol_data(gc);
 
 	if (od->ssi.received_data) {
-		char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+		char *gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name);
 		if (gname) {
 			purple_debug_info("oscar",
 					   "ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)");
@@ -3784,7 +3795,7 @@
 
 	if (od->ssi.received_data) {
 		const char *gname = purple_group_get_name(group);
-		if (aim_ssi_itemlist_finditem(od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) {
+		if (aim_ssi_itemlist_finditem(&od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) {
 			GList *cur, *groups = NULL;
 			PurpleAccount *account = purple_connection_get_account(gc);
 
@@ -3798,7 +3809,7 @@
 			}
 
 			purple_account_remove_buddies(account, moved_buddies, groups);
-			purple_account_add_buddies(account, moved_buddies);
+			purple_account_add_buddies(account, moved_buddies, NULL);
 			g_list_free(groups);
 			purple_debug_info("oscar",
 					   "ssi: moved all buddies from group %s to %s\n", old_name, gname);
@@ -3935,7 +3946,7 @@
 		gname = purple_group_get_name(g);
 		bname = purple_buddy_get_name(b);
 
-		if (aim_ssi_itemlist_exists(od->ssi.local, bname)) {
+		if (aim_ssi_itemlist_exists(&od->ssi.local, bname)) {
 			/* If the buddy is an ICQ user then load his nickname */
 			const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick");
 			char *alias;
@@ -3944,7 +3955,7 @@
 				serv_got_alias(gc, bname, servernick);
 
 			/* Store local alias on server */
-			alias = aim_ssi_getalias(od->ssi.local, gname, bname);
+			alias = aim_ssi_getalias(&od->ssi.local, gname, bname);
 			balias = purple_buddy_get_local_buddy_alias(b);
 			if (!alias && balias && *balias)
 				aim_ssi_aliasbuddy(od, gname, bname, balias);
@@ -3967,7 +3978,7 @@
 		while (next != NULL) {
 			cur = next;
 			next = next->next;
-			if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
+			if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
 				purple_debug_info("oscar",
 						"ssi: removing permit %s from local list\n", (const char *)cur->data);
 				purple_privacy_permit_remove(account, cur->data, TRUE);
@@ -3980,7 +3991,7 @@
 	while (next != NULL) {
 		cur = next;
 		next = next->next;
-		if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, deny_entry_type)) {
+		if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, deny_entry_type)) {
 			purple_debug_info("oscar",
 					"ssi: removing deny %s from local list\n", (const char *)cur->data);
 			purple_privacy_deny_remove(account, cur->data, TRUE);
@@ -3988,7 +3999,7 @@
 	}
 
 	/* Presence settings (idle time visibility) */
-	tmp = aim_ssi_getpresence(od->ssi.local);
+	tmp = aim_ssi_getpresence(&od->ssi.local);
 	if (tmp != 0xFFFFFFFF) {
 		const char *idle_reporting_pref;
 		gboolean report_idle;
@@ -4006,7 +4017,7 @@
 
 	/*** Begin code for adding from server list to local list ***/
 
-	for (curitem=od->ssi.local; curitem; curitem=curitem->next) {
+	for (curitem=od->ssi.local.data; curitem; curitem=curitem->next) {
 		if (curitem->name && !g_utf8_validate(curitem->name, -1, NULL)) {
 			/* Got node with invalid UTF-8 in the name.  Skip it. */
 			purple_debug_warning("oscar", "ssi: server list contains item of "
@@ -4020,7 +4031,7 @@
 					struct aim_ssi_item *groupitem;
 					char *gname, *gname_utf8, *alias, *alias_utf8;
 
-					groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000);
+					groupitem = aim_ssi_itemlist_find(&od->ssi.local, curitem->gid, 0x0000);
 					gname = groupitem ? groupitem->name : NULL;
 					gname_utf8 = oscar_utf8_try_convert(account, od, gname);
 
@@ -4030,7 +4041,7 @@
 						purple_blist_add_group(g, NULL);
 					}
 
-					alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name);
+					alias = aim_ssi_getalias_from_item(curitem);
 					alias_utf8 = oscar_utf8_try_convert(account, od, alias);
 
 					b = purple_find_buddy_in_group(account, curitem->name, g);
@@ -4099,12 +4110,12 @@
 				 * a part of your status and not really related to blocking.
 				 */
 				if (!od->icq && curitem->data) {
-					guint8 perm_deny = aim_ssi_getpermdeny(od->ssi.local);
-					if (perm_deny != 0 && perm_deny != account->perm_deny)
+					guint8 perm_deny = aim_ssi_getpermdeny(&od->ssi.local);
+					if (perm_deny != 0 && perm_deny != purple_account_get_privacy_type(account))
 					{
 						purple_debug_info("oscar",
-								   "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, perm_deny);
-						account->perm_deny = perm_deny;
+								   "ssi: changing permdeny from %d to %hhu\n", purple_account_get_privacy_type(account), perm_deny);
+						purple_account_set_privacy_type(account, perm_deny);
 					}
 				}
 			} break;
@@ -4228,10 +4239,10 @@
 	if ((type != 0x0000) || (name == NULL))
 		return 1;
 
-	gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+	gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name);
 	gname_utf8 = gname ? oscar_utf8_try_convert(account, od, gname) : NULL;
 
-	alias = aim_ssi_getalias(od->ssi.local, gname, name);
+	alias = aim_ssi_getalias(&od->ssi.local, gname, name);
 	alias_utf8 = oscar_utf8_try_convert(account, od, alias);
 	g_free(alias);
 
@@ -4269,7 +4280,7 @@
 
 	}
 
-	ssi_item = aim_ssi_itemlist_finditem(od->ssi.local,
+	ssi_item = aim_ssi_itemlist_finditem(&od->ssi.local,
 			gname, name, AIM_SSI_TYPE_BUDDY);
 	if (ssi_item == NULL)
 	{
@@ -4586,32 +4597,18 @@
 const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b)
 {
 	const char *name = b ? purple_buddy_get_name(b) : NULL;
-	if ((b == NULL) || (name == NULL) || oscar_util_valid_name_sms(name))
-	{
-		if (a == NULL || oscar_util_valid_name_icq(purple_account_get_username(a)))
-			return "icq";
-		else
-			return "aim";
-	}
-
-	if (oscar_util_valid_name_icq(name))
+	if (name && !oscar_util_valid_name_sms(name) && oscar_util_valid_name_icq(name))
 		return "icq";
-	return "aim";
+
+	return "icq";
 }
 
 const char *oscar_list_icon_aim(PurpleAccount *a, PurpleBuddy *b)
 {
 	const char *name = b ? purple_buddy_get_name(b) : NULL;
-	if ((b == NULL) || (name == NULL) || oscar_util_valid_name_sms(name))
-	{
-		if (a != NULL && oscar_util_valid_name_icq(purple_account_get_username(a)))
-			return "icq";
-		else
-			return "aim";
-	}
-
-	if (oscar_util_valid_name_icq(name))
+	if (name && !oscar_util_valid_name_sms(name) && oscar_util_valid_name_icq(name))
 		return "icq";
+
 	return "aim";
 }
 
@@ -4642,8 +4639,8 @@
 	if (purple_presence_is_online(presence) == FALSE) {
 		char *gname;
 		if ((name) && (od) && (od->ssi.received_data) &&
-			(gname = aim_ssi_itemlist_findparentname(od->ssi.local, name)) &&
-			(aim_ssi_waitingforauth(od->ssi.local, gname, name))) {
+			(gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name)) &&
+			(aim_ssi_waitingforauth(&od->ssi.local, gname, name))) {
 			return "not-authorized";
 		}
 	}
@@ -4710,8 +4707,8 @@
 	if ((od != NULL) && !purple_presence_is_online(presence))
 	{
 		const char *name = purple_buddy_get_name(b);
-		char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
-		if (aim_ssi_waitingforauth(od->ssi.local, gname, name))
+		char *gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name);
+		if (aim_ssi_waitingforauth(&od->ssi.local, gname, name))
 			ret = g_strdup(_("Not Authorized"));
 		else
 			ret = g_strdup(_("Offline"));
@@ -4747,7 +4744,7 @@
 	 * values of libpurple's PurplePrivacyType and the values used
 	 * by the oscar protocol.
 	 */
-	aim_ssi_setpermdeny(od, account->perm_deny);
+	aim_ssi_setpermdeny(od, purple_account_get_privacy_type(account));
 }
 
 void oscar_add_permit(PurpleConnection *gc, const char *who) {
@@ -4954,7 +4951,7 @@
 
 	data = g_new(struct name_data, 1);
 
-	comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name);
+	comment = aim_ssi_getcomment(&od->ssi.local, purple_group_get_name(g), name);
 	comment_utf8 = comment ? oscar_utf8_try_convert(account, od, comment) : NULL;
 
 	data->gc = gc;
@@ -5046,7 +5043,7 @@
 	name = purple_buddy_get_name(buddy);
 	account = purple_buddy_get_account(buddy);
 	gc = purple_account_get_connection(account);
-	od = gc->proto_data;
+	od = purple_connection_get_protocol_data(gc);
 	conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
 
 	if (conn != NULL)
@@ -5175,8 +5172,8 @@
 		 * waiting for authorization.
 		 */
 		char *gname;
-		gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname);
-		if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname))
+		gname = aim_ssi_itemlist_findparentname(&od->ssi.local, bname);
+		if (gname && aim_ssi_waitingforauth(&od->ssi.local, gname, bname))
 		{
 			act = purple_menu_action_new(_("Re-request Authorization"),
 			                           PURPLE_CALLBACK(oscar_auth_sendrequest_menu),
@@ -5327,7 +5324,7 @@
 		buddy = cur->data;
 		bname = purple_buddy_get_name(buddy);
 		gname = purple_group_get_name(purple_buddy_get_group(buddy));
-		if (aim_ssi_waitingforauth(od->ssi.local, gname, bname)) {
+		if (aim_ssi_waitingforauth(&od->ssi.local, gname, bname)) {
 			filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
 		}
 	}
@@ -5482,7 +5479,7 @@
 		conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
 		aim_icbm_makecookie(conn->cookie);
 		conn->xfer = xfer;
-		xfer->data = conn;
+		purple_xfer_set_protocol_data(xfer, conn);
 	}
 
 	return xfer;
--- a/libpurple/protocols/oscar/oscar.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Mon Oct 31 01:25:36 2011 +0000
@@ -308,9 +308,14 @@
 
 #include "peer.h"
 
-/*
- * AIM Session: The main client-data interface.
- *
+struct aim_ssi_itemlist {
+	struct aim_ssi_item *data;
+	GHashTable *idx_gid_bid;
+	GHashTable *idx_all_named_items;
+};
+
+/**
+ * The main client-data interface.
  */
 struct _OscarData
 {
@@ -387,8 +392,8 @@
 	struct {
 		gboolean received_data;
 		guint16 numitems;
-		struct aim_ssi_item *official;
-		struct aim_ssi_item *local;
+		struct aim_ssi_itemlist official;
+		struct aim_ssi_itemlist local;
 		struct aim_ssi_tmp *pending;
 		time_t timestamp;
 		gboolean waiting_for_ack;
@@ -916,15 +921,16 @@
 /* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, const char *bn, guint8 reply, const char *msg);
 
 /* Client functions for retrieving SSI data */
-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid);
-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type);
-struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn);
-char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn);
-int aim_ssi_getpermdeny(struct aim_ssi_item *list);
-guint32 aim_ssi_getpresence(struct aim_ssi_item *list);
-char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn);
-char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn);
-gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn);
+struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_itemlist *list, guint16 gid, guint16 bid);
+struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_itemlist *list, const char *gn, const char *bn, guint16 type);
+struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_itemlist *list, const char *bn);
+char *aim_ssi_itemlist_findparentname(struct aim_ssi_itemlist *list, const char *bn);
+int aim_ssi_getpermdeny(struct aim_ssi_itemlist *list);
+guint32 aim_ssi_getpresence(struct aim_ssi_itemlist *list);
+char *aim_ssi_getalias(struct aim_ssi_itemlist *list, const char *gn, const char *bn);
+char *aim_ssi_getalias_from_item(struct aim_ssi_item *item);
+char *aim_ssi_getcomment(struct aim_ssi_itemlist *list, const char *gn, const char *bn);
+gboolean aim_ssi_waitingforauth(struct aim_ssi_itemlist *list, const char *gn, const char *bn);
 
 /* Client functions for changing SSI data */
 int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *tlvlist, const char *alias, const char *comment, const char *smsnum, gboolean needauth);
--- a/libpurple/protocols/oscar/oscar_data.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/oscar_data.c	Mon Oct 31 01:25:36 2011 +0000
@@ -47,6 +47,12 @@
 	od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 	od->handlerlist = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
 
+	od->ssi.local.idx_gid_bid = g_hash_table_new(g_direct_hash, g_direct_equal);
+	od->ssi.local.idx_all_named_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+	od->ssi.official.idx_gid_bid = g_hash_table_new(g_direct_hash, g_direct_equal);
+	od->ssi.official.idx_all_named_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
 	/*
 	 * Register all the modules for this session...
 	 */
@@ -126,6 +132,12 @@
 	g_hash_table_destroy(od->buddyinfo);
 	g_hash_table_destroy(od->handlerlist);
 
+	g_hash_table_destroy(od->ssi.local.idx_gid_bid);
+	g_hash_table_destroy(od->ssi.local.idx_all_named_items);
+
+	g_hash_table_destroy(od->ssi.official.idx_gid_bid);
+	g_hash_table_destroy(od->ssi.official.idx_all_named_items);
+
 	g_free(od);
 }
 
--- a/libpurple/protocols/oscar/peer.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/peer.c	Mon Oct 31 01:25:36 2011 +0000
@@ -212,7 +212,7 @@
 	if (conn->xfer != NULL)
 	{
 		PurpleXferStatusType status;
-		conn->xfer->data = NULL;
+		purple_xfer_set_protocol_data(conn->xfer, NULL);
 		status = purple_xfer_get_status(conn->xfer);
 		if ((status != PURPLE_XFER_STATUS_DONE) &&
 			(status != PURPLE_XFER_STATUS_CANCEL_LOCAL) &&
@@ -842,7 +842,7 @@
 		 */
 		conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING;
 
-		conn->listen_data = purple_network_listen_range(5190, 5290, SOCK_STREAM,
+		conn->listen_data = purple_network_listen_range(5190, 5290, AF_UNSPEC, SOCK_STREAM, TRUE,
 				peer_connection_establish_listener_cb, conn);
 		if (conn->listen_data != NULL)
 		{
@@ -1072,7 +1072,7 @@
 		conn->xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, bn);
 		if (conn->xfer)
 		{
-			conn->xfer->data = conn;
+			purple_xfer_set_protocol_data(conn->xfer, conn);
 			purple_xfer_ref(conn->xfer);
 			purple_xfer_set_size(conn->xfer, args->info.sendfile.totsize);
 
--- a/libpurple/protocols/oscar/userinfo.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/userinfo.c	Mon Oct 31 01:25:36 2011 +0000
@@ -131,21 +131,16 @@
 }
 
 static void
-oscar_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *name, const char *value)
-{
-	if (value && value[0]) {
-		purple_notify_user_info_add_pair(user_info, name, value);
-	}
-}
-
-static void
 oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
 					const char *name, const char *value)
 {
 	gchar *utf8;
 
 	if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
-		purple_notify_user_info_add_pair(user_info, name, utf8);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext.  Will
+		         need to check callers of this function. */
+		purple_notify_user_info_add_pair_html(user_info, name, utf8);
 		g_free(utf8);
 	}
 }
@@ -158,7 +153,10 @@
 
 	if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
 		gchar *tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>", url_prefix, utf8, utf8);
-		purple_notify_user_info_add_pair(user_info, name, tmp);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext.  Will
+		         need to check callers of this function. */
+		purple_notify_user_info_add_pair_html(user_info, name, tmp);
 		g_free(utf8);
 		g_free(tmp);
 	}
@@ -263,8 +261,8 @@
 				message = tmp;
 			}
 
-		} else if (aim_ssi_waitingforauth(od->ssi.local,
-			aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)),
+		} else if (aim_ssi_waitingforauth(&od->ssi.local,
+			aim_ssi_itemlist_findparentname(&od->ssi.local, purple_buddy_get_name(b)),
 			purple_buddy_get_name(b)))
 		{
 			/* Note if an offline buddy is not authorized */
@@ -295,12 +293,12 @@
 			} else {
 				description = g_strdup(_(mood));
 			}
-			purple_notify_user_info_add_pair(user_info, _("Mood"), description);
+			purple_notify_user_info_add_pair_html(user_info, _("Mood"), description);
 			g_free(description);
 		}
 	}
 
-	purple_notify_user_info_add_pair(user_info, _("Status"), message);
+	purple_notify_user_info_add_pair_html(user_info, _("Status"), message);
 	g_free(message);
 }
 
@@ -340,23 +338,23 @@
 		bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn));
 
 	if ((bi != NULL) && (bi->ipaddr != 0)) {
-		tmp =  g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
-						(bi->ipaddr & 0xff000000) >> 24,
-						(bi->ipaddr & 0x00ff0000) >> 16,
-						(bi->ipaddr & 0x0000ff00) >> 8,
-						(bi->ipaddr & 0x000000ff));
-		oscar_user_info_add_pair(user_info, _("IP Address"), tmp);
-		g_free(tmp);
+		char tmp2[40];
+		sprintf(tmp2, "%hhu.%hhu.%hhu.%hhu",
+				(bi->ipaddr & 0xff000000) >> 24,
+				(bi->ipaddr & 0x00ff0000) >> 16,
+				(bi->ipaddr & 0x0000ff00) >> 8,
+				(bi->ipaddr & 0x000000ff));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), tmp2);
 	}
 
 	if ((userinfo != NULL) && (userinfo->warnlevel != 0)) {
-		tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5));
-		oscar_user_info_add_pair(user_info, _("Warning Level"), tmp);
-		g_free(tmp);
+		char tmp2[12];
+		sprintf(tmp2, "%d", (int)(userinfo->warnlevel/10.0 + .5));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Warning Level"), tmp2);
 	}
 
 	if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) {
-		tmp = aim_ssi_getcomment(od->ssi.local, gname, bname);
+		tmp = aim_ssi_getcomment(&od->ssi.local, gname, bname);
 		if (tmp != NULL) {
 			char *tmp2 = g_markup_escape_text(tmp, strlen(tmp));
 			g_free(tmp);
@@ -372,7 +370,7 @@
 {
 	PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
 	gchar *buf = g_strdup_printf(_("User information not available: %s"), oscar_get_msgerr_reason(error_reason));
-	purple_notify_user_info_add_pair(user_info, NULL, buf);
+	purple_notify_user_info_add_pair_plaintext(user_info, NULL, buf);
 	purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL);
 	purple_notify_user_info_destroy(user_info);
 	purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf);
@@ -402,16 +400,16 @@
 	else
 		bi = NULL;
 
-	purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who);
 	oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick);
 	if ((bi != NULL) && (bi->ipaddr != 0)) {
-		char *tstr =  g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
-						(bi->ipaddr & 0xff000000) >> 24,
-						(bi->ipaddr & 0x00ff0000) >> 16,
-						(bi->ipaddr & 0x0000ff00) >> 8,
-						(bi->ipaddr & 0x000000ff));
-		purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr);
-		g_free(tstr);
+		char tstr[40];
+		sprintf(tstr, "%hhu.%hhu.%hhu.%hhu",
+				(bi->ipaddr & 0xff000000) >> 24,
+				(bi->ipaddr & 0x00ff0000) >> 16,
+				(bi->ipaddr & 0x0000ff00) >> 8,
+				(bi->ipaddr & 0x000000ff));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), tstr);
 	}
 	oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first);
 	oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last);
@@ -425,7 +423,7 @@
 	oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile);
 
 	if (info->gender != 0)
-		purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male")));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male")));
 
 	if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) {
 		/* Initialize the struct properly or strftime() will crash
@@ -437,7 +435,7 @@
 		tm->tm_mon  = (int)info->birthmonth - 1;
 		tm->tm_year = (int)info->birthyear - 1900;
 
-		/* Ignore dst setting of today to avoid timezone shift between 
+		/* Ignore dst setting of today to avoid timezone shift between
 		 * dates in summer and winter time. */
 		tm->tm_isdst = -1;
 
@@ -451,8 +449,9 @@
 	if ((info->age > 0) && (info->age < 255)) {
 		char age[5];
 		snprintf(age, sizeof(age), "%hhd", info->age);
-		purple_notify_user_info_add_pair(user_info, _("Age"), age);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Age"), age);
 	}
+	/* TODO: Is it correct to pass info->email here...? */
 	oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Personal Web Page"), info->email, "");
 	if (buddy != NULL)
 		oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* use_html_status */ TRUE);
@@ -482,6 +481,7 @@
 		oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany);
 		oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision);
 		oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition);
+		/* TODO: Is it correct to pass info->email here...? */
 		oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Web Page"), info->email, "");
 	}
 
@@ -505,7 +505,7 @@
 
 	if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) {
 		tmp = purple_str_seconds_to_string(userinfo->idletime*60);
-		oscar_user_info_add_pair(user_info, _("Idle"), tmp);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp);
 		g_free(tmp);
 	}
 
@@ -514,17 +514,18 @@
 	if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) {
 		/* An SMS contact is always online; its Online Since value is not useful */
 		time_t t = userinfo->onlinesince;
-		oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t)));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Online Since"), purple_date_format_full(localtime(&t)));
 	}
 
 	if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) {
 		time_t t = userinfo->membersince;
-		oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t)));
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Member Since"), purple_date_format_full(localtime(&t)));
 	}
 
 	if (userinfo->capabilities != 0) {
 		tmp = oscar_caps_to_string(userinfo->capabilities);
-		oscar_user_info_add_pair(user_info, _("Capabilities"), tmp);
+		if (tmp && *tmp)
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Capabilities"), tmp);
 		g_free(tmp);
 	}
 
@@ -533,7 +534,11 @@
 		info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
 		tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account));
 		purple_notify_user_info_add_section_break(user_info);
-		oscar_user_info_add_pair(user_info, _("Profile"), tmp);
+		if (tmp && *tmp) {
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Profile"), tmp);
+		}
 		g_free(tmp);
 		g_free(info_utf8);
 	}
@@ -542,9 +547,9 @@
 	base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com";
 	tmp = g_strdup_printf("<a href=\"%s/%s\">%s</a>",
 			base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile"));
-	purple_notify_user_info_add_pair(user_info, NULL, tmp);
+	purple_notify_user_info_add_pair_html(user_info, NULL, tmp);
 	g_free(tmp);
 
 	purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL);
 	purple_notify_user_info_destroy(user_info);
-}
\ No newline at end of file
+}
--- a/libpurple/protocols/oscar/visibility.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/oscar/visibility.c	Mon Oct 31 01:25:36 2011 +0000
@@ -51,7 +51,7 @@
 static gboolean
 is_buddy_on_list(OscarData *od, const char *bname)
 {
-	return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL;
+	return aim_ssi_itemlist_finditem(&od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL;
 }
 
 static void
@@ -102,7 +102,7 @@
 
 		buddy = cur->data;
 		bname = purple_buddy_get_name(buddy);
-		if (aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, list_type)) {
+		if (aim_ssi_itemlist_finditem(&od->ssi.local, NULL, bname, list_type)) {
 			filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
 		}
 	}
--- a/libpurple/protocols/sametime/sametime.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Mon Oct 31 01:25:36 2011 +0000
@@ -197,7 +197,7 @@
 
 
 /** the purple plugin data.
-    available as gc->proto_data and mwSession_getClientData */
+    available as purple_connection_get_protocol_data(gc) and mwSession_getClientData */
 struct mwPurplePluginData {
   struct mwSession *session;
 
@@ -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 */
@@ -320,7 +321,7 @@
 
   g_return_val_if_fail(gc != NULL, NULL);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_val_if_fail(pd != NULL, NULL);
 
   return pd->session;
@@ -413,7 +414,7 @@
 			g_strerror(errno));
     DEBUG_ERROR("write returned %" G_GSSIZE_FORMAT ", %" G_GSIZE_FORMAT
 			" bytes left unwritten\n", ret, len);
-    purple_connection_error_reason(pd->gc,
+    purple_connection_error(pd->gc,
                                    PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
                                    tmp);
 	g_free(tmp);
@@ -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;
   }
 }
 
@@ -499,7 +500,7 @@
   gc = mwAwareList_getClientData(list);
   acct = purple_connection_get_account(gc);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   idle = aware->status.time;
   stat = aware->status.status;
   id = aware->id.user;
@@ -851,7 +852,7 @@
 static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
 			       struct mwSametimeUser *stuser) {
 
-  struct mwPurplePluginData *pd = gc->proto_data;
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   PurpleBuddy *buddy;
   PurpleAccount *acct = purple_connection_get_account(gc);
 
@@ -861,7 +862,7 @@
   enum mwSametimeUserType type = mwSametimeUser_getType(stuser);
 
   g_return_val_if_fail(id != NULL, NULL);
-  g_return_val_if_fail(strlen(id) > 0, NULL);
+  g_return_val_if_fail(*id, NULL);
 
   buddy = purple_find_buddy_in_group(acct, id, group);
   if(! buddy) {
@@ -973,7 +974,7 @@
 
   if(type == mwSametimeGroup_DYNAMIC) {
     purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner);
-    group_add(gc->proto_data, group);
+    group_add(purple_connection_get_protocol_data(gc), group);
   }
 
   return group;
@@ -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 */
 
@@ -1403,7 +1404,7 @@
   }
 
   if(add_buds) {
-    purple_account_add_buddies(acct, add_buds);
+    purple_account_add_buddies(acct, add_buds, NULL);
     g_list_free(add_buds);
   }
 }
@@ -1618,7 +1619,7 @@
       default:
         reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
       }
-      purple_connection_error_reason(gc, reason, err);
+      purple_connection_error(gc, reason, err);
       g_free(err);
     }
     break;
@@ -1760,14 +1761,14 @@
     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) {
     DEBUG_INFO("connection reset\n");
-    purple_connection_error_reason(pd->gc,
+    purple_connection_error(pd->gc,
                                    PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
                                    _("Server closed the connection"));
 
@@ -1778,7 +1779,7 @@
     DEBUG_INFO("error in read callback: %s\n", err_str);
 
     msg = g_strdup_printf(_("Lost connection with server: %s"), err_str);
-    purple_connection_error_reason(pd->gc,
+    purple_connection_error(pd->gc,
                                    PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
                                    msg);
     g_free(msg);
@@ -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 */
@@ -1804,7 +1804,7 @@
       /* this is a regular connect, error out */
       gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
           error_message);
-      purple_connection_error_reason(pd->gc,
+      purple_connection_error(pd->gc,
                                      PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
                                      tmp);
       g_free(tmp);
@@ -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);
@@ -2144,7 +2144,7 @@
 
 static void ft_incoming_cancel(PurpleXfer *xfer) {
   /* incoming transfer rejected or cancelled in-progress */
-  struct mwFileTransfer *ft = xfer->data;
+  struct mwFileTransfer *ft = purple_xfer_get_protocol_data(xfer);
   if(ft) mwFileTransfer_reject(ft);
 }
 
@@ -2160,9 +2160,9 @@
   struct mwFileTransfer *ft;
   FILE *fp;
 
-  ft = xfer->data;
-
-  fp = g_fopen(xfer->local_filename, "wb");
+  ft = purple_xfer_get_protocol_data(xfer);
+
+  fp = g_fopen(purple_xfer_get_local_filename(xfer), "wb");
   if(! fp) {
     mwFileTransfer_cancel(ft);
     return;
@@ -2207,7 +2207,7 @@
   {
 	purple_xfer_ref(xfer);
 	mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);
-	xfer->data = ft;
+	purple_xfer_set_protocol_data(xfer, ft);
 
 	purple_xfer_set_init_fnc(xfer, ft_incoming_init);
 	purple_xfer_set_cancel_recv_fnc(xfer, ft_incoming_cancel);
@@ -2236,8 +2236,7 @@
   if(fread(buf, (size_t) o.len, 1, fp)) {
 
     /* calculate progress and display it */
-    xfer->bytes_sent += o.len;
-    xfer->bytes_remaining -= o.len;
+    purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) + o.len);
     purple_xfer_update_progress(xfer);
 
     mwFileTransfer_send(ft, &o);
@@ -2269,7 +2268,7 @@
   }
 
   if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
-    xfer->dest_fp = g_fopen(xfer->local_filename, "rb");
+    xfer->dest_fp = g_fopen(purple_xfer_get_local_filename(xfer), "rb");
     ft_send(ft, xfer->dest_fp);
   }
 }
@@ -2286,7 +2285,7 @@
 
   xfer = mwFileTransfer_getClientData(ft);
   if(xfer) {
-    xfer->data = NULL;
+    purple_xfer_set_protocol_data(xfer, NULL);
 
     if(! mwFileTransfer_getRemaining(ft)) {
       purple_xfer_set_completed(xfer, TRUE);
@@ -2339,8 +2338,7 @@
   }
 
   /* update the progress */
-  xfer->bytes_sent += data->len;
-  xfer->bytes_remaining -= data->len;
+  purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) + data->len);
   purple_xfer_update_progress(xfer);
 
   /* let the other side know we got it, and to send some more */
@@ -2353,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);
@@ -2487,12 +2485,12 @@
   text = g_strconcat(_("Unable to send message: "), tmp, NULL);
 
   gconv = convo_get_gconv(conv);
-  if(gconv && !purple_conv_present_error(idb->user, gconv->account, text)) {
+  if(gconv && !purple_conv_present_error(idb->user, purple_conversation_get_account(gconv), text)) {
 
     g_free(text);
     text = g_strdup_printf(_("Unable to send message to %s:"),
 			   (idb->user)? idb->user: "(unknown)");
-    purple_notify_error(purple_account_get_connection(gconv->account),
+    purple_notify_error(purple_account_get_connection(purple_conversation_get_account(gconv)),
 		      NULL, text, tmp);
   }
 
@@ -2530,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));
 }
 
 
@@ -3199,7 +3197,7 @@
   mwSession_addCipher(pd->session, mwCipher_new_RC2_128(pd->session));
 
   mwSession_setClientData(pd->session, pd, NULL);
-  gc->proto_data = pd;
+  purple_connection_set_protocol_data(gc, pd);
 
   return pd;
 }
@@ -3208,7 +3206,7 @@
 static void mwPurplePluginData_free(struct mwPurplePluginData *pd) {
   g_return_if_fail(pd != NULL);
 
-  pd->gc->proto_data = NULL;
+  purple_connection_set_protocol_data(pd->gc, NULL);
 
   mwSession_removeService(pd->session, mwService_AWARE);
   mwSession_removeService(pd->session, mwService_CONFERENCE);
@@ -3270,7 +3268,7 @@
   const char *ret = NULL;
 
   if ((gc = purple_account_get_connection(purple_buddy_get_account(b)))
-      && (pd = gc->proto_data))
+      && (pd = purple_connection_get_protocol_data(gc)))
     ret = mwServiceAware_getText(pd->srvc_aware, &t);
 
   return (ret && g_utf8_validate(ret, -1, NULL)) ? g_markup_escape_text(ret, -1): NULL;
@@ -3333,29 +3331,27 @@
   char *tmp;
 
   if ((gc = purple_account_get_connection(purple_buddy_get_account(b)))
-      && (pd = gc->proto_data))
+      && (pd = purple_connection_get_protocol_data(gc)))
      message = mwServiceAware_getText(pd->srvc_aware, &idb);
 
   status = status_text(b);
 
   if(message != NULL && g_utf8_validate(message, -1, NULL) && purple_utf8_strcasecmp(status, message)) {
-    tmp = g_markup_escape_text(message, -1);
-	purple_notify_user_info_add_pair(user_info, status, tmp);
-    g_free(tmp);
+	purple_notify_user_info_add_pair_plaintext(user_info, status, message);
 
   } else {
-	purple_notify_user_info_add_pair(user_info, _("Status"), status);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status);
   }
 
   if(full && pd != NULL) {
     tmp = user_supports_text(pd->srvc_aware, purple_buddy_get_name(b));
     if(tmp) {
-	  purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
+	  purple_notify_user_info_add_pair_plaintext(user_info, _("Supports"), tmp);
       g_free(tmp);
     }
 
     if(buddy_is_external(b)) {
-	  purple_notify_user_info_add_pair(user_info, NULL, _("External User"));
+	  purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("External User"));
     }
   }
 }
@@ -3412,7 +3408,7 @@
 
   acct = purple_buddy_get_account(buddy);
   gc = purple_account_get_connection(acct);
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   srvc = pd->srvc_conf;
 
   f = purple_request_fields_get_field(fields, CHAT_KEY_TOPIC);
@@ -3578,7 +3574,7 @@
   gc = purple_account_get_connection(acct);
   g_return_if_fail(gc != NULL);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   /*
@@ -3617,7 +3613,7 @@
   gc = purple_account_get_connection(acct);
   g_return_if_fail(gc != NULL);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   rcpt_name = g_strdup_printf("@U %s", buddy->name);
@@ -3705,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));
 
@@ -3725,7 +3721,7 @@
     /* somehow, we don't have a host to connect to. Well, we need one
        to actually continue, so let's ask the user directly. */
     g_free(user);
-    purple_connection_error_reason(gc,
+    purple_connection_error(gc,
             PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
             _("A server is required to connect this account"));
     return;
@@ -3770,7 +3766,7 @@
   purple_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS);
 
   if (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL) {
-    purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+    purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
                                    _("Unable to connect"));
   }
 }
@@ -3781,7 +3777,7 @@
 
   g_return_if_fail(gc != NULL);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   /* get rid of the blist save timeout */
@@ -3795,12 +3791,12 @@
   mwSession_stop(pd->session, 0x00);
 
   /* no longer necessary */
-  gc->proto_data = NULL;
+  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 */
@@ -3986,7 +3982,7 @@
   struct mwConversation *conv;
 
   g_return_val_if_fail(gc != NULL, 0);
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   g_return_val_if_fail(pd != NULL, 0);
 
@@ -4061,7 +4057,7 @@
   gpointer t = GINT_TO_POINTER(!! state);
 
   g_return_val_if_fail(gc != NULL, 0);
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   g_return_val_if_fail(pd != NULL, 0);
 
@@ -4157,53 +4153,54 @@
   g_return_if_fail(who != NULL);
   g_return_if_fail(*who != '\0');
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   acct = purple_connection_get_account(gc);
   b = purple_find_buddy(acct, who);
   user_info = purple_notify_user_info_new();
 
   if(purple_str_has_prefix(who, "@E ")) {
-	purple_notify_user_info_add_pair(user_info, _("External User"), NULL);
+	purple_notify_user_info_add_pair_html(user_info, _("External User"), NULL);
   }
 
-  purple_notify_user_info_add_pair(user_info, _("User ID"), who);
+  purple_notify_user_info_add_pair_plaintext(user_info, _("User ID"), who);
 
   if(b) {
     guint32 type;
 
     if(purple_buddy_get_server_alias(b)) {
-		purple_notify_user_info_add_pair(user_info, _("Full Name"), purple_buddy_get_server_alias(b));
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Full Name"), purple_buddy_get_server_alias(b));
     }
 
     type = purple_blist_node_get_int((PurpleBlistNode *) b, BUDDY_KEY_CLIENT);
     if(type) {
-	  tmp = g_strdup(mw_client_name(type));
-	  if (!tmp)
+	  tmp2 = mw_client_name(type);
+	  if (tmp2) {
+		purple_notify_user_info_add_pair_plaintext(user_info, _("Last Known Client"), tmp2);
+	  } else {
 		tmp = g_strdup_printf(_("Unknown (0x%04x)<br>"), type);
-
-	  purple_notify_user_info_add_pair(user_info, _("Last Known Client"), tmp);
-
-	  g_free(tmp);
+		purple_notify_user_info_add_pair_html(user_info, _("Last Known Client"), tmp);
+	    g_free(tmp);
+	  }
     }
   }
 
   tmp = user_supports_text(pd->srvc_aware, who);
   if(tmp) {
-	purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Supports"), tmp);
 	g_free(tmp);
   }
 
   if(b) {
-	purple_notify_user_info_add_pair(user_info, _("Status"), status_text(b));
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_text(b));
 
 	/* XXX Is this adding a status message in its own section rather than with the "Status" label? */
     tmp2 = mwServiceAware_getText(pd->srvc_aware, &idb);
     if(tmp2 && g_utf8_validate(tmp2, -1, NULL)) {
-      tmp = g_markup_escape_text(tmp2, -1);
 	  purple_notify_user_info_add_section_break(user_info);
-	  purple_notify_user_info_add_pair(user_info, NULL, tmp);
-      g_free(tmp);
+	  purple_notify_user_info_add_pair_plaintext(user_info, NULL, tmp2);
     }
   }
 
@@ -4401,7 +4398,7 @@
   buddy = data->buddy;
 
   gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   if(results)
     res = results->data;
@@ -4480,9 +4477,10 @@
 
 static void mw_prpl_add_buddy(PurpleConnection *gc,
 			      PurpleBuddy *buddy,
-			      PurpleGroup *group) {
-
-  struct mwPurplePluginData *pd = gc->proto_data;
+			      PurpleGroup *group,
+			      const char *message) {
+
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   struct mwServiceResolve *srvc;
   GList *query;
   enum mwResolveFlag flags;
@@ -4527,13 +4525,14 @@
 
 static void mw_prpl_add_buddies(PurpleConnection *gc,
 				GList *buddies,
-				GList *groups) {
+				GList *groups,
+				const char *message) {
 
   struct mwPurplePluginData *pd;
   GHashTable *group_sets;
   struct mwAwareIdBlock *idbs, *idb;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   /* map PurpleGroup:GList of mwAwareIdBlock */
   group_sets = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -4584,7 +4583,7 @@
 
   GList *rem = g_list_prepend(NULL, &idb);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   group = purple_buddy_get_group(buddy);
   list = list_ensure(pd, group);
 
@@ -4631,13 +4630,13 @@
   acct = purple_connection_get_account(gc);
   g_return_if_fail(acct != NULL);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   session = pd->session;
   g_return_if_fail(session != NULL);
 
-  switch(acct->perm_deny) {
+  switch(purple_account_get_privacy_type(acct)) {
   case PURPLE_PRIVACY_DENY_USERS:
     DEBUG_INFO("PURPLE_PRIVACY_DENY_USERS\n");
     privacy_fill(&privacy, acct->deny);
@@ -4661,7 +4660,7 @@
     break;
 
   default:
-    DEBUG_INFO("acct->perm_deny is 0x%x\n", acct->perm_deny);
+    DEBUG_INFO("acct->perm_deny is 0x%x\n", purple_account_get_privacy_type(acct));
     return;
   }
 
@@ -4715,7 +4714,7 @@
   struct mwPurplePluginData *pd;
   char *c, *t;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   c = g_hash_table_lookup(components, CHAT_KEY_NAME);
   t = g_hash_table_lookup(components, CHAT_KEY_TOPIC);
@@ -4757,7 +4756,7 @@
   struct mwServiceConference *srvc;
   char *c;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   srvc = pd->srvc_conf;
 
   if(g_hash_table_lookup(components, CHAT_KEY_IS_PLACE)) {
@@ -4789,7 +4788,7 @@
   struct mwPlace *place;
   struct mwIdBlock idb = { (char *) who, NULL };
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   conf = ID_TO_CONF(pd, id);
@@ -4813,7 +4812,7 @@
   struct mwPurplePluginData *pd;
   struct mwConference *conf;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   g_return_if_fail(pd != NULL);
   conf = ID_TO_CONF(pd, id);
@@ -4849,7 +4848,7 @@
   char *msg;
   int ret;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
 
   g_return_val_if_fail(pd != NULL, 0);
   conf = ID_TO_CONF(pd, id);
@@ -4887,7 +4886,7 @@
 				const char *who,
 				const char *alias) {
 
-  struct mwPurplePluginData *pd = gc->proto_data;
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   /* it's a change to the buddy list, so we've gotta reflect that in
@@ -4905,7 +4904,7 @@
   struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
   GList *gl = g_list_prepend(NULL, &idb);
 
-  struct mwPurplePluginData *pd = gc->proto_data;
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   PurpleGroup *group;
   struct mwAwareList *list;
 
@@ -4931,7 +4930,7 @@
 				 PurpleGroup *group,
 				 GList *buddies) {
 
-  struct mwPurplePluginData *pd = gc->proto_data;
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
 
   /* it's a change in the buddy list, so we've gotta reflect that in
@@ -4951,7 +4950,7 @@
 
 
 static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) {
-  struct mwPurplePluginData *pd = gc->proto_data;
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   struct mwServiceIm *srvc;
   struct mwConversation *conv;
   struct mwIdBlock idb = { (char *) who, NULL };
@@ -4986,7 +4985,7 @@
   struct mwPurplePluginData *pd;
   struct mwAwareList *list;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_if_fail(pd != NULL);
   g_return_if_fail(pd->group_list_map != NULL);
 
@@ -5010,7 +5009,7 @@
 
   g_return_val_if_fail(gc != NULL, FALSE);
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   g_return_val_if_fail(pd != NULL, FALSE);
 
   srvc = pd->srvc_aware;
@@ -5042,12 +5041,12 @@
 
   acct = purple_xfer_get_account(xfer);
   gc = purple_account_get_connection(acct);
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   srvc = pd->srvc_ft;
 
   filename = purple_xfer_get_local_filename(xfer);
   filesize = purple_xfer_get_size(xfer);
-  idb.user = xfer->who;
+  idb.user = purple_xfer_get_remote_user(xfer);
 
   purple_xfer_update_progress(xfer);
 
@@ -5056,7 +5055,7 @@
   if(! fp) {
     char *msg = g_strdup_printf(_("Error reading file %s: \n%s\n"),
 				filename, g_strerror(errno));
-    purple_xfer_error(purple_xfer_get_type(xfer), acct, xfer->who, msg);
+    purple_xfer_error(purple_xfer_get_type(xfer), acct, purple_xfer_get_remote_user(xfer), msg);
     g_free(msg);
     return;
   }
@@ -5071,14 +5070,14 @@
 
   purple_xfer_ref(xfer);
   mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);
-  xfer->data = ft;
+  purple_xfer_set_protocol_data(xfer, ft);
 
   mwFileTransfer_offer(ft);
 }
 
 
 static void ft_outgoing_cancel(PurpleXfer *xfer) {
-  struct mwFileTransfer *ft = xfer->data;
+  struct mwFileTransfer *ft = purple_xfer_get_protocol_data(xfer);
 
   DEBUG_INFO("ft_outgoing_cancel called\n");
 
@@ -5119,6 +5118,7 @@
 
 
 static PurplePluginProtocolInfo mw_prpl_info = {
+  sizeof(PurplePluginProtocolInfo),
   OPT_PROTO_IM_IMAGE,
   NULL, /*< set in mw_plugin_init */
   NULL, /*< set in mw_plugin_init */
@@ -5159,7 +5159,6 @@
   mw_prpl_keepalive,
   NULL,
   NULL,
-  NULL,
   mw_prpl_alias_buddy,
   mw_prpl_group_buddy,
   mw_prpl_rename_group,
@@ -5184,9 +5183,6 @@
   NULL,
   NULL,
   NULL,
-  sizeof(PurplePluginProtocolInfo),
-  NULL,
-  NULL,
   NULL,
   NULL,
   NULL,
@@ -5514,7 +5510,7 @@
   enum mwResolveFlag flags;
   guint32 req;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   srvc = pd->srvc_resolve;
 
   query = g_list_prepend(NULL, (char *) name);
@@ -5639,7 +5635,7 @@
   enum mwResolveFlag flags;
   guint32 req;
 
-  pd = gc->proto_data;
+  pd = purple_connection_get_protocol_data(gc);
   srvc = pd->srvc_resolve;
 
   query = g_list_prepend(NULL, (char *) name);
--- a/libpurple/protocols/silc/buddy.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/buddy.c	Mon Oct 31 01:25:36 2011 +0000
@@ -72,7 +72,7 @@
 			   void *context)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 
 	if (!sg->conn)
 		return;
@@ -146,7 +146,7 @@
 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
 			   gboolean force_local)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcDList clients;
 	SilcClientEntry client_entry;
 	SilcClientConnectionParams params;
@@ -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));
 }
@@ -346,7 +346,7 @@
 
 	b = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(b));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	/* Find client entry */
 	clients = silc_client_get_clients_local(sg->client, sg->conn,
@@ -426,7 +426,7 @@
 static void
 silcpurple_buddy_privkey(PurpleConnection *gc, const char *name)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcPurplePrivkey p;
 	SilcDList clients;
 	SilcClientEntry client_entry;
@@ -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);
 }
@@ -554,7 +554,7 @@
 static void
 silcpurple_buddy_getkey(PurpleConnection *gc, const char *name)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcClientEntry client_entry;
@@ -618,7 +618,7 @@
 
 	b = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(b));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	pkfile = purple_blist_node_get_string(node, "public-key");
 	if (!silc_pkcs_load_public_key(pkfile, &public_key)) {
@@ -669,7 +669,7 @@
 
 void silcpurple_get_info(PurpleConnection *gc, const char *who)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcClientEntry client_entry;
@@ -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. */
@@ -1338,7 +1338,7 @@
 static void
 silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcPurpleBuddyRes r;
@@ -1396,7 +1396,7 @@
 	silc_buffer_free(attrs);
 }
 
-void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
 {
 	/* Don't add if the buddy is already on the list.
 	 *
@@ -1437,7 +1437,7 @@
 	const char *server;
 	int port;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (sg == NULL)
 		return;
 
@@ -1467,7 +1467,7 @@
 {
 	PurpleAccount *account = purple_buddy_get_account(b);
 	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcClientID *client_id = purple_buddy_get_protocol_data(b);
@@ -1533,7 +1533,7 @@
 {
 	PurpleAccount *account = purple_buddy_get_account(b);
 	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcClientID *client_id = purple_buddy_get_protocol_data(b);
@@ -1547,54 +1547,72 @@
 		return;
 
 	if (client_entry->nickname)
-		purple_notify_user_info_add_pair(user_info, _("Nickname"),
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Nickname"),
 					       client_entry->nickname);
 	if (client_entry->username && client_entry->hostname) {
 		g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname);
-		purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Username"), tmp);
 	}
 	if (client_entry->mode) {
 		memset(tmp, 0, sizeof(tmp));
 		silcpurple_get_umode_string(client_entry->mode,
 					  tmp, sizeof(tmp) - strlen(tmp));
-		purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
+		purple_notify_user_info_add_pair_plaintext(user_info, _("User Modes"), tmp);
 	}
 
 	silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
 
 	if (statusstr) {
-		purple_notify_user_info_add_pair(user_info, _("Message"), statusstr);
+		/* TODO: Check whether it's correct to call add_pair_html,
+		         or if we should be using add_pair_plaintext */
+		purple_notify_user_info_add_pair_html(user_info, _("Message"), statusstr);
 		g_free(statusstr);
 	}
 
 	if (full) {
 		if (moodstr) {
-			purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr);
 			g_free(moodstr);
 		}
 
 		if (contactstr) {
-			purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr);
 			g_free(contactstr);
 		}
 
 		if (langstr) {
-			purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr);
 			g_free(langstr);
 		}
 
 		if (devicestr) {
-			purple_notify_user_info_add_pair(user_info, _("Device"), devicestr);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr);
 			g_free(devicestr);
 		}
 
 		if (tzstr) {
-			purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr);
 			g_free(tzstr);
 		}
 
 		if (geostr) {
-			purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr);
+			/* TODO: Check whether it's correct to call add_pair_html,
+			         or if we should be using add_pair_plaintext */
+			purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr);
 			g_free(geostr);
 		}
 	}
@@ -1611,7 +1629,7 @@
 
 	b = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(b));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	/* Call KILL */
 	silc_client_command_call(sg->client, sg->conn, NULL, "KILL",
@@ -1635,7 +1653,7 @@
 {
 	PurpleAccount *account = purple_buddy_get_account(buddy);
 	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClientConnection conn = sg->conn;
 	const char *pkfile = NULL;
 	SilcClientEntry client_entry = NULL;
@@ -1701,7 +1719,7 @@
 
 void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcMime mime;
--- a/libpurple/protocols/silc/chat.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/chat.c	Mon Oct 31 01:25:36 2011 +0000
@@ -91,7 +91,7 @@
 static void
 silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	const char *chname;
 	char tmp[256], *tmp2;
 	GString *s;
@@ -500,7 +500,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -587,7 +587,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	p = silc_calloc(1, sizeof(*p));
 	if (!p)
@@ -637,7 +637,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -656,7 +656,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (!sg->conn)
 		return;
@@ -733,7 +733,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (!sg->conn)
 		return;
@@ -768,7 +768,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -786,7 +786,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -804,7 +804,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -822,7 +822,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -840,7 +840,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -858,7 +858,7 @@
 
 	chat = (PurpleChat *) node;
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
 				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
@@ -882,7 +882,7 @@
 {
 	GHashTable *components = purple_chat_get_components(chat);
 	PurpleConnection *gc = purple_account_get_connection(purple_chat_get_account(chat));
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClientConnection conn = sg->conn;
 	const char *chname = NULL;
 	SilcChannelEntry channel = NULL;
@@ -1020,7 +1020,7 @@
 
 void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	const char *channel, *passphrase, *parentch;
@@ -1103,7 +1103,7 @@
 void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg,
 			    const char *name)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcHashTableList htl;
@@ -1148,7 +1148,7 @@
 
 void silcpurple_chat_leave(PurpleConnection *gc, int id)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcHashTableList htl;
@@ -1218,7 +1218,7 @@
 int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg,
 			 PurpleMessageFlags msgflags)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcHashTableList htl;
@@ -1340,7 +1340,7 @@
 
 void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcHashTableList htl;
@@ -1384,7 +1384,7 @@
 
 PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	GList *fields = NULL;
@@ -1419,12 +1419,13 @@
 
 void silcpurple_roomlist_cancel(PurpleRoomlist *list)
 {
-	PurpleConnection *gc = purple_account_get_connection(list->account);
+	PurpleAccount *account = purple_roomlist_get_account(list);
+	PurpleConnection *gc = purple_account_get_connection(account);
 	SilcPurple sg;
 
 	if (!gc)
 		return;
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	purple_roomlist_set_in_progress(list, FALSE);
 	if (sg->roomlist == list) {
--- a/libpurple/protocols/silc/ft.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/ft.c	Mon Oct 31 01:25:36 2011 +0000
@@ -76,7 +76,7 @@
 
 	if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) {
 		/* All started sessions terminate here */
-		xfer->xfer->data = NULL;
+		purple_xfer_set_protocol_data(xfer->xfer, NULL);
 		purple_xfer_unref(xfer->xfer);
 		silc_free(xfer);
 		return;
@@ -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;
@@ -132,8 +132,7 @@
 	if (!offset && filesize)
 		purple_xfer_set_size(xfer->xfer, filesize);
 	if (offset && filesize) {
-		xfer->xfer->bytes_sent = offset;
-		xfer->xfer->bytes_remaining = filesize - offset;
+		purple_xfer_set_bytes_sent(xfer->xfer, offset);
 	}
 	purple_xfer_update_progress(xfer->xfer);
 
@@ -150,12 +149,12 @@
 static void
 silcpurple_ftp_cancel(PurpleXfer *x)
 {
-	SilcPurpleXfer xfer = x->data;
+	SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x);
 
 	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);
 }
@@ -163,7 +162,7 @@
 static void
 silcpurple_ftp_ask_name_cancel(PurpleXfer *x)
 {
-	SilcPurpleXfer xfer = x->data;
+	SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x);
 
 	if (!xfer)
 		return;
@@ -176,7 +175,7 @@
 static void
 silcpurple_ftp_ask_name_ok(PurpleXfer *x)
 {
-	SilcPurpleXfer xfer = x->data;
+	SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x);
 	const char *name;
 
 	if (!xfer)
@@ -212,7 +211,7 @@
 static void
 silcpurple_ftp_request_result(PurpleXfer *x)
 {
-	SilcPurpleXfer xfer = x->data;
+	SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x);
 	SilcClientFileError status;
 	PurpleConnection *gc = xfer->sg->gc;
 	SilcClientConnectionParams params;
@@ -310,7 +309,7 @@
 			    const char *hostname, SilcUInt16 port)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcPurpleXfer xfer;
 
 	xfer = silc_calloc(1, sizeof(*xfer));
@@ -337,7 +336,7 @@
 	purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel);
 	xfer->xfer->remote_ip = g_strdup(hostname);
 	xfer->xfer->remote_port = port;
-	xfer->xfer->data = xfer;
+	purple_xfer_set_protocol_data(xfer->xfer, xfer);
 
 	/* File transfer request */
 	purple_xfer_request(xfer->xfer);
@@ -346,7 +345,7 @@
 static void
 silcpurple_ftp_send_cancel(PurpleXfer *x)
 {
-	SilcPurpleXfer xfer = x->data;
+	SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x);
 
 	if (!xfer)
 		return;
@@ -358,7 +357,7 @@
 static void
 silcpurple_ftp_send(PurpleXfer *x)
 {
-	SilcPurpleXfer xfer = x->data;
+	SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x);
 	const char *name;
 	char *local_ip = NULL, *remote_ip = NULL;
 	gboolean local = TRUE;
@@ -435,7 +434,7 @@
 
 PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcDList clients;
@@ -467,7 +466,7 @@
 	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send);
 	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied);
 	purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel);
-	xfer->xfer->data = xfer;
+	purple_xfer_set_protocol_data(xfer->xfer, xfer);
 
 	silc_free(clients);
 
--- a/libpurple/protocols/silc/ops.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/ops.c	Mon Oct 31 01:25:36 2011 +0000
@@ -72,7 +72,7 @@
 		gc = client->application;
 
 	if (gc != NULL)
-		purple_connection_error_reason(gc, reason, tmp);
+		purple_connection_error(gc, reason, tmp);
 	else
 		purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp);
 }
@@ -88,7 +88,7 @@
 			gboolean recursive)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	const char *type;
 	const unsigned char *data;
 	SilcUInt32 data_len;
@@ -264,7 +264,7 @@
 		     SilcUInt32 message_len)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleConversation *convo = NULL;
 	char *msg, *tmp;
 
@@ -354,7 +354,7 @@
 		     SilcUInt32 message_len)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleConversation *convo = NULL;
 	char *msg, *tmp;
 
@@ -438,7 +438,7 @@
 {
 	va_list va;
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleConversation *convo;
 	SilcClientEntry client_entry, client_entry2;
@@ -948,7 +948,7 @@
 	     SilcUInt32 argc, unsigned char **argv)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 
 	switch (command) {
 
@@ -1085,7 +1085,7 @@
 		   SilcStatus error, va_list ap)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleConversation *convo;
 
 	switch (command) {
@@ -1169,7 +1169,7 @@
 			SilcUInt32 idle, *user_modes;
 			SilcDList channels;
 			SilcClientEntry client_entry;
-			char tmp[1024], *tmp2;
+			char tmp[1024];
 			char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
 			PurpleNotifyUserInfo *user_info;
 
@@ -1191,71 +1191,80 @@
 			user_modes = va_arg(ap, SilcUInt32 *);
 
 			user_info = purple_notify_user_info_new();
-			tmp2 = g_markup_escape_text(client_entry->nickname, -1);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2);
-			g_free(tmp2);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), client_entry->nickname);
 			if (client_entry->realname) {
-				tmp2 = g_markup_escape_text(client_entry->realname, -1);
-				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2);
-				g_free(tmp2);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), client_entry->realname);
 			}
-			tmp2 = g_markup_escape_text(client_entry->username, -1);
 			if (*client_entry->hostname) {
-				gchar *tmp3;
-				tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname);
-				purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
-				g_free(tmp3);
+				gchar *tmp2;
+				tmp2 = g_strdup_printf("%s@%s", client_entry->username, client_entry->hostname);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp2);
+				g_free(tmp2);
 			} else
-				purple_notify_user_info_add_pair(user_info, _("Username"), tmp2);
-			g_free(tmp2);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), client_entry->username);
 
 			if (client_entry->mode) {
 				memset(tmp, 0, sizeof(tmp));
 				silcpurple_get_umode_string(client_entry->mode,
 							    tmp, sizeof(tmp) - strlen(tmp));
-				purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("User Modes"), tmp);
 			}
 
 			silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
 			if (moodstr) {
-				purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr);
 				g_free(moodstr);
 			}
 
 			if (statusstr) {
-				tmp2 = g_markup_escape_text(statusstr, -1);
-				purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Status Text"), statusstr);
 				g_free(statusstr);
-				g_free(tmp2);
 			}
 
 			if (contactstr) {
-				purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr);
 				g_free(contactstr);
 			}
 
 			if (langstr) {
-				purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr);
 				g_free(langstr);
 			}
 
 			if (devicestr) {
-				purple_notify_user_info_add_pair(user_info, _("Device"), devicestr);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr);
 				g_free(devicestr);
 			}
 
 			if (tzstr) {
-				purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr);
 				g_free(tzstr);
 			}
 
 			if (geostr) {
-				purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr);
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr);
 				g_free(geostr);
 			}
 
-			if (*client_entry->server)
-				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
+			if (*client_entry->server) {
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server);
+			}
 
 			if (channels && user_modes) {
 				SilcChannelPayload entry;
@@ -1273,9 +1282,7 @@
 					silc_strncat(tmp, sizeof(tmp) - 1, "  ", 1);
 					silc_free(m);
 				}
-				tmp2 = g_markup_escape_text(tmp, -1);
-				purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2);
-				g_free(tmp2);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), tmp);
 			}
 
 			if (client_entry->public_key) {
@@ -1286,8 +1293,8 @@
 				if (pk) {
 					fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
 					babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-					purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
-					purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint);
 					silc_free(fingerprint);
 					silc_free(babbleprint);
 					silc_free(pk);
@@ -1311,7 +1318,7 @@
 	case SILC_COMMAND_WHOWAS:
 		{
 			SilcClientEntry client_entry;
-			char *nickname, *realname, *username, *tmp;
+			char *nickname, *realname, *username;
 			PurpleNotifyUserInfo *user_info;
 
 			if (status != SILC_STATUS_OK) {
@@ -1329,27 +1336,23 @@
 				break;
 
 			user_info = purple_notify_user_info_new();
-			tmp = g_markup_escape_text(nickname, -1);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
-			g_free(tmp);
-			if (realname) {
-				tmp = g_markup_escape_text(realname, -1);
-				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp);
-				g_free(tmp);
-			}
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), nickname);
+			if (realname)
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), realname);
 			if (username) {
-				tmp = g_markup_escape_text(username, -1);
 				if (client_entry && *client_entry->hostname) {
-					gchar *tmp3;
-					tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname);
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
-					g_free(tmp3);
+					gchar *tmp;
+					tmp = g_strdup_printf("%s@%s", username, client_entry->hostname);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp);
+					g_free(tmp);
 				} else
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
-				g_free(tmp);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), username);
 			}
-			if (client_entry && *client_entry->server)
-				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
+			if (client_entry && *client_entry->server) {
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server);
+			}
 
 
 			if (client_entry && client_entry->public_key) {
@@ -1360,8 +1363,8 @@
 				if (pk) {
 					fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
 					babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-					purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
-					purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint);
 					silc_free(fingerprint);
 					silc_free(babbleprint);
 					silc_free(pk);
@@ -1728,7 +1731,7 @@
 		     SilcGetAuthMeth completion, void *context)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcPurpleAskPassphrase internal;
 	const char *password;
 
@@ -1779,7 +1782,7 @@
 		       SilcVerifyPublicKey completion, void *context)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 
 	if (!sg->conn && (conn_type == SILC_CONN_SERVER ||
 			  conn_type == SILC_CONN_ROUTER)) {
--- a/libpurple/protocols/silc/pk.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/pk.c	Mon Oct 31 01:25:36 2011 +0000
@@ -79,7 +79,7 @@
 static void silcpurple_verify_details(PublicKeyVerify verify, gint id)
 {
 	PurpleConnection *gc = verify->client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 
 	silcpurple_show_public_key(sg, verify->entity_name, verify->public_key,
 				   G_CALLBACK(silcpurple_verify_details_cb),
--- a/libpurple/protocols/silc/silc.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/silc.c	Mon Oct 31 01:25:36 2011 +0000
@@ -78,7 +78,7 @@
 	const char *state;
 
 	if (gc != NULL)
-		sg = gc->proto_data;
+		sg = purple_connection_get_protocol_data(gc);
 
 	if (status == NULL)
 		return;
@@ -125,7 +125,7 @@
 static void
 silcpurple_keepalive(PurpleConnection *gc)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0,
 			 NULL, 0);
 }
@@ -180,7 +180,7 @@
 {
 	SilcClient client = (SilcClient)context;
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcPurpleTask ptask = NULL;
 
 	if (added) {
@@ -252,7 +252,7 @@
 	struct utsname u;
 #endif
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	switch (status) {
 	case SILC_CLIENT_CONN_SUCCESS:
@@ -316,7 +316,7 @@
 
 		/* Close the connection */
 		if (!sg->detaching)
-		  purple_connection_error_reason(gc,
+		  purple_connection_error(gc,
 		                                 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                                 _("Disconnected by server"));
 		else
@@ -325,30 +325,30 @@
 		break;
 
 	case SILC_CLIENT_CONN_ERROR:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                             _("Error connecting to SILC Server"));
 		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_KE:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
 		                             _("Key Exchange failed"));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_AUTH:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 		                             _("Authentication failed"));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_RESUME:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Resuming detached session failed. "
 		                               "Press Reconnect to create new connection."));
 		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                             _("Connection timed out"));
 		break;
 	}
@@ -367,16 +367,16 @@
 	SilcClientConnectionParams params;
 	const char *dfile;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (status != SILC_SOCKET_OK) {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Connection failed"));
 		silc_pkcs_public_key_free(sg->public_key);
 		silc_pkcs_private_key_free(sg->private_key);
 		silc_free(sg);
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		return;
 	}
 
@@ -415,15 +415,15 @@
 
 	g_return_if_fail(gc != NULL);
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                             _("Connection failed"));
 		silc_pkcs_public_key_free(sg->public_key);
 		silc_pkcs_private_key_free(sg->private_key);
 		silc_free(sg);
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		return;
 	}
 
@@ -447,9 +447,9 @@
 				 purple_account_get_int(account, "port", 706),
 				 silcpurple_login_connected, gc) == NULL)
 	{
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                             _("Unable to connect"));
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		silc_free(sg);
 		return;
 	}
@@ -457,7 +457,7 @@
 
 static void silcpurple_got_password_cb(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	SilcPurple sg = (SilcPurple)gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	char pkd[256], prd[256];
 	const char *password;
@@ -473,7 +473,7 @@
 	if (!password || !*password)
 	{
 		purple_notify_error(gc, NULL, _("Password is required to sign on."), NULL);
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		silc_free(sg);
 		return;
 	}
@@ -490,9 +490,9 @@
 				(char *)purple_account_get_string(account, "private-key", prd),
 				password,
 				&sg->public_key, &sg->private_key)) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Unable to load SILC key pair"));
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		silc_free(sg);
 		return;
 	}
@@ -505,10 +505,10 @@
 	/* The password prompt dialog doesn't get disposed if the account disconnects */
 	if (!PURPLE_CONNECTION_IS_VALID(gc))
 		return;
-	sg = gc->proto_data;
-	purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+	sg = purple_connection_get_protocol_data(gc);
+	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 			_("Unable to load SILC key pair"));
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 	silc_free(sg);
 }
 
@@ -528,16 +528,16 @@
 	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),
 											G_CALLBACK(silcpurple_no_password_cb), gc);
 			return;
 		}
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Unable to load SILC key pair"));
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		silc_free(sg);
 		return;
 	}
@@ -555,10 +555,10 @@
 	char *username, *hostname, *realname, **up;
 	int i;
 
-	gc = account->gc;
+	gc = purple_account_get_connection(account);
 	if (!gc)
 		return;
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 
 	memset(&params, 0, sizeof(params));
 	strcat(params.nickname_format, "%n#a");
@@ -566,7 +566,7 @@
 	/* Allocate SILC client */
 	client = silc_client_alloc(&ops, &params, gc, NULL);
 	if (!client) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Out of memory"));
 		return;
 	}
@@ -612,14 +612,14 @@
 	sg->client = client;
 	sg->gc = gc;
 	sg->account = account;
-	gc->proto_data = sg;
+	purple_connection_set_protocol_data(gc, sg);
 
 	/* Init SILC client */
 	if (!silc_client_init(client, username, hostname, realname,
 			      silcpurple_running, sg)) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Unable to initialize SILC protocol"));
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		silc_free(sg);
 		silc_free(hostname);
 		g_free(username);
@@ -630,9 +630,9 @@
 
 	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
 	if (!silcpurple_check_silc_dir(gc)) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 		                             _("Error loading SILC key pair"));
-		gc->proto_data = NULL;
+		purple_connection_set_protocol_data(gc, NULL);
 		silc_free(sg);
 		return;
 	}
@@ -669,7 +669,7 @@
 static void
 silcpurple_close(PurpleConnection *gc)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 #if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
 	SilcPurpleTask task;
 #endif /* __SILC_TOOLKIT_VERSION */
@@ -733,7 +733,7 @@
 static void
 silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	PurpleRequestField *f;
@@ -744,7 +744,7 @@
 	SilcVCardStruct vcard;
 	const char *val;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -905,7 +905,7 @@
 silcpurple_attrs(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	PurpleRequestFields *fields;
@@ -922,7 +922,7 @@
 	gboolean device = TRUE;
 	char status[1024], tz[16];
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -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
@@ -1072,7 +1072,7 @@
 
 	if (!gc)
 		return;
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -1090,7 +1090,7 @@
 
 	if (!gc)
 		return;
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -1125,7 +1125,7 @@
 	int keylen = SILCPURPLE_DEF_PKCS_LEN;
 	SilcPublicKey public_key;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -1208,7 +1208,7 @@
 silcpurple_create_keypair(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *g;
 	PurpleRequestField *f;
@@ -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 : "");
 }
@@ -1356,7 +1356,7 @@
 			    void *context)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcPurpleIM im = context;
 	PurpleConversation *convo;
 	char tmp[256];
@@ -1433,7 +1433,7 @@
 silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message,
 		   PurpleMessageFlags flags)
 {
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	SilcDList clients;
@@ -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), gc->account->username, 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,12 +1713,12 @@
 	SilcPurple sg;
 	char *tmp;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1742,12 +1742,12 @@
 	PurpleConnection *gc;
 	SilcPurple sg;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1767,12 +1767,12 @@
 	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 || gc->proto_data == NULL)
+	if (gc == NULL || !args || purple_connection_get_protocol_data(gc) == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (args[0])
 		chname = args[0];
@@ -1818,12 +1818,12 @@
 	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;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1850,12 +1850,12 @@
 	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;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -1887,12 +1887,12 @@
 	PurpleConnection *gc;
 	SilcPurple sg;
 
-	gc = purple_conversation_get_gc(conv);
+	gc = purple_conversation_get_connection(conv);
 
 	if (gc == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
@@ -2050,6 +2050,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
 	OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE |
 	OPT_PROTO_SLASH_COMMANDS_NATIVE,
@@ -2092,7 +2093,6 @@
 	silcpurple_keepalive,			/* keepalive */
 	NULL,					/* register_user */
 	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
 	NULL,					/* alias_buddy */
 	NULL,					/* group_buddy */
 	NULL,					/* rename_group */
@@ -2117,15 +2117,12 @@
 	NULL,				        /* unregister_user */
 	NULL,				        /* send_attention */
 	NULL,				        /* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,				        /* get_account_text_table */
 	NULL,				        /* initiate_media */
 	NULL,				        /* get_media_caps */
 	NULL,				        /* get_moods */
 	NULL,				        /* set_public_alias */
-	NULL,				        /* get_public_alias */
-	NULL,				        /* add_buddy_with_invite */
-	NULL				        /* add_buddies_with_invite */
+	NULL				        /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/silc/silcpurple.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/silcpurple.h	Mon Oct 31 01:25:36 2011 +0000
@@ -105,7 +105,7 @@
 				  SilcVerifyPublicKey completion,
 				  void *context);
 GList *silcpurple_buddy_menu(PurpleBuddy *buddy);
-void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
+void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message);
 void silcpurple_send_buddylist(PurpleConnection *gc);
 void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
 void silcpurple_buddy_keyagr_request(SilcClient client,
--- a/libpurple/protocols/silc/util.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/util.c	Mon Oct 31 01:25:36 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,10 +210,9 @@
 						  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_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				                             _("Unable to create SILC key pair"));
 				return FALSE;
 			}
@@ -253,10 +252,9 @@
 						  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_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				                             _("Unable to create SILC key pair"));
 				return FALSE;
 			}
--- a/libpurple/protocols/silc/wb.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/silc/wb.c	Mon Oct 31 01:25:36 2011 +0000
@@ -105,7 +105,7 @@
 
 PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry)
 {
-        SilcClientConnection conn;
+	SilcClientConnection conn;
 	PurpleWhiteboard *wb;
 	SilcPurpleWb wbs;
 
@@ -116,7 +116,7 @@
 	if (!wb)
 		return NULL;
 
-	if (!wb->proto_data) {
+	if (!purple_whiteboard_get_protocol_data(wb)) {
 		wbs = silc_calloc(1, sizeof(*wbs));
 		if (!wbs)
 			return NULL;
@@ -126,7 +126,7 @@
 		wbs->height = SILCPURPLE_WB_HEIGHT;
 		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
 		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
-		wb->proto_data = wbs;
+		purple_whiteboard_set_protocol_data(wb, wbs);
 
 		/* Start the whiteboard */
 		purple_whiteboard_start(wb);
@@ -147,7 +147,7 @@
 	if (!wb)
 		return NULL;
 
-	if (!wb->proto_data) {
+	if (!purple_whiteboard_get_protocol_data(wb)) {
 		wbs = silc_calloc(1, sizeof(*wbs));
 		if (!wbs)
 			return NULL;
@@ -157,7 +157,7 @@
 		wbs->height = SILCPURPLE_WB_HEIGHT;
 		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
 		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
-		wb->proto_data = wbs;
+		purple_whiteboard_set_protocol_data(wb, wbs);
 
 		/* Start the whiteboard */
 		purple_whiteboard_start(wb);
@@ -168,9 +168,10 @@
 }
 
 static void
-silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb,
+silcpurple_wb_parse(PurpleWhiteboard *wb,
 		  unsigned char *message, SilcUInt32 message_len)
 {
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	SilcUInt8 command;
 	SilcUInt16 width, height, brush_size;
 	SilcUInt32 brush_color, x, y, dx, dy;
@@ -238,15 +239,15 @@
 {
 	PurpleWhiteboard *wb;
 
-        if (id != 1)
-                goto out;
+	if (id != 1)
+		goto out;
 
 	if (!req->channel)
 		wb = silcpurple_wb_init(req->sg, req->sender);
 	else
 		wb = silcpurple_wb_init_ch(req->sg, req->channel);
 
-	silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len);
+	silcpurple_wb_parse(wb, req->message, req->message_len);
 
   out:
 	silc_free(req->message);
@@ -264,7 +265,7 @@
 	SilcPurple sg;
 
 	gc = client->application;
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	/* Open whiteboard automatically if requested */
 	if (purple_account_get_bool(sg->account, "open-wb", FALSE)) {
@@ -275,7 +276,7 @@
 		else
 			wb = silcpurple_wb_init_ch(sg, channel);
 
-		silcpurple_wb_parse(wb->proto_data, wb,
+		silcpurple_wb_parse(wb,
 				    (unsigned char *)message,
 				    message_len);
 		return;
@@ -318,12 +319,11 @@
 			 SilcUInt32 message_len)
 {
 	SilcPurple sg;
-        PurpleConnection *gc;
+	PurpleConnection *gc;
 	PurpleWhiteboard *wb;
-	SilcPurpleWb wbs;
 
 	gc = client->application;
-        sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	wb = purple_whiteboard_get_session(sg->account, sender->nickname);
 	if (!wb) {
@@ -333,8 +333,7 @@
 		return;
 	}
 
-	wbs = wb->proto_data;
-	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);
+	silcpurple_wb_parse(wb, (unsigned char *)message, message_len);
 }
 
 /* Process incoming whiteboard message on channel */
@@ -347,12 +346,11 @@
 			    SilcUInt32 message_len)
 {
 	SilcPurple sg;
-        PurpleConnection *gc;
+	PurpleConnection *gc;
 	PurpleWhiteboard *wb;
-	SilcPurpleWb wbs;
 
 	gc = client->application;
-        sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);
 	if (!wb) {
@@ -362,25 +360,24 @@
 		return;
 	}
 
-	wbs = wb->proto_data;
-	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);
+	silcpurple_wb_parse(wb, (unsigned char *)message, message_len);
 }
 
 /* Send whiteboard message */
 
 void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list)
 {
-	SilcPurpleWb wbs = wb->proto_data;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	SilcBuffer packet;
 	GList *list;
 	int len;
-        PurpleConnection *gc;
-        SilcPurple sg;
+	PurpleConnection *gc;
+	SilcPurple sg;
 
 	g_return_if_fail(draw_list);
-	gc = purple_account_get_connection(wb->account);
+	gc = purple_account_get_connection(purple_whiteboard_get_account(wb));
 	g_return_if_fail(gc);
- 	sg = gc->proto_data;
+ 	sg = purple_connection_get_protocol_data(gc);
 	g_return_if_fail(sg);
 
 	len = SILCPURPLE_WB_HEADER;
@@ -435,20 +432,22 @@
 
 void silcpurple_wb_end(PurpleWhiteboard *wb)
 {
-	silc_free(wb->proto_data);
-	wb->proto_data = NULL;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
+
+	silc_free(wbs);
+	purple_whiteboard_set_protocol_data(wb, NULL);
 }
 
 void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
 {
-	SilcPurpleWb wbs = wb->proto_data;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	*width = wbs->width;
 	*height = wbs->height;
 }
 
 void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height)
 {
-	SilcPurpleWb wbs = wb->proto_data;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX :
 			width;
 	wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX :
@@ -460,14 +459,14 @@
 
 void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
 {
-	SilcPurpleWb wbs = wb->proto_data;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	*size = wbs->brush_size;
 	*color = wbs->brush_color;
 }
 
 void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color)
 {
-	SilcPurpleWb wbs = wb->proto_data;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	wbs->brush_size = size;
 	wbs->brush_color = color;
 
@@ -477,15 +476,15 @@
 
 void silcpurple_wb_clear(PurpleWhiteboard *wb)
 {
-	SilcPurpleWb wbs = wb->proto_data;
+	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
 	SilcBuffer packet;
 	int len;
-        PurpleConnection *gc;
-        SilcPurple sg;
+	PurpleConnection *gc;
+	SilcPurple sg;
 
-	gc = purple_account_get_connection(wb->account);
+	gc = purple_account_get_connection(purple_whiteboard_get_account(wb));
 	g_return_if_fail(gc);
- 	sg = gc->proto_data;
+ 	sg = purple_connection_get_protocol_data(gc);
 	g_return_if_fail(sg);
 
 	len = SILCPURPLE_WB_HEADER;
--- a/libpurple/protocols/silc10/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-EXTRA_DIST = \
-	Makefile.mingw \
-	README \
-	TODO
-
-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-SILCSOURCES = silc.c silcpurple.h buddy.c chat.c ft.c ops.c pk.c util.c wb.c wb.h
-
-AM_CFLAGS = $(st)
-
-libsilcpurple_la_LDFLAGS = -module -avoid-version
-
-if STATIC_SILC
-
-st = -DPURPLE_STATIC_PRPL $(SILC_CFLAGS)
-noinst_LTLIBRARIES       = libsilcpurple.la
-libsilcpurple_la_SOURCES = $(SILCSOURCES)
-libsilcpurple_la_CFLAGS  = $(AM_CFLAGS)
-libsilcpurple_la_LIBADD  = $(SILC_LIBS)
-
-else
-
-st = $(SILC_CFLAGS)
-pkg_LTLIBRARIES          = libsilcpurple.la
-libsilcpurple_la_SOURCES = $(SILCSOURCES)
-libsilcpurple_la_LIBADD  = $(GLIB_LIBS) $(SILC_LIBS)
-
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(SILC_CFLAGS)
--- a/libpurple/protocols/silc10/Makefile.mingw	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Makefile.mingw
-#
-# Description: Makefile for win32 (mingw) version of libsilc protocol plugin
-#
-
-PIDGIN_TREE_TOP := ../../..
-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-
-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
-
-TARGET = libsilc
-NEEDED_DLLS =		$(SILC_TOOLKIT)/lib/silc.dll \
-			$(SILC_TOOLKIT)/lib/silcclient.dll
-TYPE = PLUGIN
-
-# Static or Plugin...
-ifeq ($(TYPE),STATIC)
-  DEFINES += -DSTATIC
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
-else
-ifeq ($(TYPE),PLUGIN)
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
-endif
-endif
-
-##
-## INCLUDE PATHS
-##
-INCLUDE_PATHS +=	-I. \
-			-I$(GTK_TOP)/include \
-			-I$(GTK_TOP)/include/glib-2.0 \
-			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(PURPLE_TOP) \
-			-I$(PURPLE_TOP)/win32 \
-			-I$(PIDGIN_TREE_TOP) \
-			-I$(SILC_TOOLKIT)/include
-
-LIB_PATHS +=		-L$(GTK_TOP)/lib \
-			-L$(PURPLE_TOP) \
-			-L$(SILC_TOOLKIT)/lib
-
-##
-##  SOURCES, OBJECTS
-##
-C_SRC =			silc.c \
-			buddy.c \
-			chat.c \
-			ft.c \
-			ops.c \
-			pk.c \
-			util.c \
-			wb.c
-
-OBJECTS = $(C_SRC:%.c=%.o)
-
-##
-## LIBRARIES
-##
-LIBS = \
-			-lglib-2.0 \
-			-lws2_32 \
-			-lintl \
-			-lpurple \
-			-lsilc \
-			-lsilcclient
-
-include $(PIDGIN_COMMON_RULES)
-
-##
-## TARGET DEFINITIONS
-##
-.PHONY: all install clean
-
-all: $(TARGET).dll
-
-install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR)
-	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-	cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
-
-$(OBJECTS): $(PURPLE_CONFIG_H)
-
-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll
-
-##
-## CLEAN RULES
-##
-clean:
-	rm -f $(OBJECTS)
-	rm -f $(TARGET).dll
-
-include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/silc10/README	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-SILC Purple Plugin
-==================
-
-This is the Purple protocol plugin of the protocol called Secure Internet
-Live Conferencing (SILC).  The implementation will use the SILC Toolkit, 
-freely available from the http://silcnet.org/ site, for the actual SILC 
-protocol implementation.
-
-To include SILC into Purple, one needs to first compile and install 
-the SILC Toolkit.  It is done as follows:
-
-	./configure --enable-shared
-	make
-	make install
-
-This will compile shared libraries of the SILC Toolkit.  If the --prefix 
-is not given to ./configure, the binaries are installed into the 
-/usr/local/silc directory.
-
-Once the Toolkit is installed one needs to tell Purple's ./configure
-script where the SILC Toolkit is located.  It is done as simply as:
-
-	./configure
-
-if pkg-config is installed in your system.  If it is isn't it's done as:
-
-	./configure --with-silc-libs=/path/to/silc/lib
-		    --with-silc-includes=/path/to/silc/include
-
-If the SILC Toolkit cannot be found then the SILC protocol plugin will
-not be compiled.
--- a/libpurple/protocols/silc10/TODO	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-Features TODO (maybe)
-=====================
-
-Preferences
-	- Add joined channels to buddy list automatically (during
-	  session)
-	- Add joined channels to buddy list automatically permanently
-
--- a/libpurple/protocols/silc10/buddy.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1748 +0,0 @@
-/*
-
-  silcpurple_buddy.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-#include "wb.h"
-
-/***************************** Key Agreement *********************************/
-
-static void
-silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data);
-
-static void
-silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
-			 			 gboolean force_local);
-
-typedef struct {
-	char *nick;
-	PurpleConnection *gc;
-} *SilcPurpleResolve;
-
-static void
-silcpurple_buddy_keyagr_resolved(SilcClient client,
-			       SilcClientConnection conn,
-			       SilcClientEntry *clients,
-			       SilcUInt32 clients_count,
-			       void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurpleResolve r = context;
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"), r->nick);
-		purple_notify_error(gc, _("Key Agreement"),
-				  _("Cannot perform the key agreement"), tmp);
-		silc_free(r->nick);
-		silc_free(r);
-		return;
-	}
-
-	silcpurple_buddy_keyagr_do(gc, r->nick, FALSE);
-	silc_free(r->nick);
-	silc_free(r);
-}
-
-typedef struct {
-	gboolean responder;
-} *SilcPurpleKeyAgr;
-
-static void
-silcpurple_buddy_keyagr_cb(SilcClient client,
-			 SilcClientConnection conn,
-			 SilcClientEntry client_entry,
-			 SilcKeyAgreementStatus status,
-			 SilcSKEKeyMaterial *key,
-			 void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	SilcPurpleKeyAgr a = context;
-
-	if (!sg->conn)
-		return;
-
-	switch (status) {
-	case SILC_KEY_AGREEMENT_OK:
-		{
-			PurpleConversation *convo;
-			char tmp[128];
-
-			/* Set the private key for this client */
-			silc_client_del_private_message_key(client, conn, client_entry);
-			silc_client_add_private_message_key_ske(client, conn, client_entry,
-								NULL, NULL, key, a->responder);
-			silc_ske_free_key_material(key);
-
-
-			/* Open IM window */
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-									client_entry->nickname, sg->account);
-			if (convo) {
-				/* we don't have windows in the core anymore...but we may want to
-				 * provide some method for asking the UI to show the window
-				purple_conv_window_show(purple_conversation_get_window(convo));
-				 */
-			} else {
-				convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account,
-							      client_entry->nickname);
-			}
-			g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname);
-			purple_conversation_set_title(convo, tmp);
-		}
-		break;
-
-	case SILC_KEY_AGREEMENT_ERROR:
-		purple_notify_error(gc, _("Key Agreement"),
-				  _("Error occurred during key agreement"), NULL);
-		break;
-
-	case SILC_KEY_AGREEMENT_FAILURE:
-		purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL);
-		break;
-
-	case SILC_KEY_AGREEMENT_TIMEOUT:
-		purple_notify_error(gc, _("Key Agreement"),
-				  _("Timeout during key agreement"), NULL);
-		break;
-
-	case SILC_KEY_AGREEMENT_ABORTED:
-		purple_notify_error(gc, _("Key Agreement"),
-				  _("Key agreement was aborted"), NULL);
-		break;
-
-	case SILC_KEY_AGREEMENT_ALREADY_STARTED:
-		purple_notify_error(gc, _("Key Agreement"),
-				  _("Key agreement is already started"), NULL);
-		break;
-
-	case SILC_KEY_AGREEMENT_SELF_DENIED:
-		purple_notify_error(gc, _("Key Agreement"),
-				  _("Key agreement cannot be started with yourself"),
-				  NULL);
-		break;
-
-	default:
-		break;
-	}
-
-	silc_free(a);
-}
-
-static void
-silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
-			 gboolean force_local)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
-	char *local_ip = NULL, *remote_ip = NULL;
-	gboolean local = TRUE;
-	char *nickname;
-	SilcPurpleKeyAgr a;
-
-	if (!sg->conn || !name)
-		return;
-
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name,
-						&clients_count);
-	if (!clients) {
-		/* Resolve unknown user */
-		SilcPurpleResolve r = silc_calloc(1, sizeof(*r));
-		if (!r)
-			return;
-		r->nick = g_strdup(name);
-		r->gc = gc;
-		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,
-					silcpurple_buddy_keyagr_resolved, r);
-		silc_free(nickname);
-		return;
-	}
-
-	/* Resolve the local IP from the outgoing socket connection.  We resolve
-	   it to check whether we have a private range IP address or public IP
-	   address.  If we have public then we will assume that we are not behind
-	   NAT and will provide automatically the point of connection to the
-	   agreement.  If we have private range address we assume that we are
-	   behind NAT and we let the responder provide the point of connection.
-
-	   The algorithm also checks the remote IP address of server connection.
-	   If it is private range address and we have private range address we
-	   assume that we are chatting in LAN and will provide the point of
-	   connection.
-
-	   Naturally this algorithm does not always get things right. */
-
-	if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) {
-		/* Check if the IP is private */
-		if (!force_local && silcpurple_ip_is_private(local_ip)) {
-			local = FALSE;
-
-			/* Local IP is private, resolve the remote server IP to see whether
-			   we are talking to Internet or just on LAN. */
-			if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL,
-							&remote_ip))
-				if (silcpurple_ip_is_private(remote_ip))
-					/* We assume we are in LAN.  Let's provide
-					   the connection point. */
-					local = TRUE;
-		}
-	}
-
-	if (force_local)
-		local = TRUE;
-
-	if (local && !local_ip)
-		local_ip = silc_net_localip();
-
-	a = silc_calloc(1, sizeof(*a));
-	if (!a)
-		return;
-	a->responder = local;
-
-	/* Send the key agreement request */
-	silc_client_send_key_agreement(sg->client, sg->conn, clients[0],
-				       local ? local_ip : NULL, NULL, 0, 60,
-				       silcpurple_buddy_keyagr_cb, a);
-
-	silc_free(local_ip);
-	silc_free(remote_ip);
-	silc_free(clients);
-}
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-	char *hostname;
-	SilcUInt16 port;
-} *SilcPurpleKeyAgrAsk;
-
-static void
-silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id)
-{
-	SilcPurpleKeyAgr ai;
-	SilcClientEntry client_entry;
-
-	if (id != 1)
-		goto out;
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(a->client, a->conn,
-						    &a->client_id);
-	if (!client_entry) {
-		purple_notify_error(a->client->application, _("Key Agreement"),
-				  _("The remote user is not present in the network any more"),
-				  NULL);
-		goto out;
-	}
-
-	/* If the hostname was provided by the requestor perform the key agreement
-	   now.  Otherwise, we will send him a request to connect to us. */
-	if (a->hostname) {
-		ai = silc_calloc(1, sizeof(*ai));
-		if (!ai)
-			goto out;
-		ai->responder = FALSE;
-		silc_client_perform_key_agreement(a->client, a->conn, client_entry,
-						  a->hostname, a->port,
-						  silcpurple_buddy_keyagr_cb, ai);
-	} else {
-		/* Send request.  Force us as the point of connection since requestor
-		   did not provide the point of connection. */
-		silcpurple_buddy_keyagr_do(a->client->application,
-					 client_entry->nickname, TRUE);
-	}
-
- out:
-	silc_free(a->hostname);
-	silc_free(a);
-}
-
-void silcpurple_buddy_keyagr_request(SilcClient client,
-				   SilcClientConnection conn,
-				   SilcClientEntry client_entry,
-				   const char *hostname, SilcUInt16 port)
-{
-	char tmp[128], tmp2[128];
-	SilcPurpleKeyAgrAsk a;
-	PurpleConnection *gc = client->application;
-
-	g_snprintf(tmp, sizeof(tmp),
-		   _("Key agreement request received from %s. Would you like to "
-		     "perform the key agreement?"), client_entry->nickname);
-	if (hostname)
-		g_snprintf(tmp2, sizeof(tmp2),
-			   _("The remote user is waiting key agreement on:\n"
-			     "Remote host: %s\nRemote port: %d"), hostname, port);
-
-	a = silc_calloc(1, sizeof(*a));
-	if (!a)
-		return;
-	a->client = client;
-	a->conn = conn;
-	a->client_id = *client_entry->id;
-	if (hostname)
-		a->hostname = strdup(hostname);
-	a->port = port;
-
-	purple_request_action(client->application, _("Key Agreement Request"), tmp,
-			    hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname,
-				NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),
-			    _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));
-}
-
-static void
-silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-
-	buddy = (PurpleBuddy *)node;
-	silcpurple_buddy_keyagr_do(buddy->account->gc, buddy->name, FALSE);
-}
-
-
-/**************************** Static IM Key **********************************/
-
-static void
-silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b;
-	PurpleConnection *gc;
-        SilcPurple sg;
-	char *nickname;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	b = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(b->account);
-	sg = gc->proto_data;
-
-	if (!silc_parse_userfqdn(b->name, &nickname, NULL))
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn,
-						nickname, b->name,
-						&clients_count);
-	if (!clients) {
-		silc_free(nickname);
-		return;
-	}
-
-	clients[0]->prv_resp = FALSE;
-	silc_client_del_private_message_key(sg->client, sg->conn,
-					    clients[0]);
-	silc_free(clients);
-	silc_free(nickname);
-}
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-} *SilcPurplePrivkey;
-
-static void
-silcpurple_buddy_privkey(PurpleConnection *gc, const char *name);
-
-static void
-silcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase)
-{
-	SilcClientEntry client_entry;
-
-        if (!passphrase || !(*passphrase)) {
-                silc_free(p);
-                return;
-        }
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(p->client, p->conn,
-						    &p->client_id);
-	if (!client_entry) {
-		purple_notify_error(p->client->application, _("IM With Password"),
-				  _("The remote user is not present in the network any more"),
-				  NULL);
-		silc_free(p);
-		return;
-	}
-
-	/* Set the private message key */
-	silc_client_del_private_message_key(p->client, p->conn,
-					    client_entry);
-	silc_client_add_private_message_key(p->client, p->conn,
-					    client_entry, NULL, NULL,
-					    (unsigned char *)passphrase,
-					    strlen(passphrase), FALSE,
-					    client_entry->prv_resp);
-	if (!client_entry->prv_resp)
-		silc_client_send_private_message_key_request(p->client,
-							     p->conn,
-							     client_entry);
-        silc_free(p);
-}
-
-static void
-silcpurple_buddy_privkey_resolved(SilcClient client,
-				SilcClientConnection conn,
-				SilcClientEntry *clients,
-				SilcUInt32 clients_count,
-				void *context)
-{
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"),
-			   (const char *)context);
-		purple_notify_error(client->application, _("IM With Password"),
-				  _("Cannot set IM key"), tmp);
-		g_free(context);
-		return;
-	}
-
-	silcpurple_buddy_privkey(client->application, context);
-	silc_free(context);
-}
-
-static void
-silcpurple_buddy_privkey(PurpleConnection *gc, const char *name)
-{
-	SilcPurple sg = gc->proto_data;
-	char *nickname;
-	SilcPurplePrivkey p;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
-
-	if (!name)
-		return;
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn,
-						nickname, name,
-						&clients_count);
-	if (!clients) {
-		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,
-					silcpurple_buddy_privkey_resolved,
-					g_strdup(name));
-		silc_free(nickname);
-		return;
-	}
-
-	p = silc_calloc(1, sizeof(*p));
-	if (!p)
-		return;
-	p->client = sg->client;
-	p->conn = sg->conn;
-	p->client_id = *clients[0]->id;
-	purple_request_input(gc, _("IM With Password"), NULL,
-	                     _("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);
-
-	silc_free(clients);
-	silc_free(nickname);
-}
-
-static void
-silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(buddy->account);
-
-	silcpurple_buddy_privkey(gc, buddy->name);
-}
-
-
-/**************************** Get Public Key *********************************/
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-} *SilcPurpleBuddyGetkey;
-
-static void
-silcpurple_buddy_getkey(PurpleConnection *gc, const char *name);
-
-static void
-silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g,
-			 SilcClientCommandReplyContext cmd)
-{
-	SilcClientEntry client_entry;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(g->client, g->conn,
-						    &g->client_id);
-	if (!client_entry) {
-		purple_notify_error(g->client->application, _("Get Public Key"),
-				  _("The remote user is not present in the network any more"),
-				  NULL);
-		silc_free(g);
-		return;
-	}
-
-	if (!client_entry->public_key) {
-		silc_free(g);
-		return;
-	}
-
-	/* Now verify the public key */
-	pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
-	silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-				   NULL, NULL);
-	silc_free(pk);
-	silc_free(g);
-}
-
-static void
-silcpurple_buddy_getkey_resolved(SilcClient client,
-			       SilcClientConnection conn,
-			       SilcClientEntry *clients,
-			       SilcUInt32 clients_count,
-			       void *context)
-{
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"),
-			   (const char *)context);
-		purple_notify_error(client->application, _("Get Public Key"),
-				  _("Cannot fetch the public key"), tmp);
-		g_free(context);
-		return;
-	}
-
-	silcpurple_buddy_getkey(client->application, context);
-	silc_free(context);
-}
-
-static void
-silcpurple_buddy_getkey(PurpleConnection *gc, const char *name)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
-	SilcPurpleBuddyGetkey g;
-	char *nickname;
-
-	if (!name)
-		return;
-
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, nickname, name,
-						&clients_count);
-	if (!clients) {
-		silc_client_get_clients(client, conn, nickname, NULL,
-					silcpurple_buddy_getkey_resolved,
-					g_strdup(name));
-		silc_free(nickname);
-		return;
-	}
-
-	/* Call GETKEY */
-	g = silc_calloc(1, sizeof(*g));
-	if (!g)
-		return;
-	g->client = client;
-	g->conn = conn;
-	g->client_id = *clients[0]->id;
-	silc_client_command_call(client, conn, NULL, "GETKEY",
-				 clients[0]->nickname, NULL);
-	silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-				    conn->cmd_ident,
-				    (SilcCommandCb)silcpurple_buddy_getkey_cb, g);
-	silc_free(clients);
-	silc_free(nickname);
-}
-
-static void
-silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(buddy->account);
-
-	silcpurple_buddy_getkey(gc, buddy->name);
-}
-
-static void
-silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b;
-	PurpleConnection *gc;
-	SilcPurple sg;
-	SilcPublicKey public_key;
-	const char *pkfile;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	b = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(b->account);
-	sg = gc->proto_data;
-
-	pkfile = purple_blist_node_get_string(node, "public-key");
-	if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) &&
-	    !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) {
-		purple_notify_error(gc,
-				  _("Show Public Key"),
-				  _("Could not load public key"), NULL);
-		return;
-	}
-
-	silcpurple_show_public_key(sg, b->name, public_key, NULL, NULL);
-	silc_pkcs_public_key_free(public_key);
-}
-
-
-/**************************** Buddy routines *********************************/
-
-/* The buddies are implemented by using the WHOIS and WATCH commands that
-   can be used to search users by their public key.  Since nicknames aren't
-   unique in SILC we cannot trust the buddy list using their nickname.  We
-   associate public keys to buddies and use those to search and watch
-   in the network.
-
-   The problem is that Purple does not return PurpleBuddy contexts to the
-   callbacks but the buddy names.  Naturally, this is not going to work
-   with SILC.  But, for now, we have to do what we can... */
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-	PurpleBuddy *b;
-	unsigned char *offline_pk;
-	SilcUInt32 offline_pk_len;
-	unsigned int offline        : 1;
-	unsigned int pubkey_search  : 1;
-	unsigned int init           : 1;
-} *SilcPurpleBuddyRes;
-
-static void
-silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id);
-static void
-silcpurple_add_buddy_resolved(SilcClient client,
-			    SilcClientConnection conn,
-			    SilcClientEntry *clients,
-			    SilcUInt32 clients_count,
-			    void *context);
-
-void silcpurple_get_info(PurpleConnection *gc, const char *who)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientEntry client_entry;
-	PurpleBuddy *b;
-	const char *filename, *nick = who;
-	char tmp[256];
-
-	if (!who)
-		return;
-	if (strlen(who) > 1 && who[0] == '@')
-		nick = who + 1;
-	if (strlen(who) > 1 && who[0] == '*')
-		nick = who + 1;
-	if (strlen(who) > 2 && who[0] == '*' && who[1] == '@')
-		nick = who + 2;
-
-	b = purple_find_buddy(gc->account, nick);
-	if (b) {
-		/* See if we have this buddy's public key.  If we do use that
-		   to search the details. */
-		filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
-		if (filename) {
-			/* Call WHOIS.  The user info is displayed in the WHOIS
-			   command reply. */
-			silc_client_command_call(client, conn, NULL, "WHOIS",
-						 "-details", "-pubkey", filename, NULL);
-			return;
-		}
-
-		if (!b->proto_data) {
-			g_snprintf(tmp, sizeof(tmp),
-				   _("User %s is not present in the network"), b->name);
-			purple_notify_error(gc, _("User Information"),
-					  _("Cannot get user information"), tmp);
-			return;
-		}
-
-		client_entry = silc_client_get_client_by_id(client, conn, b->proto_data);
-		if (client_entry) {
-			/* Call WHOIS.  The user info is displayed in the WHOIS
-			   command reply. */
-			silc_client_command_call(client, conn, NULL, "WHOIS",
-						 client_entry->nickname, "-details", NULL);
-		}
-	} else {
-		/* Call WHOIS just with nickname. */
-		silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL);
-	}
-}
-
-static void
-silcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r)
-{
-	char tmp[512];
-	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"),
-		   r->b->name);
-	purple_notify_error(r->client->application, _("Add Buddy"), tmp,
-			  _("You cannot receive buddy notifications until you "
-			    "import his/her public key.  You can use the Get Public Key "
-			    "command to get the public key."));
-	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-}
-
-static void
-silcpurple_add_buddy_save(bool success, void *context)
-{
-	SilcPurpleBuddyRes r = context;
-	PurpleBuddy *b = r->b;
-	SilcClient client = r->client;
-	SilcClientEntry client_entry;
-	SilcAttributePayload attr;
-	SilcAttribute attribute;
-	SilcVCardStruct vcard;
-	SilcAttributeObjMime message, extension;
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	SilcAttributeObjMime usericon;
-#endif
-	SilcAttributeObjPk serverpk, usersign, serversign;
-	gboolean usign_success = TRUE, ssign_success = TRUE;
-	char filename[512], filename2[512], *fingerprint = NULL, *tmp;
-	SilcUInt32 len;
-	int i;
-
-	if (!success) {
-		/* The user did not trust the public key. */
-		silcpurple_add_buddy_pk_no(r);
-		silc_free(r);
-		return;
-	}
-
-	if (r->offline) {
-		/* User is offline.  Associate the imported public key with
-		   this user. */
-		fingerprint = silc_hash_fingerprint(NULL, r->offline_pk,
-						    r->offline_pk_len);
-		for (i = 0; i < strlen(fingerprint); i++)
-			if (fingerprint[i] == ' ')
-				fingerprint[i] = '_';
-		g_snprintf(filename, sizeof(filename) - 1,
-			   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
-			   silcpurple_silcdir(), fingerprint);
-		purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
-		purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-		silc_free(fingerprint);
-		silc_free(r->offline_pk);
-		silc_free(r);
-		return;
-	}
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(r->client, r->conn,
-						    &r->client_id);
-	if (!client_entry) {
-		silc_free(r);
-		return;
-	}
-
-	memset(&vcard, 0, sizeof(vcard));
-	memset(&message, 0, sizeof(message));
-	memset(&extension, 0, sizeof(extension));
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	memset(&usericon, 0, sizeof(usericon));
-#endif
-	memset(&serverpk, 0, sizeof(serverpk));
-	memset(&usersign, 0, sizeof(usersign));
-	memset(&serversign, 0, sizeof(serversign));
-
-	/* Now that we have the public key and we trust it now we
-	   save the attributes of the buddy and update its status. */
-
-	if (client_entry->attrs) {
-		silc_dlist_start(client_entry->attrs);
-		while ((attr = silc_dlist_get(client_entry->attrs))
-		       != SILC_LIST_END) {
-			attribute = silc_attribute_get_attribute(attr);
-
-			switch (attribute) {
-			case SILC_ATTRIBUTE_USER_INFO:
-				if (!silc_attribute_get_object(attr, (void *)&vcard,
-							       sizeof(vcard)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_STATUS_MESSAGE:
-				if (!silc_attribute_get_object(attr, (void *)&message,
-							       sizeof(message)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_EXTENSION:
-				if (!silc_attribute_get_object(attr, (void *)&extension,
-							       sizeof(extension)))
-					continue;
-				break;
-
-#ifdef SILC_ATTRIBUTE_USER_ICON
-			case SILC_ATTRIBUTE_USER_ICON:
-				if (!silc_attribute_get_object(attr, (void *)&usericon,
-							       sizeof(usericon)))
-					continue;
-				break;
-#endif
-
-			case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
-				if (serverpk.type)
-					continue;
-				if (!silc_attribute_get_object(attr, (void *)&serverpk,
-							       sizeof(serverpk)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
-				if (usersign.data)
-					continue;
-				if (!silc_attribute_get_object(attr, (void *)&usersign,
-							       sizeof(usersign)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
-				if (serversign.data)
-					continue;
-				if (!silc_attribute_get_object(attr, (void *)&serversign,
-							       sizeof(serversign)))
-					continue;
-				break;
-
-			default:
-				break;
-			}
-		}
-	}
-
-	/* Verify the attribute signatures */
-
-	if (usersign.data) {
-		SilcPKCS pkcs;
-		unsigned char *verifyd;
-		SilcUInt32 verify_len;
-
-		silc_pkcs_alloc((unsigned char*)"rsa", &pkcs);
-		verifyd = silc_attribute_get_verify_data(client_entry->attrs,
-							 FALSE, &verify_len);
-		if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){
-			if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
-							usersign.data,
-							usersign.data_len,
-							verifyd, verify_len))
-				usign_success = FALSE;
-		}
-		silc_free(verifyd);
-	}
-
-	if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) {
-		SilcPublicKey public_key;
-		SilcPKCS pkcs;
-		unsigned char *verifyd;
-		SilcUInt32 verify_len;
-
-		if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len,
-						&public_key)) {
-			silc_pkcs_alloc((unsigned char *)"rsa", &pkcs);
-			verifyd = silc_attribute_get_verify_data(client_entry->attrs,
-								 TRUE, &verify_len);
-			if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) {
-				if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
-							       serversign.data,
-							       serversign.data_len,
-							       verifyd, verify_len))
-					ssign_success = FALSE;
-			}
-			silc_pkcs_public_key_free(public_key);
-			silc_free(verifyd);
-		}
-	}
-
-	fingerprint = silc_fingerprint(client_entry->fingerprint,
-				       client_entry->fingerprint_len);
-	for (i = 0; i < strlen(fingerprint); i++)
-		if (fingerprint[i] == ' ')
-			fingerprint[i] = '_';
-
-	if (usign_success || ssign_success) {
-		struct passwd *pw;
-		struct stat st;
-
-		memset(filename2, 0, sizeof(filename2));
-
-		/* Filename for dir */
-		tmp = fingerprint + strlen(fingerprint) - 9;
-		g_snprintf(filename, sizeof(filename) - 1,
-			   "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s",
-			   silcpurple_silcdir(), tmp);
-
-		pw = getpwuid(getuid());
-		if (!pw)
-			return;
-
-		/* Create dir if it doesn't exist */
-		if ((g_stat(filename, &st)) == -1) {
-			if (errno == ENOENT) {
-				if (pw->pw_uid == geteuid()) {
-					int ret = g_mkdir(filename, 0755);
-					if (ret < 0)
-						return;
-				}
-			}
-		}
-
-		/* Save VCard */
-		g_snprintf(filename2, sizeof(filename2) - 1,
-			   "%s" G_DIR_SEPARATOR_S "vcard", filename);
-		if (vcard.full_name) {
-			tmp = (char *)silc_vcard_encode(&vcard, &len);
-			silc_file_writefile(filename2, tmp, len);
-			silc_free(tmp);
-		}
-
-		/* Save status message */
-		if (message.mime) {
-			memset(filename2, 0, sizeof(filename2));
-			g_snprintf(filename2, sizeof(filename2) - 1,
-				   "%s" G_DIR_SEPARATOR_S "status_message.mime",
-				   filename);
-			silc_file_writefile(filename2, (char *)message.mime,
-					    message.mime_len);
-		}
-
-		/* Save extension data */
-		if (extension.mime) {
-			memset(filename2, 0, sizeof(filename2));
-			g_snprintf(filename2, sizeof(filename2) - 1,
-				   "%s" G_DIR_SEPARATOR_S "extension.mime",
-				   filename);
-			silc_file_writefile(filename2, (char *)extension.mime,
-					    extension.mime_len);
-		}
-
-#ifdef SILC_ATTRIBUTE_USER_ICON
-		/* Save user icon */
-		if (usericon.mime) {
-			SilcMime m = silc_mime_decode(usericon.mime,
-						      usericon.mime_len);
-			if (m) {
-				const char *type = silc_mime_get_field(m, "Content-Type");
-				if (!strcmp(type, "image/jpeg") ||
-				    !strcmp(type, "image/gif") ||
-				    !strcmp(type, "image/bmp") ||
-				    !strcmp(type, "image/png")) {
-					const unsigned char *data;
-					SilcUInt32 data_len;
-					data = silc_mime_get_data(m, &data_len);
-					if (data) {
-						/* TODO: Check if SILC gives us something to use as the checksum instead */
-						purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL);
-					}
-				}
-				silc_mime_free(m);
-			}
-		}
-#endif
-	}
-
-	/* Save the public key path to buddy properties, as it is used
-	   to identify the buddy in the network (and not the nickname). */
-	memset(filename, 0, sizeof(filename));
-	g_snprintf(filename, sizeof(filename) - 1,
-		   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
-		   silcpurple_silcdir(), fingerprint);
-	purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
-
-	/* Update online status */
-	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
-
-	/* Finally, start watching this user so we receive its status
-	   changes from the server */
-	g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename);
-	silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey",
-				 filename2, NULL);
-
-	silc_free(fingerprint);
-	silc_free(r);
-}
-
-static void
-silcpurple_add_buddy_ask_import(void *user_data, const char *name)
-{
-	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
-	SilcPublicKey public_key;
-
-	/* Load the public key */
-	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&
-	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {
-		silcpurple_add_buddy_ask_pk_cb(r, 0);
-		purple_notify_error(r->client->application,
-				  _("Add Buddy"), _("Could not load public key"), NULL);
-		return;
-	}
-
-	/* Now verify the public key */
-	r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len);
-	silcpurple_verify_public_key(r->client, r->conn, r->b->name,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   r->offline_pk, r->offline_pk_len,
-				   SILC_SKE_PK_TYPE_SILC,
-				   silcpurple_add_buddy_save, r);
-}
-
-static void
-silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name)
-{
-	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
-
-	/* The user did not import public key.  The buddy is unusable. */
-	silcpurple_add_buddy_pk_no(r);
-	silc_free(r);
-}
-
-static void
-silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id)
-{
-	if (id != 0) {
-		/* The user did not import public key.  The buddy is unusable. */
-		silcpurple_add_buddy_pk_no(r);
-		silc_free(r);
-		return;
-	}
-
-	/* Open file selector to select the public key. */
-	purple_request_file(r->client->application, _("Open..."), NULL, FALSE,
-			  G_CALLBACK(silcpurple_add_buddy_ask_import),
-			  G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel),
-			  purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
-
-}
-
-static void
-silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r)
-{
-	char tmp[512];
-	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"),
-		   r->b->name);
-	purple_request_action(r->client->application, _("Add Buddy"), tmp,
-			    _("To add the buddy you must import his/her public key. "
-			      "Press Import to import a public key."), 0,
-				  purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2,
-			    _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb),
-			    _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb));
-}
-
-static void
-silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r,
-			     SilcClientCommandReplyContext cmd)
-{
-	SilcClientEntry client_entry;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(r->client, r->conn,
-						    &r->client_id);
-	if (!client_entry || !client_entry->public_key) {
-		/* The buddy is offline/nonexistent. We will require user
-		   to associate a public key with the buddy or the buddy
-		   cannot be added. */
-		r->offline = TRUE;
-		silcpurple_add_buddy_ask_pk(r);
-		return;
-	}
-
-	/* Now verify the public key */
-	pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
-	silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-				   silcpurple_add_buddy_save, r);
-	silc_free(pk);
-}
-
-static void
-silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
-{
-	PurpleRequestField *f;
-	GList *list;
-	SilcClientEntry client_entry;
-
-	f = purple_request_fields_get_field(fields, "list");
-	list = purple_request_field_list_get_selected(f);
-	if (!list) {
-		/* The user did not select any user. */
-		silcpurple_add_buddy_pk_no(r);
-		silc_free(r);
-		return;
-	}
-
-	client_entry = purple_request_field_list_get_data(f, list->data);
-	silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r);
-}
-
-static void
-silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
-{
-	/* The user did not select any user. */
-	silcpurple_add_buddy_pk_no(r);
-	silc_free(r);
-}
-
-static void
-silcpurple_add_buddy_select(SilcPurpleBuddyRes r,
-			  SilcClientEntry *clients,
-			  SilcUInt32 clients_count)
-{
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	char tmp[512], tmp2[128];
-	int i;
-	char *fingerprint;
-
-	fields = purple_request_fields_new();
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_list_new("list", NULL);
-	purple_request_field_group_add_field(g, f);
-	purple_request_field_list_set_multi_select(f, FALSE);
-	purple_request_fields_add_group(fields, g);
-
-	for (i = 0; i < clients_count; i++) {
-		fingerprint = NULL;
-		if (clients[i]->fingerprint) {
-			fingerprint = silc_fingerprint(clients[i]->fingerprint,
-						       clients[i]->fingerprint_len);
-			g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint);
-		}
-		g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s",
-			   clients[i]->realname, clients[i]->nickname,
-			   clients[i]->username, clients[i]->hostname ?
-			   clients[i]->hostname : "",
-			   fingerprint ? tmp2 : "");
-		purple_request_field_list_add_icon(f, tmp, NULL, clients[i]);
-		silc_free(fingerprint);
-	}
-
-	purple_request_fields(r->client->application, _("Add Buddy"),
-				_("Select correct user"),
-				r->pubkey_search
-					? _("More than one user was found with the same public key. Select "
-						"the correct user from the list to add to the buddy list.")
-					: _("More than one user was found with the same name. Select "
-						"the correct user from the list to add to the buddy list."),
-				fields,
-				_("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb),
-				_("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel),
-				purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
-}
-
-static void
-silcpurple_add_buddy_resolved(SilcClient client,
-			    SilcClientConnection conn,
-			    SilcClientEntry *clients,
-			    SilcUInt32 clients_count,
-			    void *context)
-{
-	SilcPurpleBuddyRes r = context;
-	PurpleBuddy *b = r->b;
-	SilcAttributePayload pub;
-	SilcAttributeObjPk userpk;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-	const char *filename;
-
-	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
-
-	/* If the buddy is offline/nonexistent, we will require user
-	   to associate a public key with the buddy or the buddy
-	   cannot be added. */
-	if (!clients_count) {
-		if (r->init) {
-			silc_free(r);
-			return;
-		}
-
-		r->offline = TRUE;
-		/* If the user has already associated a public key, try loading it
-		 * before prompting the user to load it again */
-		if (filename != NULL)
-			silcpurple_add_buddy_ask_import(r, filename);
-		else
-			silcpurple_add_buddy_ask_pk(r);
-		return;
-	}
-
-	/* If more than one client was found with nickname, we need to verify
-	   from user which one is the correct. */
-	if (clients_count > 1 && !r->pubkey_search) {
-		if (r->init) {
-			silc_free(r);
-			return;
-		}
-
-		silcpurple_add_buddy_select(r, clients, clients_count);
-		return;
-	}
-
-	/* If we searched using public keys and more than one entry was found
-	   the same person is logged on multiple times. */
-	if (clients_count > 1 && r->pubkey_search && b->name) {
-		if (r->init) {
-			/* Find the entry that closest matches to the
-			   buddy nickname. */
-			int i;
-			for (i = 0; i < clients_count; i++) {
-				if (!g_ascii_strncasecmp(b->name, clients[i]->nickname,
-						 strlen(b->name))) {
-					clients[0] = clients[i];
-					break;
-				}
-			}
-		} else {
-			/* Verify from user which one is correct */
-			silcpurple_add_buddy_select(r, clients, clients_count);
-			return;
-		}
-	}
-
-	/* The client was found.  Now get its public key and verify
-	   that before adding the buddy. */
-	memset(&userpk, 0, sizeof(userpk));
-	b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id));
-	r->client_id = *clients[0]->id;
-
-	/* Get the public key from attributes, if not present then
-	   resolve it with GETKEY unless we have it cached already. */
-	if (clients[0]->attrs && !clients[0]->public_key) {
-		pub = silcpurple_get_attr(clients[0]->attrs,
-					SILC_ATTRIBUTE_USER_PUBLIC_KEY);
-		if (!pub || !silc_attribute_get_object(pub, (void *)&userpk,
-						       sizeof(userpk))) {
-			/* Get public key with GETKEY */
-			silc_client_command_call(client, conn, NULL,
-						 "GETKEY", clients[0]->nickname, NULL);
-			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-						    conn->cmd_ident,
-						    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
-						    r);
-			return;
-		}
-		if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len,
-						 &clients[0]->public_key))
-			return;
-		silc_free(userpk.data);
-	} else if (filename && !clients[0]->public_key) {
-		if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key,
-					       SILC_PKCS_FILE_PEM) &&
-		    !silc_pkcs_load_public_key(filename, &clients[0]->public_key,
-					       SILC_PKCS_FILE_BIN)) {
-			/* Get public key with GETKEY */
-			silc_client_command_call(client, conn, NULL,
-						 "GETKEY", clients[0]->nickname, NULL);
-			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-						    conn->cmd_ident,
-						    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
-						    r);
-			return;
-		}
-	} else if (!clients[0]->public_key) {
-		/* Get public key with GETKEY */
-		silc_client_command_call(client, conn, NULL,
-					 "GETKEY", clients[0]->nickname, NULL);
-		silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-					    conn->cmd_ident,
-					    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
-					    r);
-		return;
-	}
-
-	/* We have the public key, verify it. */
-	pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len);
-	silcpurple_verify_public_key(client, conn, clients[0]->nickname,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-				   silcpurple_add_buddy_save, r);
-	silc_free(pk);
-}
-
-static void
-silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcPurpleBuddyRes r;
-	SilcBuffer attrs;
-	const char *filename, *name = b->name;
-
-	r = silc_calloc(1, sizeof(*r));
-	if (!r)
-		return;
-	r->client = client;
-	r->conn = conn;
-	r->b = b;
-	r->init = init;
-
-	/* See if we have this buddy's public key.  If we do use that
-	   to search the details. */
-	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
-	if (filename) {
-		SilcPublicKey public_key;
-		SilcAttributeObjPk userpk;
-
-		if (!silc_pkcs_load_public_key(filename, &public_key,
-					       SILC_PKCS_FILE_PEM) &&
-		    !silc_pkcs_load_public_key(filename, &public_key,
-					       SILC_PKCS_FILE_BIN))
-			return;
-
-		/* Get all attributes, and use the public key to search user */
-		name = NULL;
-		attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
-						       SILC_ATTRIBUTE_SERVICE,
-						       SILC_ATTRIBUTE_STATUS_MOOD,
-						       SILC_ATTRIBUTE_STATUS_FREETEXT,
-						       SILC_ATTRIBUTE_STATUS_MESSAGE,
-						       SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
-						       SILC_ATTRIBUTE_PREFERRED_CONTACT,
-						       SILC_ATTRIBUTE_TIMEZONE,
-						       SILC_ATTRIBUTE_GEOLOCATION,
-#ifdef SILC_ATTRIBUTE_USER_ICON
-						       SILC_ATTRIBUTE_USER_ICON,
-#endif
-						       SILC_ATTRIBUTE_DEVICE_INFO, 0);
-		userpk.type = "silc-rsa";
-		userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len);
-		attrs = silc_attribute_payload_encode(attrs,
-						      SILC_ATTRIBUTE_USER_PUBLIC_KEY,
-						      SILC_ATTRIBUTE_FLAG_VALID,
-						      &userpk, sizeof(userpk));
-		silc_free(userpk.data);
-		silc_pkcs_public_key_free(public_key);
-		r->pubkey_search = TRUE;
-	} else {
-		/* Get all attributes */
-		attrs = silc_client_attributes_request(0);
-	}
-
-	/* Resolve */
-	silc_client_get_clients_whois(client, conn, name, NULL, attrs,
-				      silcpurple_add_buddy_resolved, r);
-	silc_buffer_free(attrs);
-}
-
-void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	/* Don't add if the buddy is already on the list.
-	 *
-	 * SILC doesn't have groups, so we don't need to do anything
-	 * for a move. */
-	if (purple_buddy_get_protocol_data(buddy) == NULL)
-		silcpurple_add_buddy_i(gc, buddy, FALSE);
-}
-
-void silcpurple_send_buddylist(PurpleConnection *gc)
-{
-	PurpleBuddyList *blist;
-	PurpleBlistNode *gnode, *cnode, *bnode;
-	PurpleBuddy *buddy;
-	PurpleAccount *account;
-
-	account = purple_connection_get_account(gc);
-
-	if ((blist = purple_get_blist()) != NULL)
-	{
-		for (gnode = blist->root; gnode != NULL; gnode = gnode->next)
-		{
-			if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
-				continue;
-			for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
-			{
-				if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
-					continue;
-				for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
-				{
-					if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
-						continue;
-					buddy = (PurpleBuddy *)bnode;
-					if (purple_buddy_get_account(buddy) == account)
-						silcpurple_add_buddy_i(gc, buddy, TRUE);
-				}
-			}
-		}
-	}
-}
-
-void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
-			   PurpleGroup *group)
-{
-	silc_free(buddy->proto_data);
-}
-
-void silcpurple_idle_set(PurpleConnection *gc, int idle)
-
-{
-	SilcPurple sg;
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcAttributeObjService service;
-	const char *server;
-	int port;
-
-	sg = gc->proto_data;
-	if (sg == NULL)
-		return;
-
-	client = sg->client;
-	if (client == NULL)
-		return;
-
-	conn = sg->conn;
-	if (conn == NULL)
-		return;
-
-	server = purple_account_get_string(sg->account, "server",
-					 "silc.silcnet.org");
-	port = purple_account_get_int(sg->account, "port", 706),
-
-	memset(&service, 0, sizeof(service));
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_SERVICE, NULL);
-	service.port = port;
-	g_snprintf(service.address, sizeof(service.address), "%s", server);
-	service.idle = idle;
-	silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_SERVICE,
-				  &service, sizeof(service));
-}
-
-char *silcpurple_status_text(PurpleBuddy *b)
-{
-	SilcPurple sg = b->account->gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientID *client_id = b->proto_data;
-	SilcClientEntry client_entry;
-	SilcAttributePayload attr;
-	SilcAttributeMood mood = 0;
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(client, conn, client_id);
-	if (!client_entry)
-		return NULL;
-
-	/* If user is online, we show the mood status, if available.
-	   If user is offline or away that status is indicated. */
-
-	if (client_entry->mode & SILC_UMODE_DETACHED)
-		return g_strdup(_("Detached"));
-	if (client_entry->mode & SILC_UMODE_GONE)
-		return g_strdup(_("Away"));
-	if (client_entry->mode & SILC_UMODE_INDISPOSED)
-		return g_strdup(_("Indisposed"));
-	if (client_entry->mode & SILC_UMODE_BUSY)
-		return g_strdup(_("Busy"));
-	if (client_entry->mode & SILC_UMODE_PAGE)
-		return g_strdup(_("Wake Me Up"));
-	if (client_entry->mode & SILC_UMODE_HYPER)
-		return g_strdup(_("Hyper Active"));
-	if (client_entry->mode & SILC_UMODE_ROBOT)
-		return g_strdup(_("Robot"));
-
-	attr = silcpurple_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD);
-	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
-		/* The mood is a bit mask, so we could show multiple moods,
-		   but let's show only one for now. */
-		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
-			return g_strdup(_("Happy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
-			return g_strdup(_("Sad"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
-			return g_strdup(_("Angry"));
-		if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
-			return g_strdup(_("Jealous"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
-			return g_strdup(_("Ashamed"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
-			return g_strdup(_("Invincible"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
-			return g_strdup(_("In Love"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
-			return g_strdup(_("Sleepy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_BORED)
-			return g_strdup(_("Bored"));
-		if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
-			return g_strdup(_("Excited"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
-			return g_strdup(_("Anxious"));
-	}
-
-	return NULL;
-}
-
-void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
-{
-	SilcPurple sg = b->account->gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientID *client_id = b->proto_data;
-	SilcClientEntry client_entry;
-	char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
-	char tmp[256];
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(client, conn, client_id);
-	if (!client_entry)
-		return;
-
-	if (client_entry->nickname)
-		purple_notify_user_info_add_pair(user_info, _("Nickname"),
-					       client_entry->nickname);
-	if (client_entry->username && client_entry->hostname) {
-		g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname);
-		purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
-	}
-	if (client_entry->mode) {
-		memset(tmp, 0, sizeof(tmp));
-		silcpurple_get_umode_string(client_entry->mode,
-					  tmp, sizeof(tmp) - strlen(tmp));
-		purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
-	}
-
-	silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
-
-	if (statusstr) {
-		purple_notify_user_info_add_pair(user_info, _("Message"), statusstr);
-		g_free(statusstr);
-	}
-
-	if (full) {
-		if (moodstr) {
-			purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr);
-			g_free(moodstr);
-		}
-
-		if (contactstr) {
-			purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr);
-			g_free(contactstr);
-		}
-
-		if (langstr) {
-			purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr);
-			g_free(langstr);
-		}
-
-		if (devicestr) {
-			purple_notify_user_info_add_pair(user_info, _("Device"), devicestr);
-			g_free(devicestr);
-		}
-
-		if (tzstr) {
-			purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr);
-			g_free(tzstr);
-		}
-
-		if (geostr) {
-			purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr);
-			g_free(geostr);
-		}
-	}
-}
-
-static void
-silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	b = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(b->account);
-	sg = gc->proto_data;
-
-	/* Call KILL */
-	silc_client_command_call(sg->client, sg->conn, NULL, "KILL",
-				 b->name, "Killed by operator", NULL);
-}
-
-typedef struct {
-	SilcPurple sg;
-	SilcClientEntry client_entry;
-} *SilcPurpleBuddyWb;
-
-static void
-silcpurple_buddy_wb(PurpleBlistNode *node, gpointer data)
-{
-	SilcPurpleBuddyWb wb = data;
-	silcpurple_wb_init(wb->sg, wb->client_entry);
-	silc_free(wb);
-}
-
-GList *silcpurple_buddy_menu(PurpleBuddy *buddy)
-{
-	PurpleConnection *gc = purple_account_get_connection(buddy->account);
-	SilcPurple sg = gc->proto_data;
-	SilcClientConnection conn = sg->conn;
-	const char *pkfile = NULL;
-	SilcClientEntry client_entry = NULL;
-	PurpleMenuAction *act;
-	GList *m = NULL;
-	SilcPurpleBuddyWb wb;
-
-	pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key");
-	client_entry = silc_client_get_client_by_id(sg->client,
-						    sg->conn,
-						    buddy->proto_data);
-
-	if (client_entry && client_entry->send_key) {
-		act = purple_menu_action_new(_("Reset IM Key"),
-		                           PURPLE_CALLBACK(silcpurple_buddy_resetkey),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-	} else {
-		act = purple_menu_action_new(_("IM with Key Exchange"),
-		                           PURPLE_CALLBACK(silcpurple_buddy_keyagr),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		act = purple_menu_action_new(_("IM with Password"),
-		                           PURPLE_CALLBACK(silcpurple_buddy_privkey_menu),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (pkfile) {
-		act = purple_menu_action_new(_("Show Public Key"),
-		                           PURPLE_CALLBACK(silcpurple_buddy_showkey),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-	} else {
-		act = purple_menu_action_new(_("Get Public Key..."),
-		                           PURPLE_CALLBACK(silcpurple_buddy_getkey_menu),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (conn && conn->local_entry->mode & SILC_UMODE_ROUTER_OPERATOR) {
-		act = purple_menu_action_new(_("Kill User"),
-		                           PURPLE_CALLBACK(silcpurple_buddy_kill),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (client_entry) {
-		wb = silc_calloc(1, sizeof(*wb));
-		wb->sg = sg;
-		wb->client_entry = client_entry;
-		act = purple_menu_action_new(_("Draw On Whiteboard"),
-		                           PURPLE_CALLBACK(silcpurple_buddy_wb),
-		                           (void *)wb, NULL);
-		m = g_list_append(m, act);
-	}
-	return m;
-}
-
-#ifdef SILC_ATTRIBUTE_USER_ICON
-void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcMime mime;
-	char type[32];
-	unsigned char *icon;
-	const char *t;
-	SilcAttributeObjMime obj;
-
-	/* Remove */
-	if (!img) {
-		silc_client_attribute_del(client, conn,
-					  SILC_ATTRIBUTE_USER_ICON, NULL);
-		return;
-	}
-
-	/* Add */
-	mime = silc_mime_alloc();
-	if (!mime)
-		return;
-
-	t = purple_imgstore_get_extension(img);
-	if (!t || !strcmp(t, "icon")) {
-		silc_mime_free(mime);
-		return;
-	}
-	if (!strcmp(t, "jpg"))
-		t = "jpeg";
-	g_snprintf(type, sizeof(type), "image/%s", t);
-	silc_mime_add_field(mime, "Content-Type", type);
-	silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img));
-
-	obj.mime = icon = silc_mime_encode(mime, &obj.mime_len);
-	if (obj.mime)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj));
-
-	silc_free(icon);
-	silc_mime_free(mime);
-}
-#endif
--- a/libpurple/protocols/silc10/chat.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1456 +0,0 @@
-/*
-
-  silcpurple_chat.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-#include "wb.h"
-
-/***************************** Channel Routines ******************************/
-
-GList *silcpurple_chat_info(PurpleConnection *gc)
-{
-	GList *ci = NULL;
-	struct proto_chat_entry *pce;
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Channel:");
-	pce->identifier = "channel";
-	pce->required = TRUE;
-	ci = g_list_append(ci, pce);
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Passphrase:");
-	pce->identifier = "passphrase";
-	pce->secret = TRUE;
-	ci = g_list_append(ci, pce);
-
-	return ci;
-}
-
-GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name)
-{
-	GHashTable *defaults;
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	if (chat_name != NULL)
-		g_hash_table_insert(defaults, "channel", g_strdup(chat_name));
-
-	return defaults;
-}
-
-static void
-silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components);
-
-static void
-silcpurple_chat_getinfo_res(SilcClient client,
-			  SilcClientConnection conn,
-			  SilcChannelEntry *channels,
-			  SilcUInt32 channels_count,
-			  void *context)
-{
-	GHashTable *components = context;
-	PurpleConnection *gc = client->application;
-	const char *chname;
-	char tmp[256];
-
-	chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return;
-
-	if (!channels) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Channel %s does not exist in the network"), chname);
-		purple_notify_error(gc, _("Channel Information"),
-				  _("Cannot get channel information"), tmp);
-		return;
-	}
-
-	silcpurple_chat_getinfo(gc, components);
-}
-
-
-static void
-silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components)
-{
-	SilcPurple sg = gc->proto_data;
-	const char *chname;
-	char *buf, tmp[256], *tmp2;
-	GString *s;
-	SilcChannelEntry channel;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-
-	if (!components)
-		return;
-
-	chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return;
-	channel = silc_client_get_channel(sg->client, sg->conn,
-					  (char *)chname);
-	if (!channel) {
-		silc_client_get_channel_resolve(sg->client, sg->conn,
-						(char *)chname,
-						silcpurple_chat_getinfo_res,
-						components);
-		return;
-	}
-
-	s = g_string_new("");
-	tmp2 = g_markup_escape_text(channel->channel_name, -1);
-	g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2);
-	g_free(tmp2);
-	if (channel->user_list && silc_hash_table_count(channel->user_list))
-		g_string_append_printf(s, _("<br><b>User Count:</b> %d"),
-				       (int)silc_hash_table_count(channel->user_list));
-
-	silc_hash_table_list(channel->user_list, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
-			tmp2 = g_markup_escape_text(chu->client->nickname, -1);
-			g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"),
-					       tmp2);
-			g_free(tmp2);
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-
-	if (channel->channel_key)
-		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),
-				       silc_cipher_get_name(channel->channel_key));
-	if (channel->hmac)
-		/* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */
-		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),
-				       silc_hmac_get_name(channel->hmac));
-
-	if (channel->topic) {
-		tmp2 = g_markup_escape_text(channel->topic, -1);
-		g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2);
-		g_free(tmp2);
-	}
-
-	if (channel->mode) {
-		g_string_append_printf(s, _("<br><b>Channel Modes:</b> "));
-		silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
-		g_string_append(s, tmp);
-	}
-
-	if (channel->founder_key) {
-		char *fingerprint, *babbleprint;
-		unsigned char *pk;
-		SilcUInt32 pk_len;
-		pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len);
-		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-		babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-
-		g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
-		g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);
-
-		silc_free(fingerprint);
-		silc_free(babbleprint);
-		silc_free(pk);
-	}
-
-	buf = g_string_free(s, FALSE);
-	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL);
-	g_free(buf);
-}
-
-
-static void
-silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat = (PurpleChat *)node;
-	silcpurple_chat_getinfo(chat->account->gc, chat->components);
-}
-
-
-#if 0   /* XXX For now these are not implemented.  We need better
-	   listview dialog from Purple for these. */
-/************************** Channel Invite List ******************************/
-
-static void
-silcpurple_chat_invitelist(PurpleBlistNode *node, gpointer data);
-{
-
-}
-
-
-/**************************** Channel Ban List *******************************/
-
-static void
-silcpurple_chat_banlist(PurpleBlistNode *node, gpointer data);
-{
-
-}
-#endif
-
-
-/************************* Channel Authentication ****************************/
-
-typedef struct {
-	SilcPurple sg;
-	SilcChannelEntry channel;
-	PurpleChat *c;
-	SilcBuffer pubkeys;
-} *SilcPurpleChauth;
-
-static void
-silcpurple_chat_chpk_add(void *user_data, const char *name)
-{
-	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
-	SilcPurple sg = sgc->sg;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcPublicKey public_key;
-	SilcBuffer chpks, pk, chidp;
-	unsigned char mode[4];
-	SilcUInt32 m;
-
-	/* Load the public key */
-	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&
-	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {
-		silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-		silc_buffer_free(sgc->pubkeys);
-		silc_free(sgc);
-		purple_notify_error(client->application,
-				  _("Add Channel Public Key"),
-				  _("Could not load public key"), NULL);
-		return;
-	}
-
-	pk = silc_pkcs_public_key_payload_encode(public_key);
-	chpks = silc_buffer_alloc_size(2);
-	SILC_PUT16_MSB(1, chpks->head);
-	chpks = silc_argument_payload_encode_one(chpks, pk->data,
-						 pk->len, 0x00);
-	silc_buffer_free(pk);
-
-	m = sgc->channel->mode;
-	m |= SILC_CHANNEL_MODE_CHANNEL_AUTH;
-
-	/* Send CMODE */
-	SILC_PUT32_MSB(m, mode);
-	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);
-	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
-				 ++conn->cmd_ident, 3,
-				 1, chidp->data, chidp->len,
-				 2, mode, sizeof(mode),
-				 9, chpks->data, chpks->len);
-	silc_buffer_free(chpks);
-	silc_buffer_free(chidp);
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-static void
-silcpurple_chat_chpk_cancel(void *user_data, const char *name)
-{
-	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
-	silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-static void
-silcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = sgc->sg;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	PurpleRequestField *f;
-	GList *list;
-	SilcPublicKey public_key;
-	SilcBuffer chpks, pk, chidp;
-	SilcUInt16 c = 0, ct;
-	unsigned char mode[4];
-	SilcUInt32 m;
-
-	f = purple_request_fields_get_field(fields, "list");
-	if (!purple_request_field_list_get_selected(f)) {
-		/* Add new public key */
-		purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE,
-				  G_CALLBACK(silcpurple_chat_chpk_add),
-				  G_CALLBACK(silcpurple_chat_chpk_cancel),
-				  purple_connection_get_account(sg->gc), NULL, NULL, sgc);
-		return;
-	}
-
-	list = purple_request_field_list_get_items(f);
-	chpks = silc_buffer_alloc_size(2);
-
-	for (ct = 0; list; list = list->next, ct++) {
-		public_key = purple_request_field_list_get_data(f, list->data);
-		if (purple_request_field_list_is_selected(f, list->data)) {
-			/* Delete this public key */
-			pk = silc_pkcs_public_key_payload_encode(public_key);
-			chpks = silc_argument_payload_encode_one(chpks, pk->data,
-								 pk->len, 0x01);
-			silc_buffer_free(pk);
-			c++;
-		}
-		silc_pkcs_public_key_free(public_key);
-	}
-	if (!c) {
-		silc_buffer_free(chpks);
-		return;
-	}
-	SILC_PUT16_MSB(c, chpks->head);
-
-	m = sgc->channel->mode;
-	if (ct == c)
-		m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH;
-
-	/* Send CMODE */
-	SILC_PUT32_MSB(m, mode);
-	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);
-	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
-				 ++conn->cmd_ident, 3,
-				 1, chidp->data, chidp->len,
-				 2, mode, sizeof(mode),
-				 9, chpks->data, chpks->len);
-	silc_buffer_free(chpks);
-	silc_buffer_free(chidp);
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-static void
-silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = sgc->sg;
-	PurpleRequestField *f;
-	const char *curpass, *val;
-	int set;
-
-	f = purple_request_fields_get_field(fields, "passphrase");
-	val = purple_request_field_string_get_value(f);
-	curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");
-
-	if (!val && curpass)
-		set = 0;
-	else if (val && !curpass)
-		set = 1;
-	else if (val && curpass && strcmp(val, curpass))
-		set = 1;
-	else
-		set = -1;
-
-	if (set == 1) {
-		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-					 sgc->channel->channel_name, "+a", val, NULL);
-		purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val);
-	} else if (set == 0) {
-		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-					 sgc->channel->channel_name, "-a", NULL);
-		purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase");
-	}
-
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
-			       SilcBuffer channel_pubkeys)
-{
-	SilcUInt16 argc;
-	SilcArgumentPayload chpks;
-	unsigned char *pk;
-	SilcUInt32 pk_len, type;
-	char *fingerprint, *babbleprint;
-	SilcPublicKey pubkey;
-	SilcPublicKeyIdentifier ident;
-	char tmp2[1024], t[512];
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	SilcPurpleChauth sgc;
-	const char *curpass = NULL;
-
-	sgc = silc_calloc(1, sizeof(*sgc));
-	if (!sgc)
-		return;
-	sgc->sg = sg;
-	sgc->channel = channel;
-
-	fields = purple_request_fields_new();
-
-	if (sgc->c)
-	  curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("passphrase", _("Channel Passphrase"),
-					  curpass, FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_label_new("l1", _("Channel Public Keys List"));
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g_snprintf(t, sizeof(t),
-		   _("Channel authentication is used to secure the channel from "
-		     "unauthorized access. The authentication may be based on "
-		     "passphrase and digital signatures. If passphrase is set, it "
-		     "is required to be able to join. If channel public keys are set "
-		     "then only users whose public keys are listed are able to join."));
-
-	if (!channel_pubkeys) {
-		f = purple_request_field_list_new("list", NULL);
-		purple_request_field_group_add_field(g, f);
-		purple_request_fields(sg->gc, _("Channel Authentication"),
-				    _("Channel Authentication"), t, fields,
-				    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
-				    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
-					purple_connection_get_account(sg->gc), NULL, NULL, sgc);
-		return;
-	}
-	sgc->pubkeys = silc_buffer_copy(channel_pubkeys);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_list_new("list", NULL);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	SILC_GET16_MSB(argc, channel_pubkeys->data);
-	chpks = silc_argument_payload_parse(channel_pubkeys->data + 2,
-					    channel_pubkeys->len - 2, argc);
-	if (!chpks)
-		return;
-
-	pk = silc_argument_get_first_arg(chpks, &type, &pk_len);
-	while (pk) {
-		fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);
-		babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);
-		silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey);
-		ident = silc_pkcs_decode_identifier(pubkey->identifier);
-
-		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
-			   ident->realname ? ident->realname : ident->username ?
-			   ident->username : "", fingerprint, babbleprint);
-		purple_request_field_list_add_icon(f, tmp2, NULL, pubkey);
-
-		silc_free(fingerprint);
-		silc_free(babbleprint);
-		silc_pkcs_free_identifier(ident);
-		pk = silc_argument_get_next_arg(chpks, &type, &pk_len);
-	}
-
-	purple_request_field_list_set_multi_select(f, FALSE);
-	purple_request_fields(sg->gc, _("Channel Authentication"),
-			    _("Channel Authentication"), t, fields,
-			    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
-			    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
-				purple_connection_get_account(sg->gc), NULL, NULL, sgc);
-
-	silc_argument_payload_free(chpks);
-}
-
-static void
-silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+C", NULL);
-}
-
-
-/************************** Channel Private Groups **************************/
-
-/* Private groups are "virtual" channels.  They are groups inside a channel.
-   This is implemented by using channel private keys.  By knowing a channel
-   private key user becomes part of that group and is able to talk on that
-   group.  Other users, on the same channel, won't be able to see the
-   messages of that group.  It is possible to have multiple groups inside
-   a channel - and thus having multiple private keys on the channel. */
-
-typedef struct {
-	SilcPurple sg;
-	PurpleChat *c;
-	const char *channel;
-} *SilcPurpleCharPrv;
-
-static void
-silcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields)
-{
-	SilcPurple sg = p->sg;
-	char tmp[512];
-	PurpleRequestField *f;
-	const char *name, *passphrase, *alias;
-	GHashTable *comp;
-	PurpleGroup *g;
-	PurpleChat *cn;
-
-	f = purple_request_fields_get_field(fields, "name");
-	name = purple_request_field_string_get_value(f);
-	if (!name) {
-		silc_free(p);
-		return;
-	}
-	f = purple_request_fields_get_field(fields, "passphrase");
-	passphrase = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "alias");
-	alias = purple_request_field_string_get_value(f);
-
-	/* Add private group to buddy list */
-	g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name);
-	comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp));
-	g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase));
-
-	cn = purple_chat_new(sg->account, alias, comp);
-	g = (PurpleGroup *)p->c->node.parent;
-	purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c);
-
-	/* Associate to a real channel */
-	purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel);
-
-	/* Join the group */
-	silcpurple_chat_join(sg->gc, comp);
-
-	silc_free(p);
-}
-
-static void
-silcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields)
-{
-	silc_free(p);
-}
-
-static void
-silcpurple_chat_prv(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	SilcPurpleCharPrv p;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	char tmp[512];
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	p = silc_calloc(1, sizeof(*p));
-	if (!p)
-		return;
-	p->sg = sg;
-
-	p->channel = g_hash_table_lookup(chat->components, "channel");
-	p->c = purple_blist_find_chat(sg->account, p->channel);
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("name", _("Group Name"),
-					  NULL, FALSE);
-	purple_request_field_group_add_field(g, f);
-
-	f = purple_request_field_string_new("passphrase", _("Passphrase"),
-					  NULL, FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-
-	f = purple_request_field_string_new("alias", _("Alias"),
-					  NULL, FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g_snprintf(tmp, sizeof(tmp),
-		   _("Please enter the %s channel private group name and passphrase."),
-		   p->channel);
-	purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields,
-			    _("Add"), G_CALLBACK(silcpurple_chat_prv_add),
-			    _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel),
-				purple_connection_get_account(gc), NULL, NULL, p);
-}
-
-
-/****************************** Channel Modes ********************************/
-
-static void
-silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-f", NULL);
-}
-
-static void
-silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-	const char *channel;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	if (!sg->conn)
-		return;
-
-	/* XXX we should have ability to define which founder
-	   key to use.  Now we use the user's own public key
-	   (default key). */
-
-	/* Call CMODE */
-	channel = g_hash_table_lookup(chat->components, "channel");
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel,
-				 "+f", NULL);
-}
-
-typedef struct {
-	SilcPurple sg;
-	char *channel;
-} *SilcPurpleChatInput;
-
-static void
-silcpurple_chat_ulimit_cb(SilcPurpleChatInput s, const char *limit)
-{
-	SilcChannelEntry channel;
-	int ulimit = 0;
-
-	channel = silc_client_get_channel(s->sg->client, s->sg->conn,
-					  (char *)s->channel);
-	if (!channel)
-		return;
-	if (limit)
-		ulimit = atoi(limit);
-
-	if (!limit || !(*limit) || *limit == '0') {
-		if (limit && ulimit == channel->user_limit) {
-			silc_free(s);
-			return;
-		}
-		silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
-					 s->channel, "-l", NULL);
-
-		silc_free(s);
-		return;
-	}
-
-	if (ulimit == channel->user_limit) {
-		silc_free(s);
-		return;
-	}
-
-	/* Call CMODE */
-	silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
-				 s->channel, "+l", limit, NULL);
-
-	silc_free(s);
-}
-
-static void
-silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	SilcPurpleChatInput s;
-	SilcChannelEntry channel;
-	char *ch;
-	char tmp[32];
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	if (!sg->conn)
-		return;
-
-	ch = g_strdup(g_hash_table_lookup(chat->components, "channel"));
-	channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch);
-	if (!channel)
-		return;
-
-	s = silc_calloc(1, sizeof(*s));
-	if (!s)
-		return;
-	s->channel = ch;
-	s->sg = sg;
-	g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit);
-	purple_request_input(gc, _("User Limit"), NULL,
-			   _("Set user limit on channel. Set to zero to reset user limit."),
-			   tmp, FALSE, FALSE, NULL,
-			   _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb),
-			   _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb),
-			   purple_connection_get_account(gc), NULL, NULL, s);
-}
-
-static void
-silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-t", NULL);
-}
-
-static void
-silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+t", NULL);
-}
-
-static void
-silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-p", NULL);
-}
-
-static void
-silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+p", NULL);
-}
-
-static void
-silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-s", NULL);
-}
-
-static void
-silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+s", NULL);
-}
-
-typedef struct {
-	SilcPurple sg;
-	SilcChannelEntry channel;
-} *SilcPurpleChatWb;
-
-static void
-silcpurple_chat_wb(PurpleBlistNode *node, gpointer data)
-{
-	SilcPurpleChatWb wb = data;
-	silcpurple_wb_init_ch(wb->sg, wb->channel);
-	silc_free(wb);
-}
-
-GList *silcpurple_chat_menu(PurpleChat *chat)
-{
-	GHashTable *components = chat->components;
-	PurpleConnection *gc = purple_account_get_connection(chat->account);
-	SilcPurple sg = gc->proto_data;
-	SilcClientConnection conn = sg->conn;
-	const char *chname = NULL;
-	SilcChannelEntry channel = NULL;
-	SilcChannelUser chu = NULL;
-	SilcUInt32 mode = 0;
-
-	GList *m = NULL;
-	PurpleMenuAction *act;
-
-	if (components)
-		chname = g_hash_table_lookup(components, "channel");
-	if (chname)
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)chname);
-	if (channel) {
-		chu = silc_client_on_channel(channel, conn->local_entry);
-		if (chu)
-			mode = chu->mode;
-	}
-
-	if (strstr(chname, "[Private Group]"))
-		return NULL;
-
-	act = purple_menu_action_new(_("Get Info"),
-	                           PURPLE_CALLBACK(silcpurple_chat_getinfo_menu),
-	                           NULL, NULL);
-	m = g_list_append(m, act);
-
-#if 0   /* XXX For now these are not implemented.  We need better
-	   listview dialog from Purple for these. */
-	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
-		act = purple_menu_action_new(_("Invite List"),
-		                           PURPLE_CALLBACK(silcpurple_chat_invitelist),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		act = purple_menu_action_new(_("Ban List"),
-		                           PURPLE_CALLBACK(silcpurple_chat_banlist),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-#endif
-
-	if (chu) {
-		act = purple_menu_action_new(_("Add Private Group"),
-		                           PURPLE_CALLBACK(silcpurple_chat_prv),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (mode & SILC_CHANNEL_UMODE_CHANFO) {
-		act = purple_menu_action_new(_("Channel Authentication"),
-		                           PURPLE_CALLBACK(silcpurple_chat_chauth),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
-			act = purple_menu_action_new(_("Reset Permanent"),
-			                           PURPLE_CALLBACK(silcpurple_chat_permanent_reset),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_menu_action_new(_("Set Permanent"),
-			                           PURPLE_CALLBACK(silcpurple_chat_permanent),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
-		act = purple_menu_action_new(_("Set User Limit"),
-		                           PURPLE_CALLBACK(silcpurple_chat_ulimit),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
-			act = purple_menu_action_new(_("Reset Topic Restriction"),
-			                           PURPLE_CALLBACK(silcpurple_chat_resettopic),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_menu_action_new(_("Set Topic Restriction"),
-			                           PURPLE_CALLBACK(silcpurple_chat_settopic),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
-			act = purple_menu_action_new(_("Reset Private Channel"),
-			                           PURPLE_CALLBACK(silcpurple_chat_resetprivate),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_menu_action_new(_("Set Private Channel"),
-			                           PURPLE_CALLBACK(silcpurple_chat_setprivate),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		if (channel->mode & SILC_CHANNEL_MODE_SECRET) {
-			act = purple_menu_action_new(_("Reset Secret Channel"),
-			                           PURPLE_CALLBACK(silcpurple_chat_resetsecret),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_menu_action_new(_("Set Secret Channel"),
-			                           PURPLE_CALLBACK(silcpurple_chat_setsecret),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (channel) {
-		SilcPurpleChatWb wb;
-		wb = silc_calloc(1, sizeof(*wb));
-		wb->sg = sg;
-		wb->channel = channel;
-		act = purple_menu_action_new(_("Draw On Whiteboard"),
-		                           PURPLE_CALLBACK(silcpurple_chat_wb),
-		                           (void *)wb, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-
-/******************************* Joining Etc. ********************************/
-
-void silcpurple_chat_join_done(SilcClient client,
-			     SilcClientConnection conn,
-			     SilcClientEntry *clients,
-			     SilcUInt32 clients_count,
-			     void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	SilcChannelEntry channel = context;
-	PurpleConversation *convo;
-	SilcUInt32 retry = SILC_PTR_TO_32(channel->context);
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	GList *users = NULL, *flags = NULL;
-	char tmp[256];
-
-	if (!clients && retry < 1) {
-		/* Resolving users failed, try again. */
-		channel->context = SILC_32_TO_PTR(retry + 1);
-		silc_client_get_clients_by_channel(client, conn, channel,
-						   silcpurple_chat_join_done, channel);
-		return;
-	}
-
-	/* Add channel to Purple */
-	channel->context = SILC_32_TO_PTR(++sg->channel_ids);
-	serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name);
-	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-							channel->channel_name, sg->account);
-	if (!convo)
-		return;
-
-	/* Add all users to channel */
-	silc_hash_table_list(channel->user_list, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE;
-		if (!chu->client->nickname)
-			continue;
-		chu->context = SILC_32_TO_PTR(sg->channel_ids);
-
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
-			f |= PURPLE_CBFLAGS_FOUNDER;
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
-			f |= PURPLE_CBFLAGS_OP;
-		users = g_list_append(users, g_strdup(chu->client->nickname));
-		flags = g_list_append(flags, GINT_TO_POINTER(f));
-
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
-			if (chu->client == conn->local_entry)
-				g_snprintf(tmp, sizeof(tmp),
-					   _("You are channel founder on <I>%s</I>"),
-					   channel->channel_name);
-			else
-				g_snprintf(tmp, sizeof(tmp),
-					   _("Channel founder on <I>%s</I> is <I>%s</I>"),
-					   channel->channel_name, chu->client->nickname);
-
-			purple_conversation_write(convo, NULL, tmp,
-						PURPLE_MESSAGE_SYSTEM, time(NULL));
-
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-
-	purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE);
-	g_list_free(users);
-	g_list_free(flags);
-
-	/* Set topic */
-	if (channel->topic)
-		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic);
-
-	/* Set nick */
-	purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname);
-}
-
-char *silcpurple_get_chat_name(GHashTable *data)
-{
-	return g_strdup(g_hash_table_lookup(data, "channel"));
-}
-
-void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	const char *channel, *passphrase, *parentch;
-
-	if (!conn)
-		return;
-
-	channel = g_hash_table_lookup(data, "channel");
-	passphrase = g_hash_table_lookup(data, "passphrase");
-
-	/* Check if we are joining a private group.  Handle it
-	   purely locally as it's not a real channel */
-	if (strstr(channel, "[Private Group]")) {
-		SilcChannelEntry channel_entry;
-		SilcChannelPrivateKey key;
-		PurpleChat *c;
-		SilcPurplePrvgrp grp;
-
-		c = purple_blist_find_chat(sg->account, channel);
-		parentch = purple_blist_node_get_string((PurpleBlistNode *)c, "parentch");
-		if (!parentch)
-			return;
-
-		channel_entry = silc_client_get_channel(sg->client, sg->conn,
-							(char *)parentch);
-		if (!channel_entry ||
-		    !silc_client_on_channel(channel_entry, sg->conn->local_entry)) {
-			char tmp[512];
-			g_snprintf(tmp, sizeof(tmp),
-				   _("You have to join the %s channel before you are "
-				     "able to join the private group"), parentch);
-			purple_notify_error(gc, _("Join Private Group"),
-					  _("Cannot join private group"), tmp);
-			return;
-		}
-
-		/* Add channel private key */
-		if (!silc_client_add_channel_private_key(client, conn,
-							 channel_entry, channel,
-							 NULL, NULL,
-							 (unsigned char *)passphrase,
-							 strlen(passphrase), &key))
-			return;
-
-		/* Join the group */
-		grp = silc_calloc(1, sizeof(*grp));
-		if (!grp)
-			return;
-		grp->id = ++sg->channel_ids + SILCPURPLE_PRVGRP;
-		grp->chid = SILC_PTR_TO_32(channel_entry->context);
-		grp->parentch = parentch;
-		grp->channel = channel;
-		grp->key = key;
-		sg->grps = g_list_append(sg->grps, grp);
-		serv_got_joined_chat(gc, grp->id, channel);
-		return;
-	}
-
-	/* XXX We should have other properties here as well:
-	   1. whether to try to authenticate to the channel
-	     1a. with default key,
-	     1b. with specific key.
-	   2. whether to try to authenticate to become founder.
-	     2a. with default key,
-	     2b. with specific key.
-
-	   Since now such variety is not possible in the join dialog
-	   we always use -founder and -auth options, which try to
-	   do both 1 and 2 with default keys. */
-
-	/* Call JOIN */
-	if ((passphrase != NULL) && (*passphrase != '\0'))
-		silc_client_command_call(client, conn, NULL, "JOIN",
-					 channel, passphrase, "-auth", "-founder", NULL);
-	else
-		silc_client_command_call(client, conn, NULL, "JOIN",
-					 channel, "-auth", "-founder", NULL);
-}
-
-void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg,
-			  const char *name)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-
-	if (!conn)
-		return;
-
-	/* See if we are inviting on a private group.  Invite
-	   to the actual channel */
-	if (id > SILCPURPLE_PRVGRP) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		id = prv->chid;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call INVITE */
-	silc_client_command_call(client, conn, NULL, "INVITE",
-				 chu->channel->channel_name,
-				 name, NULL);
-}
-
-void silcpurple_chat_leave(PurpleConnection *gc, int id)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-	GList *l;
-	SilcPurplePrvgrp prv;
-
-	if (!conn)
-		return;
-
-	/* See if we are leaving a private group */
-	if (id > SILCPURPLE_PRVGRP) {
-		SilcChannelEntry channel;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)prv->parentch);
-		if (!channel)
-			return;
-		silc_client_del_channel_private_key(client, conn,
-						    channel, prv->key);
-		silc_free(prv);
-		sg->grps = g_list_remove(sg->grps, prv);
-		serv_got_chat_left(gc, id);
-		return;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call LEAVE */
-	silc_client_command_call(client, conn, NULL, "LEAVE",
-				 chu->channel->channel_name, NULL);
-
-	serv_got_chat_left(gc, id);
-
-	/* Leave from private groups on this channel as well */
-	for (l = sg->grps; l; l = l->next)
-		if (((SilcPurplePrvgrp)l->data)->chid == id) {
-			prv = l->data;
-			silc_client_del_channel_private_key(client, conn,
-							    chu->channel,
-							    prv->key);
-			serv_got_chat_left(gc, prv->id);
-			silc_free(prv);
-			sg->grps = g_list_remove(sg->grps, prv);
-			if (!sg->grps)
-				break;
-		}
-}
-
-int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	SilcChannelEntry channel = NULL;
-	SilcChannelPrivateKey key = NULL;
-	SilcUInt32 flags;
-	int ret;
-	char *msg2, *tmp;
-	gboolean found = FALSE;
-	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
-
-	if (!msg || !conn)
-		return 0;
-
-	flags = SILC_MESSAGE_FLAG_UTF8;
-
-	tmp = msg2 = purple_unescape_html(msg);
-
-	if (!g_ascii_strncasecmp(msg2, "/me ", 4))
-	{
-		msg2 += 4;
-		if (!*msg2) {
-			g_free(tmp);
-			return 0;
-		}
-		flags |= SILC_MESSAGE_FLAG_ACTION;
-	} else if (strlen(msg) > 1 && msg[0] == '/') {
-		if (!silc_client_command_call(client, conn, msg + 1))
-			purple_notify_error(gc, _("Call Command"), _("Cannot call command"),
-							  _("Unknown command"));
-		g_free(tmp);
-		return 0;
-	}
-
-
-	if (sign)
-		flags |= SILC_MESSAGE_FLAG_SIGNED;
-
-	/* Get the channel private key if we are sending on
-	   private group */
-	if (id > SILCPURPLE_PRVGRP) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == id)
-				break;
-		if (!l) {
-			g_free(tmp);
-			return 0;
-		}
-		prv = l->data;
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)prv->parentch);
-		if (!channel) {
-			g_free(tmp);
-			return 0;
-		}
-		key = prv->key;
-	}
-
-	if (!channel) {
-		/* Find channel by id */
-		silc_hash_table_list(conn->local_entry->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-				found = TRUE;
-				break;
-			}
-		}
-		silc_hash_table_list_reset(&htl);
-		if (!found) {
-			g_free(tmp);
-			return 0;
-		}
-		channel = chu->channel;
-	}
-
-	/* Send channel message */
-	ret = silc_client_send_channel_message(client, conn, channel, key,
-					       flags, (unsigned char *)msg2,
-					       strlen(msg2), TRUE);
-	if (ret) {
-		serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg,
-				 time(NULL));
-	}
-	g_free(tmp);
-
-	return ret;
-}
-
-void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-
-	if (!conn)
-		return;
-
-	/* See if setting topic on private group.  Set it
-	   on the actual channel */
-	if (id > SILCPURPLE_PRVGRP) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		id = prv->chid;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call TOPIC */
-	silc_client_command_call(client, conn, NULL, "TOPIC",
-				 chu->channel->channel_name, topic, NULL);
-}
-
-PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	GList *fields = NULL;
-	PurpleRoomlistField *f;
-
-	if (!conn)
-		return NULL;
-
-	if (sg->roomlist)
-		purple_roomlist_unref(sg->roomlist);
-
-	sg->roomlist_cancelled = FALSE;
-
-	sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc));
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "channel", TRUE);
-	fields = g_list_append(fields, f);
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT,
-				    _("Users"), "users", FALSE);
-	fields = g_list_append(fields, f);
-	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING,
-				    _("Topic"), "topic", FALSE);
-	fields = g_list_append(fields, f);
-	purple_roomlist_set_fields(sg->roomlist, fields);
-
-	/* Call LIST */
-	silc_client_command_call(client, conn, "LIST");
-
-	purple_roomlist_set_in_progress(sg->roomlist, TRUE);
-
-	return sg->roomlist;
-}
-
-void silcpurple_roomlist_cancel(PurpleRoomlist *list)
-{
-	PurpleConnection *gc = purple_account_get_connection(list->account);
-	SilcPurple sg;
-
-	if (!gc)
-		return;
-	sg = gc->proto_data;
-
-	purple_roomlist_set_in_progress(list, FALSE);
-	if (sg->roomlist == list) {
-		purple_roomlist_unref(sg->roomlist);
-		sg->roomlist = NULL;
-		sg->roomlist_cancelled = TRUE;
-	}
-}
--- a/libpurple/protocols/silc10/ft.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
-/*
-
-  silcpurple_ft.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-
-/****************************** File Transfer ********************************/
-
-/* This implements the secure file transfer protocol (SFTP) using the SILC
-   SFTP library implementation.  The API we use from the SILC Toolkit is the
-   SILC Client file transfer API, as it provides a simple file transfer we
-   need in this case.  We could use the SILC SFTP API directly, but it would
-   be an overkill since we'd effectively re-implement the file transfer what
-   the SILC Client's file transfer API already provides.
-
-   From Purple we do NOT use the FT API to do the transfer as it is very limiting.
-   In fact it does not suite to file transfers like SFTP at all.  For example,
-   it assumes that read operations are synchronous what they are not in SFTP.
-   It also assumes that the file transfer socket is to be handled by the Purple
-   eventloop, and this naturally is something we don't want to do in case of
-   SILC Toolkit.  The FT API suites well to purely stream based file transfers
-   like HTTP GET and similar.
-
-   For this reason, we directly access the Purple GKT FT API and hack the FT
-   API to merely provide the user interface experience and all the magic
-   is done in the SILC Toolkit.  Ie. we update the statistics information in
-   the FT API for user interface, and that's it.  A bit dirty but until the
-   FT API gets better this is the way to go.  Good thing that FT API allowed
-   us to do this. */
-
-typedef struct {
-	SilcPurple sg;
-	SilcClientEntry client_entry;
-	SilcUInt32 session_id;
-	char *hostname;
-	SilcUInt16 port;
-	PurpleXfer *xfer;
-
-	SilcClientFileName completion;
-	void *completion_context;
-} *SilcPurpleXfer;
-
-static void
-silcpurple_ftp_monitor(SilcClient client,
-		     SilcClientConnection conn,
-		     SilcClientMonitorStatus status,
-		     SilcClientFileError error,
-		     SilcUInt64 offset,
-		     SilcUInt64 filesize,
-		     SilcClientEntry client_entry,
-		     SilcUInt32 session_id,
-		     const char *filepath,
-		     void *context)
-{
-	SilcPurpleXfer xfer = context;
-	PurpleConnection *gc = xfer->sg->gc;
-	char tmp[256];
-
-	if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) {
-		purple_xfer_unref(xfer->xfer);
-		silc_free(xfer);
-		return;
-	}
-
-	if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT)
-		return;
-
-	if (status == SILC_CLIENT_FILE_MONITOR_ERROR) {
-		if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) {
-			g_snprintf(tmp, sizeof(tmp), "No such file %s",
-				   filepath ? filepath : "[N/A]");
-			purple_notify_error(gc, _("Secure File Transfer"),
-					  _("Error during file transfer"), tmp);
-		} else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-					  _("Error during file transfer"),
-					  _("Permission denied"));
-		} else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-					  _("Error during file transfer"),
-					  _("Key agreement failed"));
-		} else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-					  _("Error during file transfer"),
-					  _("File transfer session does not exist"));
-		} else {
-			purple_notify_error(gc, _("Secure File Transfer"),
-					  _("Error during file transfer"), NULL);
-		}
-		silc_client_file_close(client, conn, session_id);
-		purple_xfer_unref(xfer->xfer);
-		silc_free(xfer);
-		return;
-	}
-
-	/* Update file transfer UI */
-	if (!offset && filesize)
-		purple_xfer_set_size(xfer->xfer, filesize);
-	if (offset && filesize) {
-		xfer->xfer->bytes_sent = offset;
-		xfer->xfer->bytes_remaining = filesize - offset;
-	}
-	purple_xfer_update_progress(xfer->xfer);
-
-	if (status == SILC_CLIENT_FILE_MONITOR_SEND ||
-	    status == SILC_CLIENT_FILE_MONITOR_RECEIVE) {
-		if (offset == filesize) {
-			/* Download finished */
-			purple_xfer_set_completed(xfer->xfer, TRUE);
-			silc_client_file_close(client, conn, session_id);
-		}
-	}
-}
-
-static void
-silcpurple_ftp_cancel(PurpleXfer *x)
-{
-	SilcPurpleXfer xfer = x->data;
-	xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL;
-	purple_xfer_update_progress(xfer->xfer);
-	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-}
-
-static void
-silcpurple_ftp_ask_name_cancel(PurpleXfer *x)
-{
-	SilcPurpleXfer xfer = x->data;
-
-	/* Cancel the transmission */
-	xfer->completion(NULL, xfer->completion_context);
-	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-}
-
-static void
-silcpurple_ftp_ask_name_ok(PurpleXfer *x)
-{
-	SilcPurpleXfer xfer = x->data;
-	const char *name;
-
-	name = purple_xfer_get_local_filename(x);
-	g_unlink(name);
-	xfer->completion(name, xfer->completion_context);
-}
-
-static void
-silcpurple_ftp_ask_name(SilcClient client,
-		      SilcClientConnection conn,
-		      SilcUInt32 session_id,
-		      const char *remote_filename,
-		      SilcClientFileName completion,
-		      void *completion_context,
-		      void *context)
-{
-	SilcPurpleXfer xfer = context;
-
-	xfer->completion = completion;
-	xfer->completion_context = completion_context;
-
-	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_ask_name_ok);
-	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_ask_name_cancel);
-
-	/* Request to save the file */
-	purple_xfer_set_filename(xfer->xfer, remote_filename);
-	purple_xfer_request(xfer->xfer);
-}
-
-static void
-silcpurple_ftp_request_result(PurpleXfer *x)
-{
-	SilcPurpleXfer xfer = x->data;
-	SilcClientFileError status;
-	PurpleConnection *gc = xfer->sg->gc;
-
-	if (purple_xfer_get_status(x) != PURPLE_XFER_STATUS_ACCEPTED)
-		return;
-
-	/* Start the file transfer */
-	status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn,
-					  silcpurple_ftp_monitor, xfer,
-					  NULL, xfer->session_id,
-					  silcpurple_ftp_ask_name, xfer);
-	switch (status) {
-	case SILC_CLIENT_FILE_OK:
-		return;
-		break;
-
-	case SILC_CLIENT_FILE_UNKNOWN_SESSION:
-		purple_notify_error(gc, _("Secure File Transfer"),
-				  _("No file transfer session active"), NULL);
-		break;
-
-	case SILC_CLIENT_FILE_ALREADY_STARTED:
-		purple_notify_error(gc, _("Secure File Transfer"),
-				  _("File transfer already started"), NULL);
-		break;
-
-	case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED:
-		purple_notify_error(gc, _("Secure File Transfer"),
-				  _("Could not perform key agreement for file transfer"),
-				  NULL);
-		break;
-
-	default:
-		purple_notify_error(gc, _("Secure File Transfer"),
-				  _("Could not start the file transfer"), NULL);
-		break;
-	}
-
-	/* Error */
-	purple_xfer_unref(xfer->xfer);
-	g_free(xfer->hostname);
-	silc_free(xfer);
-}
-
-static void
-silcpurple_ftp_request_denied(PurpleXfer *x)
-{
-
-}
-
-void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
-			  SilcClientEntry client_entry, SilcUInt32 session_id,
-			  const char *hostname, SilcUInt16 port)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	SilcPurpleXfer xfer;
-
-	xfer = silc_calloc(1, sizeof(*xfer));
-	if (!xfer) {
-		silc_client_file_close(sg->client, sg->conn, session_id);
-		return;
-	}
-
-	xfer->sg = sg;
-	xfer->client_entry = client_entry;
-	xfer->session_id = session_id;
-	xfer->hostname = g_strdup(hostname);
-	xfer->port = port;
-	xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_RECEIVE,
-				   xfer->client_entry->nickname);
-	if (!xfer->xfer) {
-		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-		g_free(xfer->hostname);
-		silc_free(xfer);
-		return;
-	}
-	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_request_result);
-	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied);
-	purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel);
-	xfer->xfer->remote_ip = g_strdup(hostname);
-	xfer->xfer->remote_port = port;
-	xfer->xfer->data = xfer;
-
-	/* File transfer request */
-	purple_xfer_request(xfer->xfer);
-}
-
-static void
-silcpurple_ftp_send_cancel(PurpleXfer *x)
-{
-	SilcPurpleXfer xfer = x->data;
-	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-	purple_xfer_unref(xfer->xfer);
-	g_free(xfer->hostname);
-	silc_free(xfer);
-}
-
-static void
-silcpurple_ftp_send(PurpleXfer *x)
-{
-	SilcPurpleXfer xfer = x->data;
-	const char *name;
-	char *local_ip = NULL, *remote_ip = NULL;
-	gboolean local = TRUE;
-
-	name = purple_xfer_get_local_filename(x);
-
-	/* Do the same magic what we do with key agreement (see silcpurple_buddy.c)
-	   to see if we are behind NAT. */
-	if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock,
-					 NULL, &local_ip)) {
-		/* Check if the IP is private */
-		if (silcpurple_ip_is_private(local_ip)) {
-			local = FALSE;
-			/* Local IP is private, resolve the remote server IP to see whether
-			   we are talking to Internet or just on LAN. */
-			if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL,
-							&remote_ip))
-				if (silcpurple_ip_is_private(remote_ip))
-					/* We assume we are in LAN.  Let's provide the connection point. */
-					local = TRUE;
-		}
-	}
-
-	if (local && !local_ip)
-		local_ip = silc_net_localip();
-
-	/* Send the file */
-	silc_client_file_send(xfer->sg->client, xfer->sg->conn,
-			      silcpurple_ftp_monitor, xfer,
-			      local_ip, 0, !local, xfer->client_entry,
-			      name, &xfer->session_id);
-
-	silc_free(local_ip);
-	silc_free(remote_ip);
-}
-
-static void
-silcpurple_ftp_send_file_resolved(SilcClient client,
-				SilcClientConnection conn,
-				SilcClientEntry *clients,
-				SilcUInt32 clients_count,
-				void *context)
-{
-	PurpleConnection *gc = client->application;
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"),
-			   (const char *)context);
-		purple_notify_error(gc, _("Secure File Transfer"),
-				  _("Cannot send file"), tmp);
-		silc_free(context);
-		return;
-	}
-
-	silcpurple_ftp_send_file(client->application, (const char *)context, NULL);
-	silc_free(context);
-}
-
-PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
-	SilcPurpleXfer xfer;
-	char *nickname;
-
-	g_return_val_if_fail(name != NULL, NULL);
-
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return NULL;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, nickname, name,
-											&clients_count);
-	if (!clients) {
-		silc_client_get_clients(client, conn, nickname, NULL,
-								silcpurple_ftp_send_file_resolved,
-								strdup(name));
-		silc_free(nickname);
-		return NULL;
-	}
-
-	xfer = silc_calloc(1, sizeof(*xfer));
-
-	g_return_val_if_fail(xfer != NULL, NULL);
-
-	xfer->sg = sg;
-	xfer->client_entry = clients[0];
-	xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_SEND,
-							   xfer->client_entry->nickname);
-	if (!xfer->xfer) {
-		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-		g_free(xfer->hostname);
-		silc_free(xfer);
-		return NULL;
-	}
-	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send);
-	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied);
-	purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel);
-	xfer->xfer->data = xfer;
-
-	silc_free(clients);
-	silc_free(nickname);
-
-	return xfer->xfer;
-}
-
-void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file)
-{
-	PurpleXfer *xfer = silcpurple_ftp_new_xfer(gc, name);
-
-	g_return_if_fail(xfer != NULL);
-
-	/* Choose file to send */
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
--- a/libpurple/protocols/silc10/ops.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2063 +0,0 @@
-/*
-
-  silcpurple_ops.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-#include "imgstore.h"
-#include "wb.h"
-
-static void
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcChannelEntry channel,
-		     SilcMessagePayload payload, SilcChannelPrivateKey key,
-		     SilcMessageFlags flags, const unsigned char *message,
-		     SilcUInt32 message_len);
-static void
-silc_private_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcMessagePayload payload,
-		     SilcMessageFlags flags, const unsigned char *message,
-		     SilcUInt32 message_len);
-
-/* Message sent to the application by library. `conn' associates the
-   message to a specific connection.  `conn', however, may be NULL.
-   The `type' indicates the type of the message sent by the library.
-   The application can for example filter the message according the
-   type. */
-
-static void
-silc_say(SilcClient client, SilcClientConnection conn,
-	 SilcClientMessageType type, char *msg, ...)
-{
-	/* Nothing */
-}
-
-#ifdef HAVE_SILCMIME_H
-/* Processes incoming MIME message.  Can be private message or channel
-   message. */
-
-static void
-silcpurple_mime_message(SilcClient client, SilcClientConnection conn,
-		      SilcClientEntry sender, SilcChannelEntry channel,
-		      SilcMessagePayload payload, SilcChannelPrivateKey key,
-		      SilcMessageFlags flags, SilcMime mime,
-		      gboolean recursive)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	const char *type;
-	const unsigned char *data;
-	SilcUInt32 data_len;
-	PurpleMessageFlags cflags = 0;
-	PurpleConversation *convo = NULL;
-
-	if (!mime)
-		return;
-
-	/* Check for fragmented MIME message */
-	if (silc_mime_is_partial(mime)) {
-		if (!sg->mimeass)
-			sg->mimeass = silc_mime_assembler_alloc();
-
-		/* Defragment */
-		mime = silc_mime_assemble(sg->mimeass, mime);
-		if (!mime)
-			/* More fragments to come */
-			return;
-
-		/* Process the complete message */
-		silcpurple_mime_message(client, conn, sender, channel,
-				      payload, key, flags, mime, FALSE);
-		return;
-	}
-
-	/* Check for multipart message */
-	if (silc_mime_is_multipart(mime)) {
-		SilcMime p;
-		const char *mtype;
-		SilcDList parts = silc_mime_get_multiparts(mime, &mtype);
-
-		/* Only "mixed" type supported */
-		if (strcmp(mtype, "mixed"))
-			goto out;
-
-		silc_dlist_start(parts);
-		while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
-			/* Recursively process parts */
-			silcpurple_mime_message(client, conn, sender, channel,
-					      payload, key, flags, p, TRUE);
-		}
-		goto out;
-	}
-
-	/* Get content type and MIME data */
-	type = silc_mime_get_field(mime, "Content-Type");
-	if (!type)
-		goto out;
-	data = silc_mime_get_data(mime, &data_len);
-	if (!data)
-		goto out;
-
-	/* Process according to content type */
-
-	/* Plain text */
-	if (strstr(type, "text/plain")) {
-		/* Default is UTF-8, don't check for other charsets */
-		if (!strstr(type, "utf-8"))
-			goto out;
-
-		if (channel)
-			silc_channel_message(client, conn, sender, channel,
-					     payload, key,
-					     SILC_MESSAGE_FLAG_UTF8, data,
-					     data_len);
-		else
-			silc_private_message(client, conn, sender, payload,
-					     SILC_MESSAGE_FLAG_UTF8, data,
-					     data_len);
-		goto out;
-	}
-
-	/* Image */
-	if (strstr(type, "image/png") ||
-	    strstr(type, "image/jpeg") ||
-	    strstr(type, "image/gif") ||
-	    strstr(type, "image/tiff")) {
-		char tmp[32];
-		int imgid;
-
-		/* Get channel convo (if message is for channel) */
-		if (key && channel) {
-			GList *l;
-			SilcPurplePrvgrp prv;
-
-			for (l = sg->grps; l; l = l->next)
-				if (((SilcPurplePrvgrp)l->data)->key == key) {
-					prv = l->data;
-					convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-							prv->channel, sg->account);
-					break;
-				}
-		}
-		if (channel && !convo)
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								    channel->channel_name, sg->account);
-		if (channel && !convo)
-			goto out;
-
-		imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, "");
-		if (imgid) {
-			cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV;
-			g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid);
-
-			if (channel)
-				serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
-				 		 sender->nickname ?
-				 		  sender->nickname :
-						 "<unknown>", cflags,
-						 tmp, time(NULL));
-			else
-				serv_got_im(gc, sender->nickname ?
-					    sender->nickname : "<unknown>",
-					    tmp, cflags, time(NULL));
-
-			purple_imgstore_unref_by_id(imgid);
-			cflags = 0;
-		}
-		goto out;
-	}
-
-	/* Whiteboard message */
-	if (strstr(type, "application/x-wb") &&
-	    !purple_account_get_bool(sg->account, "block-wb", FALSE)) {
-		if (channel)
-			silcpurple_wb_receive_ch(client, conn, sender, channel,
-					       payload, flags, data, data_len);
-		else
-			silcpurple_wb_receive(client, conn, sender, payload,
-					    flags, data, data_len);
-		goto out;
-	}
-
- out:
-	if (!recursive)
-		silc_mime_free(mime);
-}
-#endif /* HAVE_SILCMIME_H */
-
-/* Message for a channel. The `sender' is the sender of the message
-   The `channel' is the channel. The `message' is the message.  Note
-   that `message' maybe NULL.  The `flags' indicates message flags
-   and it is used to determine how the message can be interpreted
-   (like it may tell the message is multimedia message). */
-
-static void
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcChannelEntry channel,
-		     SilcMessagePayload payload, SilcChannelPrivateKey key,
-		     SilcMessageFlags flags, const unsigned char *message,
-		     SilcUInt32 message_len)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	PurpleConversation *convo = NULL;
-	char *msg, *tmp;
-
-	if (!message)
-		return;
-
-	if (key) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->key == key) {
-				prv = l->data;
-				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-										prv->channel, sg->account);
-				break;
-			}
-	}
-	if (!convo)
-		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
-	if (!convo)
-		return;
-
-	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
-	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
-		/* XXX */
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_DATA) {
-		/* Process MIME message */
-#ifdef HAVE_SILCMIME_H
-		SilcMime mime;
-		mime = silc_mime_decode(message, message_len);
-		silcpurple_mime_message(client, conn, sender, channel, payload,
-				      key, flags, mime, FALSE);
-#else
-		char type[128], enc[128];
-		unsigned char *data;
-		SilcUInt32 data_len;
-
-		memset(type, 0, sizeof(type));
-		memset(enc, 0, sizeof(enc));
-
-		if (!silc_mime_parse(message, message_len, NULL, 0,
-		    type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data,
-		    &data_len))
-			return;
-
-		if (!strcmp(type, "application/x-wb") &&
-		    !strcmp(enc, "binary") &&
-		    !purple_account_get_bool(sg->account, "block-wb", FALSE))
-			silcpurple_wb_receive_ch(client, conn, sender, channel,
-					       payload, flags, data, data_len);
-#endif
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_ACTION) {
-		msg = g_strdup_printf("/me %s",
-				      (const char *)message);
-		if (!msg)
-			return;
-
-		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 ?
-				 sender->nickname : "<unknown>", 0,
-				 tmp, time(NULL));
-		g_free(tmp);
-		g_free(msg);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_NOTICE) {
-		msg = g_strdup_printf("(notice) <I>%s</I> %s",
-				      sender->nickname ?
-				      sender->nickname : "<unknown>",
-				      (const char *)message);
-		if (!msg)
-			return;
-
-		/* Send to Purple */
-		purple_conversation_write(convo, NULL, (const char *)msg,
-					PURPLE_MESSAGE_SYSTEM, time(NULL));
-		g_free(msg);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		tmp = g_markup_escape_text((const char *)message, -1);
-		/* Send to Purple */
-		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
-				 sender->nickname ?
-				 sender->nickname : "<unknown>", 0,
-				 tmp, time(NULL));
-		g_free(tmp);
-	}
-}
-
-
-/* Private message to the client. The `sender' is the sender of the
-   message. The message is `message'and maybe NULL.  The `flags'
-   indicates message flags  and it is used to determine how the message
-   can be interpreted (like it may tell the message is multimedia
-   message). */
-
-static void
-silc_private_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcMessagePayload payload,
-		     SilcMessageFlags flags, const unsigned char *message,
-		     SilcUInt32 message_len)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	PurpleConversation *convo = NULL;
-	char *msg, *tmp;
-
-	if (!message)
-		return;
-
-	if (sender->nickname)
-		/* XXX - Should this be PURPLE_CONV_TYPE_IM? */
-		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-								sender->nickname, sg->account);
-
-	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
-	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
-		/* XXX */
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_DATA) {
-#ifdef HAVE_SILCMIME_H
-		/* Process MIME message */
-		SilcMime mime;
-		mime = silc_mime_decode(message, message_len);
-		silcpurple_mime_message(client, conn, sender, NULL, payload,
-				      NULL, flags, mime, FALSE);
-#else
-		char type[128], enc[128];
-		unsigned char *data;
-		SilcUInt32 data_len;
-
-		memset(type, 0, sizeof(type));
-		memset(enc, 0, sizeof(enc));
-
-		if (!silc_mime_parse(message, message_len, NULL, 0,
-		    type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data,
-		    &data_len))
-			return;
-
-		if (!strcmp(type, "application/x-wb") &&
-		    !strcmp(enc, "binary") &&
-		    !purple_account_get_bool(sg->account, "block-wb", FALSE))
-			silcpurple_wb_receive(client, conn, sender, payload,
-					    flags, data, data_len);
-#endif
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_ACTION && convo) {
-		msg = g_strdup_printf("/me %s",
-				      (const char *)message);
-		if (!msg)
-			return;
-
-		tmp = g_markup_escape_text(msg, -1);
-		/* Send to Purple */
-		serv_got_im(gc, sender->nickname ?
-			    sender->nickname : "<unknown>",
-			    tmp, 0, time(NULL));
-		g_free(msg);
-		g_free(tmp);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) {
-		msg = g_strdup_printf("(notice) <I>%s</I> %s",
-				      sender->nickname ?
-				      sender->nickname : "<unknown>",
-				      (const char *)message);
-		if (!msg)
-			return;
-
-		/* Send to Purple */
-		purple_conversation_write(convo, NULL, (const char *)msg,
-					PURPLE_MESSAGE_SYSTEM, time(NULL));
-		g_free(msg);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		tmp = g_markup_escape_text((const char *)message, -1);
-		/* Send to Purple */
-		serv_got_im(gc, sender->nickname ?
-			    sender->nickname : "<unknown>",
-			    tmp, 0, time(NULL));
-		g_free(tmp);
-	}
-}
-
-
-/* Notify message to the client. The notify arguments are sent in the
-   same order as servers sends them. The arguments are same as received
-   from the server except for ID's.  If ID is received application receives
-   the corresponding entry to the ID. For example, if Client ID is received
-   application receives SilcClientEntry.  Also, if the notify type is
-   for channel the channel entry is sent to application (even if server
-   does not send it because client library gets the channel entry from
-   the Channel ID in the packet's header). */
-
-static void
-silc_notify(SilcClient client, SilcClientConnection conn,
-	    SilcNotifyType type, ...)
-{
-	va_list va;
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	PurpleConversation *convo;
-	SilcClientEntry client_entry, client_entry2;
-	SilcChannelEntry channel;
-	SilcServerEntry server_entry;
-	SilcIdType idtype;
-	void *entry;
-	SilcUInt32 mode;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	char buf[512], buf2[512], *tmp, *name;
-	SilcNotifyType notify;
-	PurpleBuddy *b;
-	int i;
-
-	va_start(va, type);
-	memset(buf, 0, sizeof(buf));
-
-	switch (type) {
-
-	case SILC_NOTIFY_TYPE_NONE:
-		break;
-
-	case SILC_NOTIFY_TYPE_INVITE:
-		{
-			GHashTable *components;
-			va_arg(va, SilcChannelEntry);
-			name = va_arg(va, char *);
-			client_entry = va_arg(va, SilcClientEntry);
-
-			components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-			g_hash_table_insert(components, strdup("channel"), strdup(name));
-			serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components);
-		}
-		break;
-
-	case SILC_NOTIFY_TYPE_JOIN:
-		client_entry = va_arg(va, SilcClientEntry);
-		channel = va_arg(va, SilcChannelEntry);
-
-		/* If we joined channel, do nothing */
-		if (client_entry == conn->local_entry)
-			break;
-
-		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
-		if (!convo)
-			break;
-
-		/* Join user to channel */
-		g_snprintf(buf, sizeof(buf), "%s@%s",
-			   client_entry->username, client_entry->hostname);
-		purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo),
-					g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_LEAVE:
-		client_entry = va_arg(va, SilcClientEntry);
-		channel = va_arg(va, SilcChannelEntry);
-
-		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
-		if (!convo)
-			break;
-
-		/* Remove user from channel */
-		purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-					   client_entry->nickname, NULL);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_SIGNOFF:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);
-
-		if (!client_entry->nickname)
-			break;
-
-		/* Remove from all channels */
-		silc_hash_table_list(client_entry->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									chu->channel->channel_name, sg->account);
-			if (!convo)
-				continue;
-			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-						   client_entry->nickname,
-						   tmp);
-		}
-		silc_hash_table_list_reset(&htl);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_TOPIC_SET:
-		{
-			char *esc, *tmp2;
-			idtype = va_arg(va, int);
-			entry = va_arg(va, void *);
-			tmp = va_arg(va, char *);
-			channel = va_arg(va, SilcChannelEntry);
-
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									channel->channel_name, sg->account);
-			if (!convo)
-				break;
-
-			if (!tmp)
-				break;
-
-			esc = g_markup_escape_text(tmp, -1);
-			tmp2 = purple_markup_linkify(esc);
-			g_free(esc);
-
-			if (idtype == SILC_ID_CLIENT) {
-				client_entry = (SilcClientEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-						_("%s has changed the topic of <I>%s</I> to: %s"),
-						client_entry->nickname, channel->channel_name, tmp2);
-				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
-						buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo),
-						client_entry->nickname, tmp);
-			} else if (idtype == SILC_ID_SERVER) {
-				server_entry = (SilcServerEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-						_("%s has changed the topic of <I>%s</I> to: %s"),
-						server_entry->server_name, channel->channel_name, tmp2);
-				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), server_entry->server_name,
-						buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo),
-						server_entry->server_name, tmp);
-			} else if (idtype == SILC_ID_CHANNEL) {
-				channel = (SilcChannelEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-						_("%s has changed the topic of <I>%s</I> to: %s"),
-						channel->channel_name, channel->channel_name, tmp2);
-				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
-						buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo),
-						channel->channel_name, tmp);
-			} else {
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp);
-			}
-
-			g_free(tmp2);
-
-			break;
-
-		}
-	case SILC_NOTIFY_TYPE_NICK_CHANGE:
-		client_entry = va_arg(va, SilcClientEntry);
-		client_entry2 = va_arg(va, SilcClientEntry);
-
-		if (!strcmp(client_entry->nickname, client_entry2->nickname))
-			break;
-
-		/* Change nick on all channels */
-		silc_hash_table_list(client_entry2->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									chu->channel->channel_name, sg->account);
-			if (!convo)
-				continue;
-			if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname))
-				purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo),
-										   client_entry->nickname,
-										   client_entry2->nickname);
-		}
-		silc_hash_table_list_reset(&htl);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_CMODE_CHANGE:
-		idtype = va_arg(va, int);
-		entry = va_arg(va, void *);
-		mode = va_arg(va, SilcUInt32);
-		(void)va_arg(va, char *);
-		(void)va_arg(va, char *);
-		(void)va_arg(va, char *);
-		(void)va_arg(va, SilcPublicKey);
-		(void)va_arg(va, SilcBuffer);
-		channel = va_arg(va, SilcChannelEntry);
-
-		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
-		if (!convo)
-			break;
-
-		if (idtype == SILC_ID_CLIENT)
-			name = ((SilcClientEntry)entry)->nickname;
-		else if (idtype == SILC_ID_SERVER)
-			name = ((SilcServerEntry)entry)->server_name;
-		else
-			name = ((SilcChannelEntry)entry)->channel_name;
-		if (!name)
-			break;
-
-		if (mode) {
-			silcpurple_get_chmode_string(mode, buf2, sizeof(buf2));
-			g_snprintf(buf, sizeof(buf),
-				   _("<I>%s</I> set channel <I>%s</I> modes to: %s"), name,
-				   channel->channel_name, buf2);
-		} else {
-			g_snprintf(buf, sizeof(buf),
-				   _("<I>%s</I> removed all channel <I>%s</I> modes"), name,
-				   channel->channel_name);
-		}
-		purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
-				     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-		break;
-
-	case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
-		{
-			PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE;
-			idtype = va_arg(va, int);
-			entry = va_arg(va, void *);
-			mode = va_arg(va, SilcUInt32);
-			client_entry2 = va_arg(va, SilcClientEntry);
-			channel = va_arg(va, SilcChannelEntry);
-
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									channel->channel_name, sg->account);
-			if (!convo)
-				break;
-
-			if (idtype == SILC_ID_CLIENT)
-				name = ((SilcClientEntry)entry)->nickname;
-			else if (idtype == SILC_ID_SERVER)
-				name = ((SilcServerEntry)entry)->server_name;
-			else
-				name = ((SilcChannelEntry)entry)->channel_name;
-			if (!name)
-				break;
-
-			if (mode) {
-				silcpurple_get_chumode_string(mode, buf2, sizeof(buf2));
-				g_snprintf(buf, sizeof(buf),
-						_("<I>%s</I> set <I>%s's</I> modes to: %s"), name,
-						client_entry2->nickname, buf2);
-				if (mode & SILC_CHANNEL_UMODE_CHANFO)
-					flags |= PURPLE_CBFLAGS_FOUNDER;
-				if (mode & SILC_CHANNEL_UMODE_CHANOP)
-					flags |= PURPLE_CBFLAGS_OP;
-			} else {
-				g_snprintf(buf, sizeof(buf),
-						_("<I>%s</I> removed all <I>%s's</I> modes"), name,
-						client_entry2->nickname);
-			}
-			purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
-					buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-			purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags);
-			break;
-		}
-
-	case SILC_NOTIFY_TYPE_MOTD:
-		tmp = va_arg(va, char *);
-		silc_free(sg->motd);
-		sg->motd = silc_memdup(tmp, strlen(tmp));
-		break;
-
-	case SILC_NOTIFY_TYPE_KICKED:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);
-		client_entry2 = va_arg(va, SilcClientEntry);
-		channel = va_arg(va, SilcChannelEntry);
-
-		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
-		if (!convo)
-			break;
-
-		if (client_entry == conn->local_entry) {
-			/* Remove us from channel */
-			g_snprintf(buf, sizeof(buf),
-				   _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"),
-				   channel->channel_name, client_entry2->nickname,
-				   tmp ? tmp : "");
-			purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
-					     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-			serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
-		} else {
-			/* Remove user from channel */
-			g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"),
-				   client_entry2->nickname, tmp ? tmp : "");
-			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-						   client_entry->nickname,
-						   buf);
-		}
-
-		break;
-
-	case SILC_NOTIFY_TYPE_KILLED:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);
-		idtype = va_arg(va, int);
-		entry = va_arg(va, SilcClientEntry);
-
-		if (!client_entry->nickname)
-			break;
-
-		if (client_entry == conn->local_entry) {
-			if (idtype == SILC_ID_CLIENT) {
-				client_entry2 = (SilcClientEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("You have been killed by %s (%s)"),
-					   client_entry2->nickname, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_SERVER) {
-				server_entry = (SilcServerEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("You have been killed by %s (%s)"),
-					   server_entry->server_name, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_CHANNEL) {
-				channel = (SilcChannelEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("You have been killed by %s (%s)"),
-					   channel->channel_name, tmp ? tmp : "");
-			}
-
-			/* Remove us from all channels */
-			silc_hash_table_list(client_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-										chu->channel->channel_name, sg->account);
-				if (!convo)
-					continue;
-				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
-						     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
-				serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
-			}
-			silc_hash_table_list_reset(&htl);
-
-		} else {
-			if (idtype == SILC_ID_CLIENT) {
-				client_entry2 = (SilcClientEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("Killed by %s (%s)"),
-					   client_entry2->nickname, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_SERVER) {
-				server_entry = (SilcServerEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("Killed by %s (%s)"),
-					   server_entry->server_name, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_CHANNEL) {
-				channel = (SilcChannelEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("Killed by %s (%s)"),
-					   channel->channel_name, tmp ? tmp : "");
-			}
-
-			/* Remove user from all channels */
-			silc_hash_table_list(client_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-										chu->channel->channel_name, sg->account);
-				if (!convo)
-					continue;
-				purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-							   client_entry->nickname, tmp);
-			}
-			silc_hash_table_list_reset(&htl);
-		}
-
-		break;
-
-	case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
-		break;
-
-	case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
-		{
-			int i;
-			SilcClientEntry *clients;
-			SilcUInt32 clients_count;
-
-			(void)va_arg(va, void *);
-			clients = va_arg(va, SilcClientEntry *);
-			clients_count = va_arg(va, SilcUInt32);
-
-			for (i = 0; i < clients_count; i++) {
-				if (!clients[i]->nickname)
-					break;
-
-				/* Remove from all channels */
-				silc_hash_table_list(clients[i]->channels, &htl);
-				while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-					convo =
-						purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-											chu->channel->channel_name, sg->account);
-					if (!convo)
-						continue;
-					purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-								   clients[i]->nickname,
-								   _("Server signoff"));
-				}
-				silc_hash_table_list_reset(&htl);
-			}
-		}
-		break;
-
-	case SILC_NOTIFY_TYPE_ERROR:
-		{
-			SilcStatus error = va_arg(va, int);
-			purple_notify_error(gc, "Error Notify",
-					  silc_get_status_message(error),
-					  NULL);
-		}
-		break;
-
-	case SILC_NOTIFY_TYPE_WATCH:
-		{
-			SilcPublicKey public_key;
-			unsigned char *pk;
-			SilcUInt32 pk_len;
-			char *fingerprint;
-
-			client_entry = va_arg(va, SilcClientEntry);
-			(void)va_arg(va, char *);
-			mode = va_arg(va, SilcUInt32);
-			notify = va_arg(va, int);
-			public_key = va_arg(va, SilcPublicKey);
-
-			b = NULL;
-			if (public_key) {
-				PurpleBlistNode *gnode, *cnode, *bnode;
-				const char *f;
-
-				pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-				if (!pk)
-					break;
-				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-				for (i = 0; i < strlen(fingerprint); i++)
-					if (fingerprint[i] == ' ')
-						fingerprint[i] = '_';
-				g_snprintf(buf, sizeof(buf) - 1,
-					   "%s" G_DIR_SEPARATOR_S "clientkeys"
-					   G_DIR_SEPARATOR_S "clientkey_%s.pub",
-					   silcpurple_silcdir(), fingerprint);
-				silc_free(fingerprint);
-				silc_free(pk);
-
-				/* Find buddy by associated public key */
-				for (gnode = purple_get_blist()->root; gnode;
-				     gnode = gnode->next) {
-					if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
-						continue;
-					for (cnode = gnode->child; cnode; cnode = cnode->next) {
-						if( !PURPLE_BLIST_NODE_IS_CONTACT(cnode))
-							continue;
-						for (bnode = cnode->child; bnode;
-						     bnode = bnode->next) {
-							if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
-								continue;
-							b = (PurpleBuddy *)bnode;
-							if (b->account != gc->account)
-								continue;
-							f = purple_blist_node_get_string(bnode, "public-key");
-							if (f && !strcmp(f, buf))
-								goto cont;
-							b = NULL;
-						}
-					}
-				}
-			}
-		cont:
-			if (!b) {
-				/* Find buddy by nickname */
-				b = purple_find_buddy(sg->account, client_entry->nickname);
-				if (!b) {
-					purple_debug_warning("silc", "WATCH for %s, unknown buddy\n",
-						client_entry->nickname);
-					break;
-				}
-			}
-
-			silc_free(b->proto_data);
-			b->proto_data = silc_memdup(client_entry->id,
-						    sizeof(*client_entry->id));
-			if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
-				break;
-			} else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
-				/* See if client was away and is now present */
-				if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
-					      SILC_UMODE_BUSY | SILC_UMODE_PAGE |
-					      SILC_UMODE_DETACHED)) &&
-				    (client_entry->mode & SILC_UMODE_GONE ||
-				     client_entry->mode & SILC_UMODE_INDISPOSED ||
-				     client_entry->mode & SILC_UMODE_BUSY ||
-				     client_entry->mode & SILC_UMODE_PAGE ||
-				     client_entry->mode & SILC_UMODE_DETACHED)) {
-					client_entry->mode = mode;
-					purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
-				}
-				else if ((mode & SILC_UMODE_GONE) ||
-					 (mode & SILC_UMODE_INDISPOSED) ||
-					 (mode & SILC_UMODE_BUSY) ||
-					 (mode & SILC_UMODE_PAGE) ||
-					 (mode & SILC_UMODE_DETACHED)) {
-					client_entry->mode = mode;
-					purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-				}
-			} else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
-				   notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF ||
-				   notify == SILC_NOTIFY_TYPE_KILLED) {
-				client_entry->mode = mode;
-				purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-			} else if (notify == SILC_NOTIFY_TYPE_NONE) {
-				client_entry->mode = mode;
-				purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
-			}
-		}
-		break;
-
-	default:
-		purple_debug_info("silc", "Unhandled notification: %d\n", type);
-		break;
-	}
-
-	va_end(va);
-}
-
-
-/* Command handler. This function is called always in the command function.
-   If error occurs it will be called as well. `conn' is the associated
-   client connection. `cmd_context' is the command context that was
-   originally sent to the command. `success' is FALSE if error occurred
-   during command. `command' is the command being processed. It must be
-   noted that this is not reply from server. This is merely called just
-   after application has called the command. Just to tell application
-   that the command really was processed. */
-
-static void
-silc_command(SilcClient client, SilcClientConnection conn,
-	     SilcClientCommandContext cmd_context, bool success,
-	     SilcCommand command, SilcStatus status)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-
-	switch (command) {
-
-	case SILC_COMMAND_CMODE:
-		if (cmd_context->argc == 3 &&
-		    !strcmp((char *)cmd_context->argv[2], "+C"))
-			sg->chpk = TRUE;
-		else
-			sg->chpk = FALSE;
-		break;
-
-	default:
-		break;
-	}
-}
-
-#if 0
-static void
-silcpurple_whois_more(SilcClientEntry client_entry, gint id)
-{
-	SilcAttributePayload attr;
-	SilcAttribute attribute;
-	char *buf;
-	GString *s;
-	SilcVCardStruct vcard;
-	int i;
-
-	if (id != 0)
-		return;
-
-	memset(&vcard, 0, sizeof(vcard));
-
-	s = g_string_new("");
-
-	silc_dlist_start(client_entry->attrs);
-	while ((attr = silc_dlist_get(client_entry->attrs)) != SILC_LIST_END) {
-		attribute = silc_attribute_get_attribute(attr);
-		switch (attribute) {
-
-		case SILC_ATTRIBUTE_USER_INFO:
-			if (!silc_attribute_get_object(attr, (void *)&vcard,
-						       sizeof(vcard)))
-				continue;
-			g_string_append_printf(s, "%s:\n\n", _("Personal Information"));
-			if (vcard.full_name)
-				g_string_append_printf(s, "%s:\t\t%s\n",
-						       _("Full Name"),
-						       vcard.full_name);
-			if (vcard.first_name)
-				g_string_append_printf(s, "%s:\t%s\n",
-						       _("First Name"),
-						       vcard.first_name);
-			if (vcard.middle_names)
-				g_string_append_printf(s, "%s:\t%s\n",
-						       _("Middle Name"),
-						       vcard.middle_names);
-			if (vcard.family_name)
-				g_string_append_printf(s, "%s:\t%s\n",
-						       _("Family Name"),
-						       vcard.family_name);
-			if (vcard.nickname)
-				g_string_append_printf(s, "%s:\t\t%s\n",
-						       _("Nickname"),
-						       vcard.nickname);
-			if (vcard.bday)
-				g_string_append_printf(s, "%s:\t\t%s\n",
-						       _("Birth Day"),
-						       vcard.bday);
-			if (vcard.title)
-				g_string_append_printf(s, "%s:\t\t%s\n",
-						       _("Job Title"),
-						       vcard.title);
-			if (vcard.role)
-				g_string_append_printf(s, "%s:\t\t%s\n",
-						       _("Job Role"),
-						       vcard.role);
-			if (vcard.org_name)
-				g_string_append_printf(s, "%s:\t%s\n",
-						       _("Organization"),
-						       vcard.org_name);
-			if (vcard.org_unit)
-				g_string_append_printf(s, "%s:\t\t%s\n",
-						       _("Unit"),
-						       vcard.org_unit);
-			if (vcard.url)
-				g_string_append_printf(s, "%s:\t%s\n",
-						       _("Homepage"),
-						       vcard.url);
-			if (vcard.label)
-				g_string_append_printf(s, "%s:\t%s\n",
-						       _("Address"),
-						       vcard.label);
-			for (i = 0; i < vcard.num_tels; i++) {
-				if (vcard.tels[i].telnum)
-					g_string_append_printf(s, "%s:\t\t\t%s\n",
-							       _("Phone"),
-							       vcard.tels[i].telnum);
-			}
-			for (i = 0; i < vcard.num_emails; i++) {
-				if (vcard.emails[i].address)
-					g_string_append_printf(s, "%s:\t\t%s\n",
-							       _("Email"),
-							       vcard.emails[i].address);
-			}
-			if (vcard.note)
-				g_string_append_printf(s, "\n%s:\t\t%s\n",
-						       _("Note"),
-						       vcard.note);
-			break;
-		}
-	}
-
-	buf = g_string_free(s, FALSE);
-	purple_notify_info(NULL, _("User Information"), _("User Information"),
-			 buf);
-	g_free(buf);
-}
-#endif
-
-/* Command reply handler. This function is called always in the command reply
-   function. If error occurs it will be called as well. Normal scenario
-   is that it will be called after the received command data has been parsed
-   and processed. The function is used to pass the received command data to
-   the application.
-
-   `conn' is the associated client connection. `cmd_payload' is the command
-   payload data received from server and it can be ignored. It is provided
-   if the application would like to re-parse the received command data,
-   however, it must be noted that the data is parsed already by the library
-   thus the payload can be ignored. `success' is FALSE if error occurred.
-   In this case arguments are not sent to the application. The `status' is
-   the command reply status server returned. The `command' is the command
-   reply being processed. The function has variable argument list and each
-   command defines the number and type of arguments it passes to the
-   application (on error they are not sent). */
-
-static void
-silc_command_reply(SilcClient client, SilcClientConnection conn,
-		   SilcCommandPayload cmd_payload, bool success,
-		   SilcCommand command, SilcStatus status, ...)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	PurpleConversation *convo;
-	va_list vp;
-
-	va_start(vp, status);
-
-	switch (command) {
-	case SILC_COMMAND_JOIN:
-		{
-			SilcChannelEntry channel_entry;
-
-			if (!success) {
-				purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"),
-						  silc_get_status_message(status));
-				return;
-			}
-
-			(void)va_arg(vp, char *);
-			channel_entry = va_arg(vp, SilcChannelEntry);
-
-			/* Resolve users on channel */
-			silc_client_get_clients_by_channel(client, conn, channel_entry,
-							   silcpurple_chat_join_done,
-							   channel_entry);
-		}
-		break;
-
-	case SILC_COMMAND_LEAVE:
-		break;
-
-	case SILC_COMMAND_USERS:
-		break;
-
-	case SILC_COMMAND_WHOIS:
-		{
-			SilcUInt32 idle, mode;
-			SilcBuffer channels, user_modes;
-			SilcClientEntry client_entry;
-			char tmp[1024], *tmp2;
-			char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
-			PurpleNotifyUserInfo *user_info;
-
-			if (!success) {
-				purple_notify_error(gc, _("User Information"),
-						_("Cannot get user information"),
-						silc_get_status_message(status));
-				break;
-			}
-
-			client_entry = va_arg(vp, SilcClientEntry);
-			if (!client_entry->nickname)
-				break;
-			(void)va_arg(vp, char *);
-			(void)va_arg(vp, char *);
-			(void)va_arg(vp, char *);
-			channels = va_arg(vp, SilcBuffer);
-			mode = va_arg(vp, SilcUInt32);
-			idle = va_arg(vp, SilcUInt32);
-			(void)va_arg(vp, unsigned char *);
-			user_modes = va_arg(vp, SilcBuffer);
-
-			user_info = purple_notify_user_info_new();
-			tmp2 = g_markup_escape_text(client_entry->nickname, -1);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2);
-			g_free(tmp2);
-			if (client_entry->realname) {
-				tmp2 = g_markup_escape_text(client_entry->realname, -1);
-				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2);
-				g_free(tmp2);
-			}
-			if (client_entry->username) {
-				tmp2 = g_markup_escape_text(client_entry->username, -1);
-				if (client_entry->hostname) {
-					gchar *tmp3;
-					tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname);
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
-					g_free(tmp3);
-				} else
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp2);
-				g_free(tmp2);
-			}
-
-			if (client_entry->mode) {
-				memset(tmp, 0, sizeof(tmp));
-				silcpurple_get_umode_string(client_entry->mode,
-						tmp, sizeof(tmp) - strlen(tmp));
-				purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
-			}
-
-			silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
-			if (moodstr) {
-				purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr);
-				g_free(moodstr);
-			}
-
-			if (statusstr) {
-				tmp2 = g_markup_escape_text(statusstr, -1);
-				purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2);
-				g_free(statusstr);
-				g_free(tmp2);
-			}
-
-			if (contactstr) {
-				purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr);
-				g_free(contactstr);
-			}
-
-			if (langstr) {
-				purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr);
-				g_free(langstr);
-			}
-
-			if (devicestr) {
-				purple_notify_user_info_add_pair(user_info, _("Device"), devicestr);
-				g_free(devicestr);
-			}
-
-			if (tzstr) {
-				purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr);
-				g_free(tzstr);
-			}
-
-			if (geostr) {
-				purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr);
-				g_free(geostr);
-			}
-
-			if (client_entry->server)
-				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
-
-			if (channels && user_modes) {
-				SilcUInt32 *umodes;
-				SilcDList list =
-					silc_channel_payload_parse_list(channels->data,
-							channels->len);
-				if (list && silc_get_mode_list(user_modes,
-							silc_dlist_count(list),
-							&umodes)) {
-					SilcChannelPayload entry;
-					int i = 0;
-
-					memset(tmp, 0, sizeof(tmp));
-					silc_dlist_start(list);
-					while ((entry = silc_dlist_get(list))
-							!= SILC_LIST_END) {
-						SilcUInt32 name_len;
-						char *m = silc_client_chumode_char(umodes[i++]);
-						char *name = (char *)silc_channel_get_name(entry, &name_len);
-						if (m)
-							silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m));
-						silc_strncat(tmp, sizeof(tmp) - 1, name, name_len);
-						silc_strncat(tmp, sizeof(tmp) - 1, "  ", 1);
-						silc_free(m);
-
-					}
-					tmp2 = g_markup_escape_text(tmp, -1);
-					purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2);
-					g_free(tmp2);
-					silc_free(umodes);
-				}
-			}
-
-			if (client_entry->public_key) {
-				char *fingerprint, *babbleprint;
-				unsigned char *pk;
-				SilcUInt32 pk_len;
-				pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
-				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-				babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-				purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
-				purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
-				silc_free(fingerprint);
-				silc_free(babbleprint);
-				silc_free(pk);
-			}
-
-#if 0 /* XXX for now, let's not show attrs here */
-			if (client_entry->attrs)
-				purple_request_action(gc, _("User Information"),
-						_("User Information"),
-						buf, 1, client_entry, 2,
-						_("OK"), G_CALLBACK(silcpurple_whois_more),
-						_("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL);
-			else
-#endif
-			purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL);
-			purple_notify_user_info_destroy(user_info);
-		}
-		break;
-
-	case SILC_COMMAND_WHOWAS:
-		{
-			SilcClientEntry client_entry;
-			char *nickname, *realname, *username, *tmp;
-			PurpleNotifyUserInfo *user_info;
-
-			if (!success) {
-				purple_notify_error(gc, _("User Information"),
-						  _("Cannot get user information"),
-						  silc_get_status_message(status));
-				break;
-			}
-
-			client_entry = va_arg(vp, SilcClientEntry);
-			nickname = va_arg(vp, char *);
-			username = va_arg(vp, char *);
-			realname = va_arg(vp, char *);
-			if (!nickname)
-				break;
-
-			user_info = purple_notify_user_info_new();
-			tmp = g_markup_escape_text(nickname, -1);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
-			g_free(tmp);
-			if (realname) {
-				tmp = g_markup_escape_text(realname, -1);
-				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp);
-				g_free(tmp);
-			}
-			if (username) {
-				tmp = g_markup_escape_text(username, -1);
-				if (client_entry && client_entry->hostname) {
-					gchar *tmp3;
-					tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname);
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
-					g_free(tmp3);
-				} else
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
-				g_free(tmp);
-			}
-			if (client_entry && client_entry->server)
-				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
-
-
-			if (client_entry && client_entry->public_key) {
-				char *fingerprint, *babbleprint;
-				unsigned char *pk;
-				SilcUInt32 pk_len;
-				pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
-				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-				babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-				purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
-				purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
-				silc_free(fingerprint);
-				silc_free(babbleprint);
-				silc_free(pk);
-			}
-
-			purple_notify_userinfo(gc, nickname, user_info, NULL, NULL);
-			purple_notify_user_info_destroy(user_info);
-		}
-		break;
-
-	case SILC_COMMAND_DETACH:
-		if (!success) {
-			purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"),
-					  silc_get_status_message(status));
-			return;
-		}
-		break;
-
-	case SILC_COMMAND_TOPIC:
-		{
-			SilcChannelEntry channel;
-
-			if (!success) {
-				purple_notify_error(gc, _("Topic"), _("Cannot set topic"),
-						  silc_get_status_message(status));
-				return;
-			}
-
-			channel = va_arg(vp, SilcChannelEntry);
-
-			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									channel->channel_name, sg->account);
-			if (!convo) {
-				purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n",
-								 channel->channel_name);
-				break;
-			}
-
-			/* Set topic */
-			if (channel->topic)
-				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic);
-		}
-		break;
-
-	case SILC_COMMAND_NICK:
-		{
-			/* I don't think we should need to do this because the server should
-			 * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own
-			 * nick, but it isn't, so we deal with it here instead. Stu. */
-			SilcClientEntry local_entry;
-			SilcHashTableList htl;
-			SilcChannelUser chu;
-			const char *oldnick;
-
-			if (!success) {
-				purple_notify_error(gc, _("Nick"), _("Failed to change nickname"),
-						silc_get_status_message(status));
-				return;
-			}
-
-			local_entry = va_arg(vp, SilcClientEntry);
-
-			/* Change nick on all channels */
-			silc_hash_table_list(local_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									chu->channel->channel_name, sg->account);
-				if (!convo)
-					continue;
-				oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo));
-				if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) {
-					purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo),
-							oldnick, local_entry->nickname);
-					purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname);
-				}
-			}
-			silc_hash_table_list_reset(&htl);
-
-			purple_connection_set_display_name(gc, local_entry->nickname);
-		}
-		break;
-
-	case SILC_COMMAND_LIST:
-		{
-			char *topic, *name;
-			int usercount;
-			PurpleRoomlistRoom *room;
-
-			if (sg->roomlist_cancelled)
-				break;
-
-			if (!success) {
-				purple_notify_error(gc, _("Error"), _("Error retrieving room list"),
-						  silc_get_status_message(status));
-				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
-				purple_roomlist_unref(sg->roomlist);
-				sg->roomlist = NULL;
-				return;
-			}
-
-			(void)va_arg(vp, SilcChannelEntry);
-			name = va_arg(vp, char *);
-			if (!name) {
-				purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"),
-						  silc_get_status_message(status));
-				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
-				purple_roomlist_unref(sg->roomlist);
-				sg->roomlist = NULL;
-				return;
-			}
-			topic = va_arg(vp, char *);
-			usercount = va_arg(vp, int);
-
-			room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL);
-			purple_roomlist_room_add_field(sg->roomlist, room, name);
-			purple_roomlist_room_add_field(sg->roomlist, room,
-						     SILC_32_TO_PTR(usercount));
-			purple_roomlist_room_add_field(sg->roomlist, room,
-						     topic ? topic : "");
-			purple_roomlist_room_add(sg->roomlist, room);
-
-			if (status == SILC_STATUS_LIST_END ||
-			    status == SILC_STATUS_OK) {
-				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
-				purple_roomlist_unref(sg->roomlist);
-				sg->roomlist = NULL;
-			}
-		}
-		break;
-
-	case SILC_COMMAND_GETKEY:
-		{
-			SilcPublicKey public_key;
-
-			if (!success) {
-				purple_notify_error(gc, _("Get Public Key"),
-						  _("Cannot fetch the public key"),
-						  silc_get_status_message(status));
-				return;
-			}
-
-			(void)va_arg(vp, SilcUInt32);
-			(void)va_arg(vp, void *);
-			public_key = va_arg(vp, SilcPublicKey);
-
-			if (!public_key)
-				purple_notify_error(gc, _("Get Public Key"),
-						  _("Cannot fetch the public key"),
-						  _("No public key was received"));
-		}
-		break;
-
-	case SILC_COMMAND_INFO:
-		{
-
-			char *server_name;
-			char *server_info;
-			char tmp[256];
-
-			if (!success) {
-				purple_notify_error(gc, _("Server Information"),
-						  _("Cannot get server information"),
-						  silc_get_status_message(status));
-				return;
-			}
-
-			(void)va_arg(vp, SilcServerEntry);
-			server_name = va_arg(vp, char *);
-			server_info = va_arg(vp, char *);
-
-			if (server_name && server_info) {
-				g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s",
-					   server_name, server_info);
-				purple_notify_info(gc, NULL, _("Server Information"), tmp);
-			}
-		}
-		break;
-
-	case SILC_COMMAND_STATS:
-		{
-			SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops,
-			my_router_ops, cell_clients, cell_channels, cell_servers,
-			clients, channels, servers, routers, server_ops, router_ops;
-			SilcUInt32 buffer_length;
-			SilcBufferStruct buf;
-
-			unsigned char *server_stats;
-			char *msg;
-
-			if (!success) {
-				purple_notify_error(gc, _("Server Statistics"),
-						_("Cannot get server statistics"),
-						silc_get_status_message(status));
-				return;
-			}
-
-			server_stats = va_arg(vp, unsigned char *);
-			buffer_length = va_arg(vp, SilcUInt32);
-			if (!server_stats || !buffer_length) {
-				purple_notify_error(gc, _("Server Statistics"),
-						_("No server statistics available"), NULL);
-				break;
-			}
-			silc_buffer_set(&buf, server_stats, buffer_length);
-			silc_buffer_unformat(&buf,
-					SILC_STR_UI_INT(&starttime),
-					SILC_STR_UI_INT(&uptime),
-					SILC_STR_UI_INT(&my_clients),
-					SILC_STR_UI_INT(&my_channels),
-					SILC_STR_UI_INT(&my_server_ops),
-					SILC_STR_UI_INT(&my_router_ops),
-					SILC_STR_UI_INT(&cell_clients),
-					SILC_STR_UI_INT(&cell_channels),
-					SILC_STR_UI_INT(&cell_servers),
-					SILC_STR_UI_INT(&clients),
-					SILC_STR_UI_INT(&channels),
-					SILC_STR_UI_INT(&servers),
-					SILC_STR_UI_INT(&routers),
-					SILC_STR_UI_INT(&server_ops),
-					SILC_STR_UI_INT(&router_ops),
-					SILC_STR_END);
-
-			msg = g_strdup_printf(_("Local server start time: %s\n"
-					"Local server uptime: %s\n"
-					"Local server clients: %d\n"
-					"Local server channels: %d\n"
-					"Local server operators: %d\n"
-					"Local router operators: %d\n"
-					"Local cell clients: %d\n"
-					"Local cell channels: %d\n"
-					"Local cell servers: %d\n"
-					"Total clients: %d\n"
-					"Total channels: %d\n"
-					"Total servers: %d\n"
-					"Total routers: %d\n"
-					"Total server operators: %d\n"
-					"Total router operators: %d\n"),
-					silc_get_time(starttime),
-					purple_str_seconds_to_string((int)uptime),
-					(int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops,
-					(int)cell_clients, (int)cell_channels, (int)cell_servers,
-					(int)clients, (int)channels, (int)servers, (int)routers,
-					(int)server_ops, (int)router_ops);
-
-			purple_notify_info(gc, NULL,
-					_("Network Statistics"), msg);
-			g_free(msg);
-		}
-		break;
-
-	case SILC_COMMAND_PING:
-		{
-			if (!success) {
-				purple_notify_error(gc, _("Ping"), _("Ping failed"),
-								  silc_get_status_message(status));
-				return;
-			}
-
-			purple_notify_info(gc, _("Ping"), _("Ping reply received from server"),
-							 NULL);
-		}
-		break;
-
-	case SILC_COMMAND_KILL:
-		if (!success) {
-			purple_notify_error(gc, _("Kill User"),
-					  _("Could not kill user"),
-					  silc_get_status_message(status));
-			return;
-		}
-		break;
-
-	case SILC_COMMAND_CMODE:
-		{
-			SilcChannelEntry channel_entry;
-			SilcBuffer channel_pubkeys;
-
-			if (!success)
-				return;
-
-			channel_entry = va_arg(vp, SilcChannelEntry);
-			(void)va_arg(vp, SilcUInt32);
-			(void)va_arg(vp, SilcPublicKey);
-			channel_pubkeys = va_arg(vp, SilcBuffer);
-
-			if (sg->chpk)
-				silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys);
-		}
-		break;
-
-	default:
-		if (success)
-			purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command);
-		else
-			purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command,
-							silc_get_status_message(status));
-		break;
-	}
-
-	va_end(vp);
-}
-
-
-/* Called to indicate that connection was either successfully established
-   or connecting failed.  This is also the first time application receives
-   the SilcClientConnection object which it should save somewhere.
-   If the `success' is FALSE the application must always call the function
-   silc_client_close_connection. */
-
-static void
-silc_connected(SilcClient client, SilcClientConnection conn,
-	       SilcClientConnectionStatus status)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg;
-
-	if (gc == NULL) {
-		silc_client_close_connection(client, conn);
-		return;
-	}
-	sg = gc->proto_data;
-
-	switch (status) {
-	case SILC_CLIENT_CONN_SUCCESS:
-	case SILC_CLIENT_CONN_SUCCESS_RESUME:
-		purple_connection_set_state(gc, PURPLE_CONNECTED);
-
-		/* Send the server our buddy list */
-		silcpurple_send_buddylist(gc);
-
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-
-		/* Send any UMODEs configured for account */
-		if (purple_account_get_bool(sg->account, "block-ims", FALSE)) {
-			silc_client_command_call(sg->client, sg->conn, NULL,
-					"UMODE", "+P", NULL);
-		}
-
-		return;
-		break;
-	case SILC_CLIENT_CONN_ERROR:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Error during connecting to SILC Server"));
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_KE:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-			_("Key Exchange failed"));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_AUTH:
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
-			_("Authentication failed"));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_RESUME:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-			_("Resuming detached session failed. "
-			  "Press Reconnect to create new connection."));
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Connection timed out"));
-		break;
-	}
-
-	/* Error */
-	sg->conn = NULL;
-	silc_client_close_connection(client, conn);
-}
-
-
-/* Called to indicate that connection was disconnected to the server.
-   The `status' may tell the reason of the disconnection, and if the
-   `message' is non-NULL it may include the disconnection message
-   received from server. */
-
-static void
-silc_disconnected(SilcClient client, SilcClientConnection conn,
-		  SilcStatus status, const char *message)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-
-	if (sg->resuming && !sg->detaching)
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-
-	sg->conn = NULL;
-
-	/* Close the connection */
-	if (!sg->detaching)
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Disconnected by server"));
-	else
-		/* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
-		purple_account_disconnect(purple_connection_get_account(gc));
-}
-
-
-typedef struct {
-	SilcGetAuthMeth completion;
-	void *context;
-} *SilcPurpleGetAuthMethod;
-
-/* Callback called when we've received the authentication method information
-   from the server after we've requested it. */
-
-static void silc_get_auth_method_callback(SilcClient client,
-					  SilcClientConnection conn,
-					  SilcAuthMethod auth_meth,
-					  void *context)
-{
-	SilcPurpleGetAuthMethod internal = context;
-
-	switch (auth_meth) {
-	case SILC_AUTH_NONE:
-		/* No authentication required. */
-		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-		break;
-
-	case SILC_AUTH_PASSWORD:
-		/* By returning NULL here the library will ask the passphrase from us
-		   by calling the silc_ask_passphrase. */
-		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-		break;
-
-	case SILC_AUTH_PUBLIC_KEY:
-		/* Do not get the authentication data now, the library will generate
-		   it using our default key, if we do not provide it here. */
-		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-		break;
-	}
-
-	silc_free(internal);
-}
-
-/* Find authentication method and authentication data by hostname and
-   port. The hostname may be IP address as well. When the authentication
-   method has been resolved the `completion' callback with the found
-   authentication method and authentication data is called. The `conn'
-   may be NULL. */
-
-static void
-silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-		     char *hostname, SilcUInt16 port,
-		     SilcGetAuthMeth completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	SilcPurpleGetAuthMethod internal;
-	const char *password;
-
-	/* Progress */
-	if (sg->resuming)
-		purple_connection_update_progress(gc, _("Resuming session"), 4, 5);
-	else
-		purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5);
-
-	/* Check configuration if we have this connection configured.  If we
-	   have then return that data immediately, as it's faster way. */
-	if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) {
-		completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
-		return;
-	}
-	password = purple_connection_get_password(gc);
-	if (password && *password) {
-		completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context);
-		return;
-	}
-
-	/* Resolve the authentication method from server, as we may not know it. */
-	internal = silc_calloc(1, sizeof(*internal));
-	if (!internal)
-		return;
-	internal->completion = completion;
-	internal->context = context;
-	silc_client_request_authentication_method(client, conn,
-						  silc_get_auth_method_callback,
-						  internal);
-}
-
-
-/* Verifies received public key. The `conn_type' indicates which entity
-   (server, client etc.) has sent the public key. If user decides to trust
-   the application may save the key as trusted public key for later
-   use. The `completion' must be called after the public key has been
-   verified. */
-
-static void
-silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-		       SilcSocketType conn_type, unsigned char *pk,
-		       SilcUInt32 pk_len, SilcSKEPKType pk_type,
-		       SilcVerifyPublicKey completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-
-	if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER ||
-			  conn_type == SILC_SOCKET_TYPE_ROUTER)) {
-		/* Progress */
-		if (sg->resuming)
-			purple_connection_update_progress(gc, _("Resuming session"), 3, 5);
-		else
-			purple_connection_update_progress(gc, _("Verifying server public key"),
-							3, 5);
-	}
-
-	/* Verify public key */
-	silcpurple_verify_public_key(client, conn, NULL, conn_type, pk,
-				   pk_len, pk_type, completion, context);
-}
-
-typedef struct {
-	SilcAskPassphrase completion;
-	void *context;
-} *SilcPurpleAskPassphrase;
-
-static void
-silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase)
-{
-	if (!passphrase || !(*passphrase))
-		internal->completion(NULL, 0, internal->context);
-	else
-		internal->completion((unsigned char *)passphrase,
-				     strlen(passphrase), internal->context);
-	silc_free(internal);
-}
-
-/* Ask (interact, that is) a passphrase from user. The passphrase is
-   returned to the library by calling the `completion' callback with
-   the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
-   if not then the library will attempt to encode. */
-
-static void
-silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-		    SilcAskPassphrase completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal));
-
-	if (!internal)
-		return;
-	internal->completion = completion;
-	internal->context = context;
-	purple_request_input(gc, _("Passphrase"), NULL,
-			   _("Passphrase required"), NULL, FALSE, TRUE, NULL,
-			   _("OK"), G_CALLBACK(silc_ask_passphrase_cb),
-			   _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb),
-			   purple_connection_get_account(gc), NULL, NULL, internal);
-}
-
-
-/* Notifies application that failure packet was received.  This is called
-   if there is some protocol active in the client.  The `protocol' is the
-   protocol context.  The `failure' is opaque pointer to the failure
-   indication.  Note, that the `failure' is protocol dependant and
-   application must explicitly cast it to correct type.  Usually `failure'
-   is 32 bit failure type (see protocol specs for all protocol failure
-   types). */
-
-static void
-silc_failure(SilcClient client, SilcClientConnection conn,
-	     SilcProtocol protocol, void *failure)
-{
-	PurpleConnection *gc = client->application;
-	char buf[128];
-
-	memset(buf, 0, sizeof(buf));
-
-	if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
-		SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure);
-
-		if (status == SILC_SKE_STATUS_BAD_VERSION)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Version mismatch, upgrade your client"));
-		if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not trust/support your public key"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed KE group"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed cipher"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed PKCS"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed hash function"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed HMAC"));
-		if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
-			g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature"));
-		if (status == SILC_SKE_STATUS_INVALID_COOKIE)
-			g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie"));
-
-		/* Show the error on the progress bar.  A more generic error message
-		   is going to be showed to user after this in the silc_connected. */
-		purple_connection_update_progress(gc, buf, 2, 5);
-	}
-
-	if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
-		SilcUInt32 err = SILC_PTR_TO_32(failure);
-
-		if (err == SILC_AUTH_FAILED)
-			g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed"));
-
-		/* Show the error on the progress bar.  A more generic error message
-		   is going to be showed to user after this in the silc_connected. */
-		purple_connection_update_progress(gc, buf, 4, 5);
-	}
-}
-
-/* Asks whether the user would like to perform the key agreement protocol.
-   This is called after we have received an key agreement packet or an
-   reply to our key agreement packet. This returns TRUE if the user wants
-   the library to perform the key agreement protocol and FALSE if it is not
-   desired (application may start it later by calling the function
-   silc_client_perform_key_agreement). If TRUE is returned also the
-   `completion' and `context' arguments must be set by the application. */
-
-static bool
-silc_key_agreement(SilcClient client, SilcClientConnection conn,
-		   SilcClientEntry client_entry, const char *hostname,
-		   SilcUInt16 port, SilcKeyAgreementCallback *completion,
-		   void **context)
-{
-	silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port);
-	*completion = NULL;
-	*context = NULL;
-	return FALSE;
-}
-
-
-/* Notifies application that file transfer protocol session is being
-   requested by the remote client indicated by the `client_entry' from
-   the `hostname' and `port'. The `session_id' is the file transfer
-   session and it can be used to either accept or reject the file
-   transfer request, by calling the silc_client_file_receive or
-   silc_client_file_close, respectively. */
-
-static void
-silc_ftp(SilcClient client, SilcClientConnection conn,
-	 SilcClientEntry client_entry, SilcUInt32 session_id,
-	 const char *hostname, SilcUInt16 port)
-{
-	silcpurple_ftp_request(client, conn, client_entry, session_id,
-			     hostname, port);
-}
-
-
-/* Delivers SILC session detachment data indicated by `detach_data' to the
-   application.  If application has issued SILC_COMMAND_DETACH command
-   the client session in the SILC network is not quit.  The client remains
-   in the network but is detached.  The detachment data may be used later
-   to resume the session in the SILC Network.  The appliation is
-   responsible of saving the `detach_data', to for example in a file.
-
-   The detachment data can be given as argument to the functions
-   silc_client_connect_to_server, or silc_client_add_connection when
-   creating connection to remote server, inside SilcClientConnectionParams
-   structure.  If it is provided the client library will attempt to resume
-   the session in the network.  After the connection is created
-   successfully, the application is responsible of setting the user
-   interface for user into the same state it was before detaching (showing
-   same channels, channel modes, etc).  It can do this by fetching the
-   information (like joined channels) from the client library. */
-
-static void
-silc_detach(SilcClient client, SilcClientConnection conn,
-	    const unsigned char *detach_data, SilcUInt32 detach_data_len)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	const char *file;
-
-	/* Save the detachment data to file. */
-	file = silcpurple_session_file(purple_account_get_username(sg->account));
-	g_unlink(file);
-	silc_file_writefile(file, (char *)detach_data, detach_data_len);
-}
-
-SilcClientOperations ops = {
-	silc_say,
-	silc_channel_message,
-	silc_private_message,
-	silc_notify,
-	silc_command,
-	silc_command_reply,
-	silc_connected,
-	silc_disconnected,
-	silc_get_auth_method,
-	silc_verify_public_key,
-	silc_ask_passphrase,
-	silc_failure,
-	silc_key_agreement,
-	silc_ftp,
-	silc_detach
-};
--- a/libpurple/protocols/silc10/pk.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/*
-
-  silcpurple_pk.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-
-/************************* Public Key Verification ***************************/
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	char *filename;
-	char *entity;
-	char *entity_name;
-	char *fingerprint;
-	char *babbleprint;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-	SilcSKEPKType pk_type;
-	SilcVerifyPublicKey completion;
-	void *context;
-	gboolean changed;
-} *PublicKeyVerify;
-
-static void silcpurple_verify_ask(const char *entity,
-				const char *fingerprint,
-				const char *babbleprint,
-				PublicKeyVerify verify);
-
-static void silcpurple_verify_cb(PublicKeyVerify verify, gint id)
-{
-	if (id != 2) {
-		if (verify->completion)
-			verify->completion(FALSE, verify->context);
-	} else {
-		if (verify->completion)
-			verify->completion(TRUE, verify->context);
-
-		/* Save the key for future checking */
-		silc_pkcs_save_public_key_data(verify->filename, verify->pk,
-					       verify->pk_len, SILC_PKCS_FILE_PEM);
-	}
-
-	silc_free(verify->filename);
-	silc_free(verify->entity);
-	silc_free(verify->entity_name);
-	silc_free(verify->fingerprint);
-	silc_free(verify->babbleprint);
-	silc_free(verify->pk);
-	silc_free(verify);
-}
-
-static void silcpurple_verify_details_cb(PublicKeyVerify verify)
-{
-	/* What a hack.  We have to display the accept dialog _again_
-	   because Purple closes the dialog after you press the button.  Purple
-	   should have option for the dialogs whether the buttons close them
-	   or not. */
-	silcpurple_verify_ask(verify->entity, verify->fingerprint,
-			    verify->babbleprint, verify);
-}
-
-static void silcpurple_verify_details(PublicKeyVerify verify, gint id)
-{
-	SilcPublicKey public_key;
-	PurpleConnection *gc = verify->client->application;
-	SilcPurple sg = gc->proto_data;
-
-	silc_pkcs_public_key_decode(verify->pk, verify->pk_len,
-				    &public_key);
-	silcpurple_show_public_key(sg, verify->entity_name, public_key,
-				 G_CALLBACK(silcpurple_verify_details_cb),
-				 verify);
-	silc_pkcs_public_key_free(public_key);
-}
-
-static void silcpurple_verify_ask(const char *entity,
-				const char *fingerprint,
-				const char *babbleprint,
-				PublicKeyVerify verify)
-{
-	PurpleConnection *gc = verify->client->application;
-	char tmp[256], tmp2[256];
-
-	if (verify->changed) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Received %s's public key. Your local copy does not match this "
-			     "key. Would you still like to accept this public key?"),
-			   entity);
-	} else {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Received %s's public key. Would you like to accept this "
-			     "public key?"), entity);
-	}
-	g_snprintf(tmp2, sizeof(tmp2),
-		   _("Fingerprint and babbleprint for the %s key are:\n\n"
-		     "%s\n%s\n"), entity, fingerprint, babbleprint);
-
-	purple_request_action(gc, _("Verify Public Key"), tmp, tmp2,
-						PURPLE_DEFAULT_ACTION_NONE,
-						purple_connection_get_account(gc), entity, NULL, verify, 3,
-			    _("Yes"), G_CALLBACK(silcpurple_verify_cb),
-			    _("No"), G_CALLBACK(silcpurple_verify_cb),
-			    _("_View..."), G_CALLBACK(silcpurple_verify_details));
-}
-
-void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
-				const char *name, SilcSocketType conn_type,
-				unsigned char *pk, SilcUInt32 pk_len,
-				SilcSKEPKType pk_type,
-				SilcVerifyPublicKey completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	int i;
-	char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
-	char *fingerprint, *babbleprint;
-	struct passwd *pw;
-	struct stat st;
-	char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
-			 conn_type == SILC_SOCKET_TYPE_ROUTER) ?
-			"server" : "client");
-	PublicKeyVerify verify;
-
-	if (pk_type != SILC_SKE_PK_TYPE_SILC) {
-		purple_notify_error(gc, _("Verify Public Key"),
-				  _("Unsupported public key type"), NULL);
-		if (completion)
-			completion(FALSE, context);
-		return;
-	}
-
-	pw = getpwuid(getuid());
-	if (!pw) {
-		if (completion)
-			completion(FALSE, context);
-		return;
-	}
-
-	memset(filename, 0, sizeof(filename));
-	memset(filename2, 0, sizeof(filename2));
-	memset(file, 0, sizeof(file));
-
-	if (conn_type == SILC_SOCKET_TYPE_SERVER ||
-	    conn_type == SILC_SOCKET_TYPE_ROUTER) {
-		if (!name) {
-			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   conn->sock->ip, conn->sock->port);
-			g_snprintf(filename, sizeof(filename) - 1,
-				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-				   silcpurple_silcdir(), entity, file);
-
-			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   conn->sock->hostname, conn->sock->port);
-			g_snprintf(filename2, sizeof(filename2) - 1,
-				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-				   silcpurple_silcdir(), entity, file);
-
-			ipf = filename;
-			hostf = filename2;
-		} else {
-			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   name, conn->sock->port);
-			g_snprintf(filename, sizeof(filename) - 1,
-				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-				   silcpurple_silcdir(), entity, file);
-
-			ipf = filename;
-		}
-	} else {
-		/* Replace all whitespaces with `_'. */
-		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-		for (i = 0; i < strlen(fingerprint); i++)
-			if (fingerprint[i] == ' ')
-				fingerprint[i] = '_';
-
-		g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
-		g_snprintf(filename, sizeof(filename) - 1,
-			   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-			   silcpurple_silcdir(), entity, file);
-		silc_free(fingerprint);
-
-		ipf = filename;
-	}
-
-	verify = silc_calloc(1, sizeof(*verify));
-	if (!verify)
-		return;
-	verify->client = client;
-	verify->conn = conn;
-	verify->filename = strdup(ipf);
-	verify->entity = strdup(entity);
-	verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ?
-			       (name ? strdup(name) : strdup(conn->sock->hostname))
-			       : NULL);
-	verify->pk = silc_memdup(pk, pk_len);
-	verify->pk_len = pk_len;
-	verify->pk_type = pk_type;
-	verify->completion = completion;
-	verify->context = context;
-	fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-	babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-
-	/* Check whether this key already exists */
-	if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
-		/* Key does not exist, ask user to verify the key and save it */
-		silcpurple_verify_ask(name ? name : entity,
-				    fingerprint, babbleprint, verify);
-		return;
-	} else {
-		/* The key already exists, verify it. */
-		SilcPublicKey public_key;
-		unsigned char *encpk;
-		SilcUInt32 encpk_len;
-
-		/* Load the key file, try for both IP filename and hostname filename */
-		if (!silc_pkcs_load_public_key(ipf, &public_key,
-					       SILC_PKCS_FILE_PEM) &&
-		    !silc_pkcs_load_public_key(ipf, &public_key,
-					       SILC_PKCS_FILE_BIN) &&
-		    (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key,
-							   SILC_PKCS_FILE_PEM) &&
-				!silc_pkcs_load_public_key(hostf, &public_key,
-							   SILC_PKCS_FILE_BIN)))) {
-			silcpurple_verify_ask(name ? name : entity,
-					    fingerprint, babbleprint, verify);
-			return;
-		}
-
-		/* Encode the key data */
-		encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
-		if (!encpk) {
-			silcpurple_verify_ask(name ? name : entity,
-					    fingerprint, babbleprint, verify);
-			return;
-		}
-
-		/* Compare the keys */
-		if (memcmp(encpk, pk, encpk_len)) {
-			/* Ask user to verify the key and save it */
-			verify->changed = TRUE;
-			silcpurple_verify_ask(name ? name : entity,
-					    fingerprint, babbleprint, verify);
-			return;
-		}
-
-		/* Local copy matched */
-		if (completion)
-			completion(TRUE, context);
-		silc_free(verify->filename);
-		silc_free(verify->entity);
-		silc_free(verify->entity_name);
-		silc_free(verify->pk);
-		silc_free(verify->fingerprint);
-		silc_free(verify->babbleprint);
-		silc_free(verify);
-	}
-}
--- a/libpurple/protocols/silc10/silc.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1965 +0,0 @@
-/*
-
-  silcpurple.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2005 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-#include "version.h"
-#include "wb.h"
-#include "core.h"
-
-extern SilcClientOperations ops;
-static PurplePlugin *silc_plugin = NULL;
-
-static const char *
-silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b)
-{
-	return (const char *)"silc";
-}
-
-static GList *
-silcpurple_away_states(PurpleAccount *account)
-{
-	PurpleStatusType *type;
-	GList *types = NULL;
-
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-
-	return types;
-}
-
-static void
-silcpurple_set_status(PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = NULL;
-	SilcUInt32 mode;
-	SilcBuffer idp;
-	unsigned char mb[4];
-	const char *state;
-
-	if (gc != NULL)
-		sg = gc->proto_data;
-
-	if (status == NULL)
-		return;
-
-	state = purple_status_get_id(status);
-
-	if (state == NULL)
-		return;
-
-	if ((sg == NULL) || (sg->conn == NULL))
-		return;
-
-	mode = sg->conn->local_entry->mode;
-	mode &= ~(SILC_UMODE_GONE |
-		  SILC_UMODE_HYPER |
-		  SILC_UMODE_BUSY |
-		  SILC_UMODE_INDISPOSED |
-		  SILC_UMODE_PAGE);
-
-	if (!strcmp(state, "hyper"))
-		mode |= SILC_UMODE_HYPER;
-	else if (!strcmp(state, "away"))
-		mode |= SILC_UMODE_GONE;
-	else if (!strcmp(state, "busy"))
-		mode |= SILC_UMODE_BUSY;
-	else if (!strcmp(state, "indisposed"))
-		mode |= SILC_UMODE_INDISPOSED;
-	else if (!strcmp(state, "page"))
-		mode |= SILC_UMODE_PAGE;
-
-	/* Send UMODE */
-	idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT);
-	SILC_PUT32_MSB(mode, mb);
-	silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE,
-				 ++sg->conn->cmd_ident, 2,
-				 1, idp->data, idp->len,
-				 2, mb, sizeof(mb));
-	silc_buffer_free(idp);
-}
-
-
-/*************************** Connection Routines *****************************/
-
-static void
-silcpurple_keepalive(PurpleConnection *gc)
-{
-	SilcPurple sg = gc->proto_data;
-	silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT,
-				NULL, 0);
-}
-
-static gboolean
-silcpurple_scheduler(gpointer *context)
-{
-	SilcPurple sg = (SilcPurple)context;
-	silc_client_run_one(sg->client);
-	return TRUE;
-}
-
-static void
-silcpurple_nickname_parse(const char *nickname,
-			char **ret_nickname)
-{
-	silc_parse_userfqdn(nickname, ret_nickname, NULL);
-}
-
-static void
-silcpurple_login_connected(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc = data;
-	SilcPurple sg;
-	SilcClient client;
-	SilcClientConnection conn;
-	PurpleAccount *account;
-	SilcClientConnectionParams params;
-	SilcUInt32 mask;
-	const char *dfile, *tmp;
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	PurpleStoredImage *img;
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-	struct utsname u;
-#endif
-
-
-	g_return_if_fail(gc != NULL);
-
-	sg = gc->proto_data;
-
-	if (source < 0) {
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Connection failed"));
-		return;
-	}
-
-	client = sg->client;
-	account = sg->account;
-
-	/* Get session detachment data, if available */
-	memset(&params, 0, sizeof(params));
-	dfile = silcpurple_session_file(purple_account_get_username(sg->account));
-	params.detach_data = (unsigned char *)silc_file_readfile(dfile, &params.detach_data_len);
-	if (params.detach_data)
-		params.detach_data[params.detach_data_len] = 0;
-
-	/* Add connection to SILC client library */
-	conn = silc_client_add_connection(
-			  sg->client, &params,
-			  (char *)purple_account_get_string(account, "server",
-							  "silc.silcnet.org"),
-			  purple_account_get_int(account, "port", 706), sg);
-	if (!conn) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unable to initialize SILC Client connection"));
-		gc->proto_data = NULL;
-		return;
-	}
-	sg->conn = conn;
-
-	/* Progress */
-	if (params.detach_data) {
-		purple_connection_update_progress(gc, _("Resuming session"), 2, 5);
-		sg->resuming = TRUE;
-	} else {
-		purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5);
-	}
-
-	/* Perform SILC Key Exchange.  The "silc_connected" will be called
-	   eventually. */
-	silc_client_start_key_exchange(sg->client, sg->conn, source);
-
-	/* Set default attributes */
-	mask = SILC_ATTRIBUTE_MOOD_NORMAL;
-	silc_client_attribute_add(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MOOD,
-				  SILC_32_TO_PTR(mask),
-				  sizeof(SilcUInt32));
-	mask = SILC_ATTRIBUTE_CONTACT_CHAT;
-	silc_client_attribute_add(client, conn,
-				  SILC_ATTRIBUTE_PREFERRED_CONTACT,
-				  SILC_32_TO_PTR(mask),
-				  sizeof(SilcUInt32));
-#ifdef HAVE_SYS_UTSNAME_H
-	if (!uname(&u)) {
-		SilcAttributeObjDevice dev;
-		memset(&dev, 0, sizeof(dev));
-		dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
-		dev.version = u.release;
-		dev.model = u.sysname;
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_DEVICE_INFO,
-					  (void *)&dev, sizeof(dev));
-	}
-#endif
-#ifdef _WIN32
-	tmp = _tzname[0];
-#else
-	tmp = tzname[0];
-#endif
-	silc_client_attribute_add(client, conn,
-				  SILC_ATTRIBUTE_TIMEZONE,
-				  (void *)tmp, strlen(tmp));
-
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	/* Set our buddy icon */
-	img = purple_buddy_icons_find_account_icon(account);
-	silcpurple_buddy_set_icon(gc, img);
-	purple_imgstore_unref(img);
-#endif
-
-	silc_free(params.detach_data);
-}
-
-static void
-silcpurple_login(PurpleAccount *account)
-{
-	SilcPurple sg;
-	SilcClient client;
-	SilcClientParams params;
-	PurpleConnection *gc;
-	char pkd[256], prd[256];
-	const char *cipher, *hmac;
-	char *realname;
-	int i;
-
-	gc = account->gc;
-	if (!gc)
-		return;
-	gc->proto_data = NULL;
-
-	memset(&params, 0, sizeof(params));
-	strcat(params.nickname_format, "%n@%h%a");
-	params.nickname_parse = silcpurple_nickname_parse;
-	params.ignore_requested_attributes = FALSE;
-
-	/* Allocate SILC client */
-	client = silc_client_alloc(&ops, &params, gc, NULL);
-	if (!client) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Out of memory"));
-		return;
-	}
-
-	/* Get username, real name and local hostname for SILC library */
-	if (purple_account_get_username(account)) {
-		const char *u = purple_account_get_username(account);
-		char **up = g_strsplit(u, "@", 2);
-		client->username = strdup(up[0]);
-		g_strfreev(up);
-	} else {
-		client->username = silc_get_username();
-		purple_account_set_username(account, client->username);
-	}
-	realname = silc_get_real_name();
-	if (purple_account_get_user_info(account)) {
-		client->realname = strdup(purple_account_get_user_info(account));
-		free(realname);
-	} else if ((silc_get_real_name() != NULL) && (*realname != '\0')) {
-		client->realname = realname;
-		purple_account_set_user_info(account, client->realname);
-	} else {
-		free(realname);
-		client->realname = strdup(_("John Noname"));
-	}
-	client->hostname = silc_net_localhost();
-
-	purple_connection_set_display_name(gc, client->username);
-
-	/* Register requested cipher and HMAC */
-	cipher = purple_account_get_string(account, "cipher", SILC_DEFAULT_CIPHER);
-	for (i = 0; silc_default_ciphers[i].name; i++)
-		if (!strcmp(silc_default_ciphers[i].name, cipher)) {
-			silc_cipher_register(&(silc_default_ciphers[i]));
-			break;
-		}
-	hmac = purple_account_get_string(account, "hmac", SILC_DEFAULT_HMAC);
-	for (i = 0; silc_default_hmacs[i].name; i++)
-		if (!strcmp(silc_default_hmacs[i].name, hmac)) {
-			silc_hmac_register(&(silc_default_hmacs[i]));
-			break;
-		}
-
-	/* Init SILC client */
-	if (!silc_client_init(client)) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Unable to initialize SILC protocol"));
-		return;
-	}
-
-	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
-	if (!silcpurple_check_silc_dir(gc)) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Error loading SILC key pair"));
-		return;
-	}
-
-	/* Progress */
-	purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);
-
-	/* Load SILC key pair */
-	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());
-	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, &client->pkcs,
-				&client->public_key, &client->private_key)) {
-		g_snprintf(pkd, sizeof(pkd), _("Unable to load SILC key pair: %s"), g_strerror(errno));
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             pkd);
-		return;
-	}
-
-	sg = silc_calloc(1, sizeof(*sg));
-	if (!sg)
-		return;
-	memset(sg, 0, sizeof(*sg));
-	sg->client = client;
-	sg->gc = gc;
-	sg->account = account;
-	gc->proto_data = sg;
-
-	/* Connect to the SILC server */
-	if (purple_proxy_connect(gc, account,
-			       purple_account_get_string(account, "server",
-						       "silc.silcnet.org"),
-			       purple_account_get_int(account, "port", 706),
-			       silcpurple_login_connected, gc) == NULL)
-	{
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                             _("Unable to create connection"));
-		return;
-	}
-
-	/* Schedule SILC using Glib's event loop */
-	sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg);
-}
-
-static int
-silcpurple_close_final(gpointer *context)
-{
-	SilcPurple sg = (SilcPurple)context;
-	silc_client_stop(sg->client);
-	silc_client_free(sg->client);
-#ifdef HAVE_SILCMIME_H
-	if (sg->mimeass)
-		silc_mime_assembler_free(sg->mimeass);
-#endif
-	silc_free(sg);
-	return 0;
-}
-
-static void
-silcpurple_close(PurpleConnection *gc)
-{
-	SilcPurple sg = gc->proto_data;
-	GHashTable *ui_info;
-	const char *ui_name = NULL, *ui_website = NULL;
-	char *quit_msg;
-
-	g_return_if_fail(sg != NULL);
-
-	ui_info = purple_core_get_ui_info();
-
-	if(ui_info) {
-		ui_name = g_hash_table_lookup(ui_info, "name");
-		ui_website = g_hash_table_lookup(ui_info, "website");
-	}
-
-	if(!ui_name || !ui_website) {
-		ui_name = "Pidgin";
-		ui_website = PURPLE_WEBSITE;
-	}
-	quit_msg = g_strdup_printf(_("Download %s: %s"),
-							   ui_name, ui_website);
-
-	/* Send QUIT */
-	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", quit_msg, NULL);
-	g_free(quit_msg);
-
-	if (sg->conn)
-		silc_client_close_connection(sg->client, sg->conn);
-
-	purple_timeout_remove(sg->scheduler);
-	purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg);
-}
-
-
-/****************************** Protocol Actions *****************************/
-
-static void
-silcpurple_attrs_cancel(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	/* Nothing */
-}
-
-static void
-silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	PurpleRequestField *f;
-	char *tmp;
-	SilcUInt32 tmp_len, mask;
-	SilcAttributeObjService service;
-	SilcAttributeObjDevice dev;
-	SilcVCardStruct vcard;
-	const char *val;
-
-	sg = gc->proto_data;
-	if (!sg)
-		return;
-
-	memset(&service, 0, sizeof(service));
-	memset(&dev, 0, sizeof(dev));
-	memset(&vcard, 0, sizeof(vcard));
-
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_USER_INFO, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_SERVICE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MOOD, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_TIMEZONE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_GEOLOCATION, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_DEVICE_INFO, NULL);
-
-	/* Set mood */
-	mask = 0;
-	f = purple_request_fields_get_field(fields, "mood_normal");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_NORMAL;
-	f = purple_request_fields_get_field(fields, "mood_happy");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_HAPPY;
-	f = purple_request_fields_get_field(fields, "mood_sad");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_SAD;
-	f = purple_request_fields_get_field(fields, "mood_angry");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_ANGRY;
-	f = purple_request_fields_get_field(fields, "mood_jealous");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_JEALOUS;
-	f = purple_request_fields_get_field(fields, "mood_ashamed");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_ASHAMED;
-	f = purple_request_fields_get_field(fields, "mood_invincible");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE;
-	f = purple_request_fields_get_field(fields, "mood_inlove");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_INLOVE;
-	f = purple_request_fields_get_field(fields, "mood_sleepy");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_SLEEPY;
-	f = purple_request_fields_get_field(fields, "mood_bored");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_BORED;
-	f = purple_request_fields_get_field(fields, "mood_excited");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_EXCITED;
-	f = purple_request_fields_get_field(fields, "mood_anxious");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS;
-	silc_client_attribute_add(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MOOD,
-				  SILC_32_TO_PTR(mask),
-				  sizeof(SilcUInt32));
-
-	/* Set preferred contact */
-	mask = 0;
-	f = purple_request_fields_get_field(fields, "contact_chat");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
-	f = purple_request_fields_get_field(fields, "contact_email");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_EMAIL;
-	f = purple_request_fields_get_field(fields, "contact_call");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_CALL;
-	f = purple_request_fields_get_field(fields, "contact_sms");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_SMS;
-	f = purple_request_fields_get_field(fields, "contact_mms");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_MMS;
-	f = purple_request_fields_get_field(fields, "contact_video");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_VIDEO;
-	if (mask)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_PREFERRED_CONTACT,
-					  SILC_32_TO_PTR(mask),
-					  sizeof(SilcUInt32));
-
-	/* Set status text */
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "status_text");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_STATUS_FREETEXT,
-					  (void *)val, strlen(val));
-
-	/* Set vcard */
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "vcard");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val) {
-		purple_account_set_string(sg->account, "vcard", val);
-		tmp = silc_file_readfile(val, &tmp_len);
-		if (tmp) {
-			tmp[tmp_len] = 0;
-			if (silc_vcard_decode((unsigned char *)tmp, tmp_len, &vcard))
-				silc_client_attribute_add(client, conn,
-							  SILC_ATTRIBUTE_USER_INFO,
-							  (void *)&vcard,
-							  sizeof(vcard));
-		}
-		silc_vcard_free(&vcard);
-		silc_free(tmp);
-	} else {
-		purple_account_set_string(sg->account, "vcard", "");
-	}
-
-#ifdef HAVE_SYS_UTSNAME_H
-	/* Set device info */
-	f = purple_request_fields_get_field(fields, "device");
-	if (f && purple_request_field_bool_get_value(f)) {
-		struct utsname u;
-		if (!uname(&u)) {
-			dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
-			dev.version = u.release;
-			dev.model = u.sysname;
-			silc_client_attribute_add(client, conn,
-						  SILC_ATTRIBUTE_DEVICE_INFO,
-						  (void *)&dev, sizeof(dev));
-		}
-	}
-#endif
-
-	/* Set timezone */
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "timezone");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_TIMEZONE,
-					  (void *)val, strlen(val));
-}
-
-static void
-silcpurple_attrs(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	SilcHashTable attrs;
-	SilcAttributePayload attr;
-	gboolean mnormal = TRUE, mhappy = FALSE, msad = FALSE,
-		mangry = FALSE, mjealous = FALSE, mashamed = FALSE,
-		minvincible = FALSE, minlove = FALSE, msleepy = FALSE,
-		mbored = FALSE, mexcited = FALSE, manxious = FALSE;
-	gboolean cemail = FALSE, ccall = FALSE, csms = FALSE,
-		cmms = FALSE, cchat = TRUE, cvideo = FALSE;
-	gboolean device = TRUE;
-	char status[1024];
-
-	sg = gc->proto_data;
-	if (!sg)
-		return;
-
-	memset(status, 0, sizeof(status));
-
-	attrs = silc_client_attributes_get(client, conn);
-	if (attrs) {
-		if (silc_hash_table_find(attrs,
-					 SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_MOOD),
-					 NULL, (void *)&attr)) {
-			SilcUInt32 mood = 0;
-			silc_attribute_get_object(attr, &mood, sizeof(mood));
-			mnormal = !mood;
-			mhappy = (mood & SILC_ATTRIBUTE_MOOD_HAPPY);
-			msad = (mood & SILC_ATTRIBUTE_MOOD_SAD);
-			mangry = (mood & SILC_ATTRIBUTE_MOOD_ANGRY);
-			mjealous = (mood & SILC_ATTRIBUTE_MOOD_JEALOUS);
-			mashamed = (mood & SILC_ATTRIBUTE_MOOD_ASHAMED);
-			minvincible = (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE);
-			minlove = (mood & SILC_ATTRIBUTE_MOOD_INLOVE);
-			msleepy = (mood & SILC_ATTRIBUTE_MOOD_SLEEPY);
-			mbored = (mood & SILC_ATTRIBUTE_MOOD_BORED);
-			mexcited = (mood & SILC_ATTRIBUTE_MOOD_EXCITED);
-			manxious = (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS);
-		}
-
-		if (silc_hash_table_find(attrs,
-					 SILC_32_TO_PTR(SILC_ATTRIBUTE_PREFERRED_CONTACT),
-					 NULL, (void *)&attr)) {
-			SilcUInt32 contact = 0;
-			silc_attribute_get_object(attr, &contact, sizeof(contact));
-			cemail = (contact & SILC_ATTRIBUTE_CONTACT_EMAIL);
-			ccall = (contact & SILC_ATTRIBUTE_CONTACT_CALL);
-			csms = (contact & SILC_ATTRIBUTE_CONTACT_SMS);
-			cmms = (contact & SILC_ATTRIBUTE_CONTACT_MMS);
-			cchat = (contact & SILC_ATTRIBUTE_CONTACT_CHAT);
-			cvideo = (contact & SILC_ATTRIBUTE_CONTACT_VIDEO);
-		}
-
-		if (silc_hash_table_find(attrs,
-					 SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_FREETEXT),
-					 NULL, (void *)&attr))
-			silc_attribute_get_object(attr, &status, sizeof(status));
-
-		if (!silc_hash_table_find(attrs,
-					  SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO),
-					  NULL, (void *)&attr))
-			device = FALSE;
-	}
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_label_new("l3", _("Your Current Mood"));
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_normal", _("Normal"), mnormal);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_happy", _("Happy"), mhappy);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_sad", _("Sad"), msad);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_angry", _("Angry"), mangry);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_jealous", _("Jealous"), mjealous);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_ashamed", _("Ashamed"), mashamed);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_invincible", _("Invincible"), minvincible);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_inlove", _("In love"), minlove);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_sleepy", _("Sleepy"), msleepy);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_bored", _("Bored"), mbored);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_excited", _("Excited"), mexcited);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_anxious", _("Anxious"), manxious);
-	purple_request_field_group_add_field(g, f);
-
-	f = purple_request_field_label_new("l4", _("\nYour Preferred Contact Methods"));
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_chat", _("Chat"), cchat);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_email", _("Email"), cemail);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_call", _("Phone"), ccall);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_sms", _("SMS"), csms);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_mms", _("MMS"), cmms);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_video", _("Video conferencing"), cvideo);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("status_text", _("Your Current Status"),
-					  status[0] ? status : NULL, TRUE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-#if 0
-	f = purple_request_field_label_new("l2", _("Online Services"));
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("services",
-					_("Let others see what services you are using"),
-					TRUE);
-	purple_request_field_group_add_field(g, f);
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-	f = purple_request_field_bool_new("device",
-					_("Let others see what computer you are using"),
-					device);
-	purple_request_field_group_add_field(g, f);
-#endif
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("vcard", _("Your VCard File"),
-					  purple_account_get_string(sg->account, "vcard", ""),
-					  FALSE);
-	purple_request_field_group_add_field(g, f);
-#ifdef _WIN32
-	f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE);
-#else
-	f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE);
-#endif
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	purple_request_fields(gc, _("User Online Status Attributes"),
-			    _("User Online Status Attributes"),
-			    _("You can let other users see your online status information "
-			      "and your personal information. Please fill the information "
-			      "you would like other users to see about yourself."),
-			    fields,
-			    _("OK"), G_CALLBACK(silcpurple_attrs_cb),
-			    _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel),
-				gc->account, NULL, NULL, gc);
-}
-
-static void
-silcpurple_detach(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	SilcPurple sg;
-
-	if (!gc)
-		return;
-	sg = gc->proto_data;
-	if (!sg)
-		return;
-
-	/* Call DETACH */
-	silc_client_command_call(sg->client, sg->conn, "DETACH");
-	sg->detaching = TRUE;
-}
-
-static void
-silcpurple_view_motd(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	SilcPurple sg;
-	char *tmp;
-
-	if (!gc)
-		return;
-	sg = gc->proto_data;
-	if (!sg)
-		return;
-
-	if (!sg->motd) {
-		purple_notify_error(
-		     gc, _("Message of the Day"), _("No Message of the Day available"),
-		     _("There is no Message of the Day associated with this connection"));
-		return;
-	}
-
-	tmp = g_markup_escape_text(sg->motd, -1);
-	purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL,
-			      tmp, NULL, NULL);
-	g_free(tmp);
-}
-
-static void
-silcpurple_create_keypair_cancel(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	/* Nothing */
-}
-
-static void
-silcpurple_create_keypair_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = gc->proto_data;
-	PurpleRequestField *f;
-	const char *val, *pkfile = NULL, *prfile = NULL;
-	const char *pass1 = NULL, *pass2 = NULL, *un = NULL, *hn = NULL;
-	const char *rn = NULL, *e = NULL, *o = NULL, *c = NULL;
-	char *identifier;
-	int keylen = SILCPURPLE_DEF_PKCS_LEN;
-	SilcPublicKey public_key;
-
-	sg = gc->proto_data;
-	if (!sg)
-		return;
-
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "pass1");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		pass1 = val;
-	else
-		pass1 = "";
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "pass2");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		pass2 = val;
-	else
-		pass2 = "";
-
-	if (strcmp(pass1, pass2)) {
-		purple_notify_error(
-		     gc, _("Create New SILC Key Pair"), _("Passphrases do not match"), NULL);
-		return;
-	}
-
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "key");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		keylen = atoi(val);
-	f = purple_request_fields_get_field(fields, "pkfile");
-	if (f)
-		pkfile = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "prfile");
-	if (f)
-		prfile = purple_request_field_string_get_value(f);
-
-	f = purple_request_fields_get_field(fields, "un");
-	if (f)
-		un = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "hn");
-	if (f)
-		hn = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "rn");
-	if (f)
-		rn = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "e");
-	if (f)
-		e = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "o");
-	if (f)
-		o = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "c");
-	if (f)
-		c = purple_request_field_string_get_value(f);
-
-	identifier = silc_pkcs_encode_identifier((char *)un, (char *)hn,
-						 (char *)rn, (char *)e, (char *)o, (char *)c);
-
-	/* Create the key pair */
-	if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile,
-				  identifier, pass1, NULL, &public_key, NULL,
-				  FALSE)) {
-		purple_notify_error(
-		     gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL);
-		return;
-	}
-
-	silcpurple_show_public_key(sg, NULL, public_key, NULL, NULL);
-
-	silc_pkcs_public_key_free(public_key);
-	silc_free(identifier);
-}
-
-static void
-silcpurple_create_keypair(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	SilcPurple sg = gc->proto_data;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	const char *username, *realname;
-	char *hostname, **u;
-	char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256];
-
-	username = purple_account_get_username(sg->account);
-	u = g_strsplit(username, "@", 2);
-	username = u[0];
-	realname = purple_account_get_user_info(sg->account);
-	hostname = silc_net_localhost();
-	g_snprintf(tmp, sizeof(tmp), "%s@%s", username, hostname);
-
-	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));
-	g_snprintf(prd, sizeof(prd) - 1, "%s",
-		   purple_account_get_string(gc->account, "private-key", prd2));
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("key", _("Key length"), "2048", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("pkfile", _("Public key file"), pkd, FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("prfile", _("Private key file"), prd, FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("un", _("Username"), username ? username : "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("hn", _("Hostname"), hostname ? hostname : "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("rn", _("Real name"), realname ? realname : "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("e", _("Email"), tmp, FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("o", _("Organization"), "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("c", _("Country"), "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("pass1", _("Passphrase"), "", FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("pass2", _("Passphrase (retype)"), "", FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	purple_request_fields(gc, _("Create New SILC Key Pair"),
-			    _("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);
-
-	g_strfreev(u);
-	silc_free(hostname);
-}
-
-static void
-silcpurple_change_pass(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	purple_account_request_change_password(purple_connection_get_account(gc));
-}
-
-static void
-silcpurple_change_passwd(PurpleConnection *gc, const char *old, const char *new)
-{
-	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,
-								   "private-key",
-								   prd), old ? old : "", new ? new : "");
-}
-
-static void
-silcpurple_show_set_info(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	purple_account_request_change_user_info(purple_connection_get_account(gc));
-}
-
-static void
-silcpurple_set_info(PurpleConnection *gc, const char *text)
-{
-}
-
-static GList *
-silcpurple_actions(PurplePlugin *plugin, gpointer context)
-{
-	GList *list = NULL;
-	PurplePluginAction *act;
-
-	act = purple_plugin_action_new(_("Online Status"),
-			silcpurple_attrs);
-	list = g_list_append(list, act);
-
-	act = purple_plugin_action_new(_("Detach From Server"),
-			silcpurple_detach);
-	list = g_list_append(list, act);
-
-	act = purple_plugin_action_new(_("View Message of the Day"),
-			silcpurple_view_motd);
-	list = g_list_append(list, act);
-
-	act = purple_plugin_action_new(_("Create SILC Key Pair..."),
-			silcpurple_create_keypair);
-	list = g_list_append(list, act);
-
-	act = purple_plugin_action_new(_("Change Password..."),
-			silcpurple_change_pass);
-	list = g_list_append(list, act);
-
-	act = purple_plugin_action_new(_("Set User Info..."),
-			silcpurple_show_set_info);
-	list = g_list_append(list, act);
-
-	return list;
-}
-
-
-/******************************* IM Routines *********************************/
-
-typedef struct {
-	char *nick;
-	char *message;
-	SilcUInt32 message_len;
-	SilcMessageFlags flags;
-	PurpleMessageFlags gflags;
-} *SilcPurpleIM;
-
-static void
-silcpurple_send_im_resolved(SilcClient client,
-			  SilcClientConnection conn,
-			  SilcClientEntry *clients,
-			  SilcUInt32 clients_count,
-			  void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	SilcPurpleIM im = context;
-	PurpleConversation *convo;
-	char tmp[256], *nickname = NULL;
-	SilcClientEntry client_entry;
-#ifdef HAVE_SILCMIME_H
-	SilcDList list;
-#endif
-
-	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick,
-							sg->account);
-	if (!convo)
-		return;
-
-	if (!clients)
-		goto err;
-
-	if (clients_count > 1) {
-		silc_parse_userfqdn(im->nick, &nickname, NULL);
-
-		/* Find the correct one. The im->nick might be a formatted nick
-		   so this will find the correct one. */
-		clients = silc_client_get_clients_local(client, conn,
-							nickname, im->nick,
-							&clients_count);
-		if (!clients)
-			goto err;
-		client_entry = clients[0];
-		silc_free(clients);
-	} else {
-		client_entry = clients[0];
-	}
-
-#ifdef HAVE_SILCMIME_H
-	/* Check for images */
-	if (im->gflags & PURPLE_MESSAGE_IMAGES) {
-		list = silcpurple_image_message(im->message, (SilcUInt32 *)&im->flags);
-		if (list) {
-			/* Send one or more MIME message.  If more than one, they
-			   are MIME fragments due to over large message */
-			SilcBuffer buf;
-
-			silc_dlist_start(list);
-			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
-				silc_client_send_private_message(client, conn,
-								 client_entry, im->flags,
-								 buf->data, buf->len,
-								 TRUE);
-			silc_mime_partial_free(list);
-			purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
-				   im->message, 0, time(NULL));
-			goto out;
-		}
-	}
-#endif
-
-	/* Send the message */
-	silc_client_send_private_message(client, conn, client_entry, im->flags,
-					 (unsigned char *)im->message, im->message_len, TRUE);
-	purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
-			   im->message, 0, time(NULL));
-	goto out;
-
- err:
-	g_snprintf(tmp, sizeof(tmp),
-		   _("User <I>%s</I> is not present in the network"), im->nick);
-	purple_conversation_write(convo, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-
- out:
-	g_free(im->nick);
-	g_free(im->message);
-	silc_free(im);
-	silc_free(nickname);
-}
-
-static int
-silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message,
-		 PurpleMessageFlags flags)
-{
-	SilcPurple sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count, mflags;
-	char *nickname, *msg, *tmp;
-	int ret = 0;
-	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
-#ifdef HAVE_SILCMIME_H
-	SilcDList list;
-#endif
-
-	if (!who || !message)
-		return 0;
-
-	mflags = SILC_MESSAGE_FLAG_UTF8;
-
-	tmp = msg = purple_unescape_html(message);
-
-	if (!g_ascii_strncasecmp(msg, "/me ", 4)) {
-		msg += 4;
-		if (!*msg) {
-			g_free(tmp);
-			return 0;
-		}
-		mflags |= SILC_MESSAGE_FLAG_ACTION;
-	} else if (strlen(msg) > 1 && msg[0] == '/') {
-		if (!silc_client_command_call(client, conn, msg + 1))
-			purple_notify_error(gc, _("Call Command"), _("Cannot call command"),
-					_("Unknown command"));
-		g_free(tmp);
-		return 0;
-	}
-
-
-	if (!silc_parse_userfqdn(who, &nickname, NULL)) {
-		g_free(tmp);
-		return 0;
-	}
-
-	if (sign)
-		mflags |= SILC_MESSAGE_FLAG_SIGNED;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, nickname, who,
-						&clients_count);
-	if (!clients) {
-		/* Resolve unknown user */
-		SilcPurpleIM im = silc_calloc(1, sizeof(*im));
-		if (!im) {
-			g_free(tmp);
-			return 0;
-		}
-		im->nick = g_strdup(who);
-		im->message = g_strdup(message);
-		im->message_len = strlen(im->message);
-		im->flags = mflags;
-		im->gflags = flags;
-		silc_client_get_clients(client, conn, nickname, NULL,
-					silcpurple_send_im_resolved, im);
-		silc_free(nickname);
-		g_free(tmp);
-		return 0;
-	}
-
-#ifdef HAVE_SILCMIME_H
-	/* Check for images */
-	if (flags & PURPLE_MESSAGE_IMAGES) {
-		list = silcpurple_image_message(message, &mflags);
-		if (list) {
-			/* Send one or more MIME message.  If more than one, they
-			   are MIME fragments due to over large message */
-			SilcBuffer buf;
-
-			silc_dlist_start(list);
-			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
-				ret =
-			 	silc_client_send_private_message(client, conn,
-								 clients[0], mflags,
-								 buf->data, buf->len,
-								 TRUE);
-			silc_mime_partial_free(list);
-			g_free(tmp);
-			silc_free(nickname);
-			silc_free(clients);
-			return ret;
-		}
-	}
-#endif
-
-	/* Send private message directly */
-	ret = silc_client_send_private_message(client, conn, clients[0],
-					       mflags,
-					       (unsigned char *)msg,
-					       strlen(msg), TRUE);
-
-	g_free(tmp);
-	silc_free(nickname);
-	silc_free(clients);
-	return ret;
-}
-
-
-static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) {
-	/* split this single menu building function back into the two
-	   original: one for buddies and one for chats */
-
-	if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
-		return silcpurple_chat_menu((PurpleChat *) node);
-	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		return silcpurple_buddy_menu((PurpleBuddy *) node);
-	} else {
-		g_return_val_if_reached(NULL);
-	}
-}
-
-/********************************* Commands **********************************/
-
-static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	PurpleConversation *convo = conv;
-	int id = 0;
-
-	gc = purple_conversation_get_gc(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);
-
-	if (convo != NULL)
-		id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo));
-
-	if (id == 0)
-		return PURPLE_CMD_RET_FAILED;
-
-	silcpurple_chat_leave(gc, id);
-
-	return PURPLE_CMD_RET_OK;
-
-}
-
-static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	int id = 0;
-	char *buf, *tmp, *tmp2;
-	const char *topic;
-
-	gc = purple_conversation_get_gc(conv);
-	id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv));
-
-	if (gc == NULL || id == 0)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!args || !args[0]) {
-		topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(conv));
-		if (topic) {
-			tmp = g_markup_escape_text(topic, -1);
-			tmp2 = purple_markup_linkify(tmp);
-			buf = g_strdup_printf(_("current topic is: %s"), tmp2);
-			g_free(tmp);
-			g_free(tmp2);
-		} else
-			buf = g_strdup(_("No topic is set"));
-		purple_conv_chat_write(PURPLE_CONV_CHAT(conv), gc->account->username, buf,
-							 PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
-		g_free(buf);
-
-	}
-
-	if (args && args[0] && (strlen(args[0]) > 255)) {
-		*error = g_strdup(_("Topic too long"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	silcpurple_chat_set_topic(gc, id, args ? args[0] : NULL);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_chat_join(PurpleConversation *conv,
-        const char *cmd, char **args, char **error, void *data)
-{
-	GHashTable *comp;
-
-	if(!args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-
-	g_hash_table_replace(comp, "channel", args[0]);
-	if(args[1])
-		g_hash_table_replace(comp, "passphrase", args[1]);
-
-	silcpurple_chat_join(purple_conversation_get_gc(conv), comp);
-
-	g_hash_table_destroy(comp);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_chat_list(PurpleConversation *conv,
-        const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	gc = purple_conversation_get_gc(conv);
-	purple_roomlist_show_with_account(purple_connection_get_account(gc));
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_whois(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	silcpurple_get_info(gc, args[0]);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_msg(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	int ret;
-	PurpleConnection *gc;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND);
-
-	if (ret)
-		return PURPLE_CMD_RET_OK;
-	else
-		return PURPLE_CMD_RET_FAILED;
-}
-
-static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	int ret = 1;
-	PurpleConversation *convo;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-
-	if (!args || !args[0]) {
-		*error = g_strdup(_("You must specify a nick"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	account = purple_connection_get_account(gc);
-
-	convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, args[0]);
-
-	if (args[1]) {
-		ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND);
-		purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc),
-				args[1], PURPLE_MESSAGE_SEND, time(NULL));
-	}
-
-	if (ret)
-		return PURPLE_CMD_RET_OK;
-	else
-		return PURPLE_CMD_RET_FAILED;
-}
-
-static PurpleCmdRet silcpurple_cmd_motd(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	char *tmp;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = gc->proto_data;
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!sg->motd) {
-		*error = g_strdup(_("There is no Message of the Day associated with this connection"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	tmp = g_markup_escape_text(sg->motd, -1);
-	purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL,
-			tmp, NULL, NULL);
-	g_free(tmp);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_detach(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = gc->proto_data;
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	silc_client_command_call(sg->client, sg->conn, "DETACH");
-	sg->detaching = TRUE;
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	SilcChannelEntry channel;
-	char *silccmd, *silcargs, *msg, tmp[256];
-	const char *chname;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL || !args || gc->proto_data == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = gc->proto_data;
-
-	if (args[0])
-		chname = args[0];
-	else
-		chname = purple_conversation_get_name(conv);
-
-	if (!args[1]) {
-		channel = silc_client_get_channel(sg->client, sg->conn,
-										  (char *)chname);
-		if (!channel) {
-			*error = g_strdup_printf(_("channel %s not found"), chname);
-			return PURPLE_CMD_RET_FAILED;
-		}
-		if (channel->mode) {
-			silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
-			msg = g_strdup_printf(_("channel modes for %s: %s"), chname, tmp);
-		} else {
-			msg = g_strdup_printf(_("no channel modes are set on %s"), chname);
-		}
-		purple_conv_chat_write(PURPLE_CONV_CHAT(conv), "",
-							 msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
-		g_free(msg);
-		return PURPLE_CMD_RET_OK;
-	}
-
-	silcargs = g_strjoinv(" ", args);
-	silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL);
-	g_free(silcargs);
-	if (!silc_client_command_call(sg->client, sg->conn, silccmd)) {
-		g_free(silccmd);
-		*error = g_strdup_printf(_("Failed to set cmodes for %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	g_free(silccmd);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_generic(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	char *silccmd, *silcargs;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = gc->proto_data;
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	silcargs = g_strjoinv(" ", args);
-	silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL);
-	g_free(silcargs);
-	if (!silc_client_command_call(sg->client, sg->conn, silccmd)) {
-		g_free(silccmd);
-		*error = g_strdup_printf(_("Unknown command: %s, (may be a client bug)"), cmd);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	g_free(silccmd);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_quit(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	GHashTable *ui_info;
-	const char *ui_name = NULL, *ui_website = NULL;
-	char *quit_msg;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = gc->proto_data;
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	ui_info = purple_core_get_ui_info();
-
-	if(ui_info) {
-		ui_name = g_hash_table_lookup(ui_info, "name");
-		ui_website = g_hash_table_lookup(ui_info, "website");
-	}
-
-	if(!ui_name || !ui_website) {
-		ui_name = "Pidgin";
-		ui_website = PURPLE_WEBSITE;
-	}
-	quit_msg = g_strdup_printf(_("Download %s: %s"),
-							   ui_name, ui_website);
-
-	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", (args && args[0]) ? args[0] : quit_msg, NULL);
-	g_free(quit_msg);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = purple_conversation_get_gc(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = gc->proto_data;
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!silc_client_command_call(sg->client, sg->conn, args[0])) {
-		*error = g_strdup_printf(_("Unknown command: %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-
-/************************** Plugin Initialization ****************************/
-
-static void
-silcpurple_register_commands(void)
-{
-	purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
-			"prpl-silc", silcpurple_cmd_chat_part, _("part [channel]:  Leave the chat"), NULL);
-	purple_cmd_register("leave", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
-			"prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]:  Leave the chat"), NULL);
-	purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
-			silcpurple_cmd_chat_topic, _("topic [&lt;new topic&gt;]:  View or change the topic"), NULL);
-	purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
-			"prpl-silc", silcpurple_cmd_chat_join,
-			_("join &lt;channel&gt; [&lt;password&gt;]:  Join a chat on this network"), NULL);
-	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
-			silcpurple_cmd_chat_list, _("list:  List channels on this network"), NULL);
-	purple_cmd_register("whois", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc",
-			silcpurple_cmd_whois, _("whois &lt;nick&gt;:  View nick's information"), NULL);
-	purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_msg,
-			_("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user"), NULL);
-	purple_cmd_register("query", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query,
-			_("query &lt;nick&gt; [&lt;message&gt;]:  Send a private message to a user"), NULL);
-	purple_cmd_register("motd", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd,
-			_("motd:  View the server's Message Of The Day"), NULL);
-	purple_cmd_register("detach", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_detach,
-			_("detach:  Detach this session"), NULL);
-	purple_cmd_register("quit", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit,
-			_("quit [message]:  Disconnect from the server, with an optional message"), NULL);
-	purple_cmd_register("call", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_call,
-			_("call &lt;command&gt;:  Call any silc client command"), NULL);
-	/* These below just get passed through for the silc client library to deal
-	 * with */
-	purple_cmd_register("kill", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("kill &lt;nick&gt; [-pubkey|&lt;reason&gt;]:  Kill nick"), NULL);
-	purple_cmd_register("nick", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("nick &lt;newnick&gt;:  Change your nickname"), NULL);
-	purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("whowas &lt;nick&gt;:  View nick's information"), NULL);
-	purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode,
-			_("cmode &lt;channel&gt; [+|-&lt;modes&gt;] [arguments]:  Change or display channel modes"), NULL);
-	purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("cumode &lt;channel&gt; +|-&lt;modes&gt; &lt;nick&gt;:  Change nick's modes on channel"), NULL);
-	purple_cmd_register("umode", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("umode &lt;usermodes&gt;:  Set your modes in the network"), NULL);
-	purple_cmd_register("oper", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("oper &lt;nick&gt; [-pubkey]:  Get server operator privileges"), NULL);
-	purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("invite &lt;channel&gt; [-|+]&lt;nick&gt;:  invite nick or add/remove from channel invite list"), NULL);
-	purple_cmd_register("kick", "wws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("kick &lt;channel&gt; &lt;nick&gt; [comment]:  Kick client from channel"), NULL);
-	purple_cmd_register("info", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("info [server]:  View server administrative details"), NULL);
-	purple_cmd_register("ban", "ww", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("ban [&lt;channel&gt; +|-&lt;nick&gt;]:  Ban client from channel"), NULL);
-	purple_cmd_register("getkey", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("getkey &lt;nick|server&gt;:  Retrieve client's or server's public key"), NULL);
-	purple_cmd_register("stats", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("stats:  View server and network statistics"), NULL);
-	purple_cmd_register("ping", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("ping:  Send PING to the connected server"), NULL);
-#if 0 /* Purple doesn't handle these yet */
-	purple_cmd_register("users", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
-			"prpl-silc", silcpurple_cmd_users,
-			_("users &lt;channel&gt;:  List users in channel"));
-	purple_cmd_register("names", "ww", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_names,
-			_("names [-count|-ops|-halfops|-voices|-normal] &lt;channel(s)&gt;:  List specific users in channel(s)"));
-#endif
-}
-
-static PurpleWhiteboardPrplOps silcpurple_wb_ops =
-{
-	silcpurple_wb_start,
-	silcpurple_wb_end,
-	silcpurple_wb_get_dimensions,
-	silcpurple_wb_set_dimensions,
-	silcpurple_wb_get_brush,
-	silcpurple_wb_set_brush,
-	silcpurple_wb_send,
-	silcpurple_wb_clear,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static PurplePluginProtocolInfo prpl_info =
-{
-#ifdef HAVE_SILCMIME_H
-	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
-	OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE |
-	OPT_PROTO_SLASH_COMMANDS_NATIVE,
-#else
-	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
-	OPT_PROTO_PASSWORD_OPTIONAL |
-	OPT_PROTO_SLASH_COMMANDS_NATIVE,
-#endif
-	NULL,						/* user_splits */
-	NULL,						/* protocol_options */
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	{"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-#else
-	NO_BUDDY_ICONS,
-#endif
-	silcpurple_list_icon,			/* list_icon */
-	NULL,				/* list_emblems */
-	silcpurple_status_text,		/* status_text */
-	silcpurple_tooltip_text,		/* tooltip_text */
-	silcpurple_away_states,		/* away_states */
-	silcpurple_blist_node_menu,	/* blist_node_menu */
-	silcpurple_chat_info,			/* chat_info */
-	silcpurple_chat_info_defaults,/* chat_info_defaults */
-	silcpurple_login,				/* login */
-	silcpurple_close,				/* close */
-	silcpurple_send_im,			/* send_im */
-	silcpurple_set_info,			/* set_info */
-	NULL,						/* send_typing */
-	silcpurple_get_info,			/* get_info */
-	silcpurple_set_status,		/* set_status */
-	silcpurple_idle_set,			/* set_idle */
-	silcpurple_change_passwd,		/* change_passwd */
-	silcpurple_add_buddy,			/* add_buddy */
-	NULL,						/* add_buddies */
-	silcpurple_remove_buddy,		/* remove_buddy */
-	NULL,						/* remove_buddies */
-	NULL,						/* add_permit */
-	NULL,						/* add_deny */
-	NULL,						/* rem_permit */
-	NULL,						/* rem_deny */
-	NULL,						/* set_permit_deny */
-	silcpurple_chat_join,			/* join_chat */
-	NULL,						/* reject_chat */
-	silcpurple_get_chat_name,		/* get_chat_name */
-	silcpurple_chat_invite,		/* chat_invite */
-	silcpurple_chat_leave,		/* chat_leave */
-	NULL,						/* chat_whisper */
-	silcpurple_chat_send,			/* chat_send */
-	silcpurple_keepalive,			/* keepalive */
-	NULL,						/* register_user */
-	NULL,						/* get_cb_info */
-	NULL,						/* get_cb_away */
-	NULL,						/* alias_buddy */
-	NULL,						/* group_buddy */
-	NULL,						/* rename_group */
-	NULL,						/* buddy_free */
-	NULL,						/* convo_closed */
-	NULL,						/* normalize */
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	silcpurple_buddy_set_icon,			/* set_buddy_icon */
-#else
-	NULL,
-#endif
-	NULL,						/* remove_group */
-	NULL,						/* get_cb_real_name */
-	silcpurple_chat_set_topic,	/* set_chat_topic */
-	NULL,						/* find_blist_chat */
-	silcpurple_roomlist_get_list,	/* roomlist_get_list */
-	silcpurple_roomlist_cancel,	/* roomlist_cancel */
-	NULL,						/* roomlist_expand_category */
-	NULL,						/* can_receive_file */
-	silcpurple_ftp_send_file,		/* send_file */
-	silcpurple_ftp_new_xfer,		/* new_xfer */
-	NULL,						/* offline_message */
-	&silcpurple_wb_ops,			/* whiteboard_prpl_ops */
-	NULL,                       /* send_raw */
-	NULL,                       /* roomlist_room_serialize */
-	NULL,                       /* unregister_user */
-	NULL,                       /* send_attention */
-	NULL,                       /* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
-	NULL,                       /* get_account_text_table */
-	NULL,                       /* initiate_media */
-	NULL,                       /* get_media_caps */
-	NULL,                       /* get_moods */
-	NULL,                       /* set_public_alias */
-	NULL,                       /* get_public_alias */
-	NULL,                       /* add_buddy_with_invite */
-	NULL                        /* add_buddies_with_invite */
-};
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	"prpl-silc",                                      /**< id             */
-	"SILC",                                           /**< name           */
-	"1.0",                                            /**< version        */
-	/**  summary        */
-	N_("SILC Protocol Plugin"),
-	/**  description    */
-	N_("Secure Internet Live Conferencing (SILC) Protocol"),
-	"Pekka Riikonen",                                 /**< author         */
-	"http://silcnet.org/",                            /**< homepage       */
-
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	silcpurple_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	PurpleAccountOption *option;
-	PurpleAccountUserSplit *split;
-	char tmp[256];
-	int i;
-	PurpleKeyValuePair *kvp;
-	GList *list = NULL;
-
-	silc_plugin = plugin;
-
-	split = purple_account_user_split_new(_("Network"), "silcnet.org", '@');
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
-
-	/* Account options */
-	option = purple_account_option_string_new(_("Connect server"),
-						"server",
-						"silc.silcnet.org");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_int_new(_("Port"), "port", 706);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
-	option = purple_account_option_string_new(_("Public Key file"),
-						"public-key", tmp);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
-	option = purple_account_option_string_new(_("Private Key file"),
-						"private-key", tmp);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	for (i = 0; silc_default_ciphers[i].name; i++) {
-		kvp = g_new0(PurpleKeyValuePair, 1);
-		kvp->key = g_strdup(silc_default_ciphers[i].name);
-		kvp->value = g_strdup(silc_default_ciphers[i].name);
-		list = g_list_append(list, kvp);
-	}
-	option = purple_account_option_list_new(_("Cipher"), "cipher", list);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	list = NULL;
-	for (i = 0; silc_default_hmacs[i].name; i++) {
-		kvp = g_new0(PurpleKeyValuePair, 1);
-		kvp->key = g_strdup(silc_default_hmacs[i].name);
-		kvp->value = g_strdup(silc_default_hmacs[i].name);
-		list = g_list_append(list, kvp);
-	}
-	option = purple_account_option_list_new(_("HMAC"), "hmac", list);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	option = purple_account_option_bool_new(_("Public key authentication"),
-					      "pubkey-auth", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Block IMs without Key Exchange"),
-					      "block-ims", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Block messages to whiteboard"),
-					      "block-wb", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Automatically open whiteboard"),
-					      "open-wb", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Digitally sign and verify all messages"),
-					      "sign-verify", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	purple_prefs_remove("/plugins/prpl/silc");
-
-	silcpurple_register_commands();
-
-#ifdef _WIN32
-	silc_net_win32_init();
-#endif
-}
-
-PURPLE_INIT_PLUGIN(silc10, init_plugin, info);
--- a/libpurple/protocols/silc10/silcpurple.h	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
-
-  silcpurple.h
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#ifndef SILCPURPLE_H
-#define SILCPURPLE_H
-
-/* Purple includes */
-#include "internal.h"
-#include "account.h"
-#include "accountopt.h"
-#include "cmds.h"
-#include "conversation.h"
-#include "debug.h"
-#include "ft.h"
-#include "notify.h"
-#include "prpl.h"
-#include "request.h"
-#include "roomlist.h"
-#include "server.h"
-#include "util.h"
-
-/* Default public and private key file names */
-#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub"
-#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv"
-
-/* Default settings for creating key pair */
-#define SILCPURPLE_DEF_PKCS "rsa"
-#define SILCPURPLE_DEF_PKCS_LEN 2048
-
-#define SILCPURPLE_PRVGRP 0x001fffff
-
-/* Status IDs */
-#define SILCPURPLE_STATUS_ID_OFFLINE	"offline"
-#define SILCPURPLE_STATUS_ID_AVAILABLE "available"
-#define SILCPURPLE_STATUS_ID_HYPER	"hyper"
-#define SILCPURPLE_STATUS_ID_AWAY		"away"
-#define SILCPURPLE_STATUS_ID_BUSY		"busy"
-#define SILCPURPLE_STATUS_ID_INDISPOSED "indisposed"
-#define SILCPURPLE_STATUS_ID_PAGE		"page"
-
-typedef struct {
-	unsigned long id;
-	const char *channel;
-	unsigned long chid;
-	const char *parentch;
-	SilcChannelPrivateKey key;
-} *SilcPurplePrvgrp;
-
-/* The SILC Purple plugin context */
-typedef struct SilcPurpleStruct {
-	SilcClient client;
-	SilcClientConnection conn;
-
-	guint scheduler;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	unsigned long channel_ids;
-	GList *grps;
-
-	char *motd;
-	PurpleRoomlist *roomlist;
-#ifdef HAVE_SILCMIME_H
-	SilcMimeAssembler mimeass;
-#endif
-	unsigned int detaching            : 1;
-	unsigned int resuming             : 1;
-	unsigned int roomlist_cancelled   : 1;
-	unsigned int chpk                 : 1;
-} *SilcPurple;
-
-
-gboolean silcpurple_check_silc_dir(PurpleConnection *gc);
-void silcpurple_chat_join_done(SilcClient client,
-			     SilcClientConnection conn,
-			     SilcClientEntry *clients,
-			     SilcUInt32 clients_count,
-			     void *context);
-const char *silcpurple_silcdir(void);
-const char *silcpurple_session_file(const char *account);
-void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
-				const char *name, SilcSocketType conn_type,
-				unsigned char *pk, SilcUInt32 pk_len,
-				SilcSKEPKType pk_type,
-				SilcVerifyPublicKey completion, void *context);
-GList *silcpurple_buddy_menu(PurpleBuddy *buddy);
-void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
-void silcpurple_send_buddylist(PurpleConnection *gc);
-void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
-void silcpurple_buddy_keyagr_request(SilcClient client,
-				   SilcClientConnection conn,
-				   SilcClientEntry client_entry,
-				   const char *hostname, SilcUInt16 port);
-void silcpurple_idle_set(PurpleConnection *gc, int idle);
-void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
-char *silcpurple_status_text(PurpleBuddy *b);
-gboolean silcpurple_ip_is_private(const char *ip);
-void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file);
-PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name);
-void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
-			  SilcClientEntry client_entry, SilcUInt32 session_id,
-			  const char *hostname, SilcUInt16 port);
-void silcpurple_show_public_key(SilcPurple sg,
-			      const char *name, SilcPublicKey public_key,
-			      GCallback callback, void *context);
-void silcpurple_get_info(PurpleConnection *gc, const char *who);
-SilcAttributePayload
-silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute);
-void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
-			       SilcUInt32 buf_size);
-void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
-				SilcUInt32 buf_size);
-void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
-				 SilcUInt32 buf_size);
-GList *silcpurple_chat_info(PurpleConnection *gc);
-GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name);
-GList *silcpurple_chat_menu(PurpleChat *);
-void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data);
-char *silcpurple_get_chat_name(GHashTable *data);
-void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg,
-			  const char *name);
-void silcpurple_chat_leave(PurpleConnection *gc, int id);
-int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags flags);
-void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic);
-PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc);
-void silcpurple_roomlist_cancel(PurpleRoomlist *list);
-void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
-			       SilcBuffer channel_pubkeys);
-void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
-					 char **contactstr, char **langstr, char **devicestr,
-					 char **tzstr, char **geostr);
-#ifdef SILC_ATTRIBUTE_USER_ICON
-void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img);
-#endif
-#ifdef HAVE_SILCMIME_H
-char *silcpurple_file2mime(const char *filename);
-SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags);
-#endif
-
-#ifdef _WIN32
-typedef int uid_t;
-
-struct passwd {
-	char	*pw_name;	/* user name */
-	char	*pw_passwd;	/* user password */
-	int		pw_uid;		/* user id */
-	int		pw_gid;		/* group id */
-	char	*pw_gecos;	/* real name */
-	char	*pw_dir;	/* home directory */
-	char	*pw_shell;	/* shell program */
-};
-
-struct passwd *getpwuid(int uid);
-int getuid(void);
-int geteuid(void);
-#endif
-
-#endif /* SILCPURPLE_H */
--- a/libpurple/protocols/silc10/util.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,776 +0,0 @@
-/*
-
-  silcpurple_util.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2005 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-#include "imgstore.h"
-
-/**************************** Utility Routines *******************************/
-
-static char str[256], str2[256];
-
-const char *silcpurple_silcdir(void)
-{
-	const char *hd = purple_home_dir();
-	memset(str, 0, sizeof(str));
-	g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp");
-	return (const char *)str;
-}
-
-const char *silcpurple_session_file(const char *account)
-{
-	memset(str2, 0, sizeof(str2));
-	g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session",
-		   silcpurple_silcdir(), account);
-	return (const char *)str2;
-}
-
-gboolean silcpurple_ip_is_private(const char *ip)
-{
-	if (silc_net_is_ip4(ip)) {
-		if (!strncmp(ip, "10.", 3)) {
-			return TRUE;
-		} else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) {
-			char tmp[3];
-			int s;
-			memset(tmp, 0, sizeof(tmp));
-			strncpy(tmp, ip + 4, 2);
-			s = atoi(tmp);
-			if (s >= 16 && s <= 31)
-				return TRUE;
-		} else if (!strncmp(ip, "192.168.", 8)) {
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-/* This checks stats for various SILC files and directories. First it
-   checks if ~/.silc directory exist and is owned by the correct user. If
-   it doesn't exist, it will create the directory. After that it checks if
-   user's Public and Private key files exists and creates them if needed. */
-
-gboolean silcpurple_check_silc_dir(PurpleConnection *gc)
-{
-	char filename[256], file_public_key[256], file_private_key[256];
-	char servfilename[256], clientfilename[256], friendsfilename[256];
-	char pkd[256], prd[256];
-	struct stat st;
-	struct passwd *pw;
-	int fd;
-
-	pw = getpwuid(getuid());
-	if (!pw) {
-		purple_debug_error("silc", "silc: %s\n", g_strerror(errno));
-		return FALSE;
-	}
-
-	g_snprintf(filename, sizeof(filename) - 1, "%s", silcpurple_silcdir());
-	g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys",
-		   silcpurple_silcdir());
-	g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys",
-		   silcpurple_silcdir());
-	g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends",
-		   silcpurple_silcdir());
-
-	/*
-	 * Check ~/.silc directory
-	 */
-	if ((g_stat(filename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(filename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", filename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					filename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno));
-			return FALSE;
-		}
-	} else {
-#ifndef _WIN32
-		/* Check the owner of the dir */
-		if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-			purple_debug_error("silc", "You don't seem to own '%s' directory\n",
-				filename);
-			return FALSE;
-		}
-#endif
-	}
-
-	/*
-	 * Check ~./silc/serverkeys directory
-	 */
-	if ((g_stat(servfilename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(servfilename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					servfilename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
-							 servfilename, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-	/*
-	 * Check ~./silc/clientkeys directory
-	 */
-	if ((g_stat(clientfilename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(clientfilename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					clientfilename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
-							 clientfilename, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-	/*
-	 * Check ~./silc/friends directory
-	 */
-	if ((g_stat(friendsfilename, &st)) == -1) {
-		/* If dir doesn't exist */
-		if (errno == ENOENT) {
-			if (pw->pw_uid == geteuid()) {
-				if ((g_mkdir(friendsfilename, 0755)) == -1) {
-					purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
-					friendsfilename);
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
-							 friendsfilename, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-	/*
-	 * Check Public and Private keys
-	 */
-	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));
-	g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(gc->account, "private-key", prd));
-
-	if ((g_stat(file_public_key, &st)) == -1) {
-		/* If file doesn't exist */
-		if (errno == ENOENT) {
-			purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
-			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
-					     SILCPURPLE_DEF_PKCS_LEN,
-					     file_public_key, file_private_key, NULL,
-					     (gc->password == NULL) ? "" : gc->password,
-						 NULL, NULL, NULL, FALSE)) {
-				purple_debug_error("silc", "Couldn't create key pair\n");
-				return FALSE;
-			}
-
-			if ((g_stat(file_public_key, &st)) == -1) {
-				purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
-					file_public_key, g_strerror(errno));
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
-							 file_public_key, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-#ifndef _WIN32
-	/* Check the owner of the public key */
-	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-		purple_debug_error("silc", "You don't seem to own your public key!?\n");
-		return FALSE;
-	}
-#endif
-
-	if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
-		if ((fstat(fd, &st)) == -1) {
-			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							 file_private_key, g_strerror(errno));
-			close(fd);
-			return FALSE;
-		}
-	} else if ((g_stat(file_private_key, &st)) == -1) {
-		/* If file doesn't exist */
-		if (errno == ENOENT) {
-			purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
-			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
-					     SILCPURPLE_DEF_PKCS_LEN,
-					     file_public_key, file_private_key, NULL,
-					     (gc->password == NULL) ? "" : gc->password,
-						 NULL, NULL, NULL, FALSE)) {
-				purple_debug_error("silc", "Couldn't create key pair\n");
-				return FALSE;
-			}
-
-			if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
-				if ((fstat(fd, &st)) == -1) {
-					purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							 file_private_key, g_strerror(errno));
-					close(fd);
-					return FALSE;
-				}
-			}
-			/* This shouldn't really happen because silc_create_key_pair()
-			 * will set the permissions */
-			else if ((g_stat(file_private_key, &st)) == -1) {
-				purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-					file_private_key, g_strerror(errno));
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							 file_private_key, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-#ifndef _WIN32
-	/* Check the owner of the private key */
-	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-		purple_debug_error("silc", "You don't seem to own your private key!?\n");
-		if (fd != -1)
-			close(fd);
-		return FALSE;
-	}
-
-	/* Check the permissions for the private key */
-	if ((st.st_mode & 0777) != 0600) {
-		purple_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n"
-			"Trying to change them ...\n", file_private_key);
-		if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR)) == -1) {
-			purple_debug_error("silc",
-				"Failed to change permissions for private key file!\n"
-				"Permissions for your private key file must be 0600.\n");
-			if (fd != -1)
-				close(fd);
-			return FALSE;
-		}
-		purple_debug_warning("silc", "Done.\n\n");
-	}
-#endif
-
-	if (fd != -1)
-		close(fd);
-
-	return TRUE;
-}
-
-#ifdef _WIN32
-struct passwd *getpwuid(uid_t uid) {
-	struct passwd *pwd = calloc(1, sizeof(struct passwd));
-	return pwd;
-}
-
-uid_t getuid() {
-	return 0;
-}
-
-uid_t geteuid() {
-	return 0;
-}
-#endif
-
-void silcpurple_show_public_key(SilcPurple sg,
-			      const char *name, SilcPublicKey public_key,
-			      GCallback callback, void *context)
-{
-	SilcPublicKeyIdentifier ident;
-	SilcPKCS pkcs;
-	char *fingerprint, *babbleprint;
-	unsigned char *pk;
-	SilcUInt32 pk_len, key_len = 0;
-	GString *s;
-	char *buf;
-
-	ident = silc_pkcs_decode_identifier(public_key->identifier);
-	if (!ident)
-		return;
-
-	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-	fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-	babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-
-	if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) {
-		key_len = silc_pkcs_public_key_set(pkcs, public_key);
-		silc_pkcs_free(pkcs);
-	}
-
-	s = g_string_new("");
-	if (ident->realname)
-		/* Hint for translators: Please check the tabulator width here and in
-		   the next strings (short strings: 2 tabs, longer strings 1 tab,
-		   sum: 3 tabs or 24 characters) */
-		g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname);
-	if (ident->username)
-		g_string_append_printf(s, _("User Name: \t%s\n"), ident->username);
-	if (ident->email)
-		g_string_append_printf(s, _("Email: \t\t%s\n"), ident->email);
-	if (ident->host)
-		g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host);
-	if (ident->org)
-		g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
-	if (ident->country)
-		g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
-	g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name);
-	g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
-	g_string_append_printf(s, "\n");
-	g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
-	g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
-
-	buf = g_string_free(s, FALSE);
-
-	purple_request_action(sg->gc, _("Public Key Information"),
-			    _("Public Key Information"),
-			    buf, 0, purple_connection_get_account(sg->gc),
-				NULL, NULL, context, 1, _("Close"), callback);
-
-	g_free(buf);
-	silc_free(fingerprint);
-	silc_free(babbleprint);
-	silc_free(pk);
-	silc_pkcs_free_identifier(ident);
-}
-
-SilcAttributePayload
-silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute)
-{
-	SilcAttributePayload attr = NULL;
-
-	if (!attrs)
-		return NULL;
-
-	silc_dlist_start(attrs);
-	while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END)
-		if (attribute == silc_attribute_get_attribute(attr))
-			break;
-
-	return attr;
-}
-
-void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
-			       SilcUInt32 buf_size)
-{
-	memset(buf, 0, buf_size);
-	if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
-	    (mode & SILC_UMODE_ROUTER_OPERATOR)) {
-		strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
-		       "[server operator] " :
-		       (mode & SILC_UMODE_ROUTER_OPERATOR) ?
-		       "[SILC operator] " : "[unknown mode] ");
-	}
-	if (mode & SILC_UMODE_GONE)
-		strcat(buf, "[away] ");
-	if (mode & SILC_UMODE_INDISPOSED)
-		strcat(buf, "[indisposed] ");
-	if (mode & SILC_UMODE_BUSY)
-		strcat(buf, "[busy] ");
-	if (mode & SILC_UMODE_PAGE)
-		strcat(buf, "[wake me up] ");
-	if (mode & SILC_UMODE_HYPER)
-		strcat(buf, "[hyperactive] ");
-	if (mode & SILC_UMODE_ROBOT)
-		strcat(buf, "[robot] ");
-	if (mode & SILC_UMODE_ANONYMOUS)
-		strcat(buf, "[anonymous] ");
-	if (mode & SILC_UMODE_BLOCK_PRIVMSG)
-		strcat(buf, "[blocks private messages] ");
-	if (mode & SILC_UMODE_DETACHED)
-		strcat(buf, "[detached] ");
-	if (mode & SILC_UMODE_REJECT_WATCHING)
-		strcat(buf, "[rejects watching] ");
-	if (mode & SILC_UMODE_BLOCK_INVITE)
-		strcat(buf, "[blocks invites] ");
-	g_strchomp(buf);
-}
-
-void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
-				SilcUInt32 buf_size)
-{
-	memset(buf, 0, buf_size);
-	if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
-		strcat(buf, "[permanent] ");
-	if (mode & SILC_CHANNEL_MODE_PRIVATE)
-		strcat(buf, "[private] ");
-	if (mode & SILC_CHANNEL_MODE_SECRET)
-		strcat(buf, "[secret] ");
-	if (mode & SILC_CHANNEL_MODE_PRIVKEY)
-		strcat(buf, "[private key] ");
-	if (mode & SILC_CHANNEL_MODE_INVITE)
-		strcat(buf, "[invite only] ");
-	if (mode & SILC_CHANNEL_MODE_TOPIC)
-		strcat(buf, "[topic restricted] ");
-	if (mode & SILC_CHANNEL_MODE_ULIMIT)
-		strcat(buf, "[user count limit] ");
-	if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
-		strcat(buf, "[passphrase auth] ");
-	if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
-		strcat(buf, "[public key auth] ");
-	if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
-		strcat(buf, "[users silenced] ");
-	if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
-		strcat(buf, "[operators silenced] ");
-	g_strchomp(buf);
-}
-
-void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
-				 SilcUInt32 buf_size)
-{
-	memset(buf, 0, buf_size);
-	if (mode & SILC_CHANNEL_UMODE_CHANFO)
-		strcat(buf, "[founder] ");
-	if (mode & SILC_CHANNEL_UMODE_CHANOP)
-		strcat(buf, "[operator] ");
-	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
-		strcat(buf, "[blocks messages] ");
-	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
-		strcat(buf, "[blocks user messages] ");
-	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
-		strcat(buf, "[blocks robot messages] ");
-	if (mode & SILC_CHANNEL_UMODE_QUIET)
-		strcat(buf, "[quieted] ");
-	g_strchomp(buf);
-}
-
-void
-silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
-					 char **contactstr, char **langstr, char **devicestr,
-					 char **tzstr, char **geostr)
-{
-	SilcAttributePayload attr;
-	SilcAttributeMood mood = 0;
-	SilcAttributeContact contact;
-	SilcAttributeObjDevice device;
-	SilcAttributeObjGeo geo;
-
-	char tmp[1024];
-	GString *s;
-
-	*moodstr = NULL;
-	*statusstr = NULL;
-	*contactstr = NULL;
-	*langstr = NULL;
-	*devicestr = NULL;
-	*tzstr = NULL;
-	*geostr = NULL;
-
-	if (!attrs)
-		return;
-
-	s = g_string_new("");
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD);
-	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
-		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
-			g_string_append_printf(s, "[%s] ", _("Happy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
-			g_string_append_printf(s, "[%s] ", _("Sad"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
-			g_string_append_printf(s, "[%s] ", _("Angry"));
-		if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
-			g_string_append_printf(s, "[%s] ", _("Jealous"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
-			g_string_append_printf(s, "[%s] ", _("Ashamed"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
-			g_string_append_printf(s, "[%s] ", _("Invincible"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
-			g_string_append_printf(s, "[%s] ", _("In Love"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
-			g_string_append_printf(s, "[%s] ", _("Sleepy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_BORED)
-			g_string_append_printf(s, "[%s] ", _("Bored"));
-		if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
-			g_string_append_printf(s, "[%s] ", _("Excited"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
-			g_string_append_printf(s, "[%s] ", _("Anxious"));
-	}
-	if (strlen(s->str)) {
-		*moodstr = s->str;
-		g_string_free(s, FALSE);
-		g_strchomp(*moodstr);
-	} else
-		g_string_free(s, TRUE);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT);
-	memset(tmp, 0, sizeof(tmp));
-	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		*statusstr = g_strdup(tmp);
-
-	s = g_string_new("");
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT);
-	if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) {
-		if (contact & SILC_ATTRIBUTE_CONTACT_CHAT)
-			g_string_append_printf(s, "[%s] ", _("Chat"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL)
-			g_string_append_printf(s, "[%s] ", _("Email"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_CALL)
-			g_string_append_printf(s, "[%s] ", _("Phone"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_PAGE)
-			g_string_append_printf(s, "[%s] ", _("Paging"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_SMS)
-			g_string_append_printf(s, "[%s] ", _("SMS"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_MMS)
-			g_string_append_printf(s, "[%s] ", _("MMS"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO)
-			g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
-	}
-	if (strlen(s->str)) {
-		*contactstr = s->str;
-		g_string_free(s, FALSE);
-		g_strchomp(*contactstr);
-	} else
-		g_string_free(s, TRUE);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE);
-	memset(tmp, 0, sizeof(tmp));
-	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		*langstr = g_strdup(tmp);
-
-	s = g_string_new("");
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO);
-	memset(&device, 0, sizeof(device));
-	if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) {
-		if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER)
-			g_string_append_printf(s, "%s: ", _("Computer"));
-		if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE)
-			g_string_append_printf(s, "%s: ", _("Mobile Phone"));
-		if (device.type == SILC_ATTRIBUTE_DEVICE_PDA)
-			g_string_append_printf(s, "%s: ", _("PDA"));
-		if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL)
-			g_string_append_printf(s, "%s: ", _("Terminal"));
-		g_string_append_printf(s, "%s %s %s %s",
-				device.manufacturer ? device.manufacturer : "",
-				device.version ? device.version : "",
-				device.model ? device.model : "",
-				device.language ? device.language : "");
-	}
-	if (strlen(s->str)) {
-		*devicestr = s->str;
-		g_string_free(s, FALSE);
-	} else
-		g_string_free(s, TRUE);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE);
-	memset(tmp, 0, sizeof(tmp));
-	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		*tzstr = g_strdup(tmp);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION);
-	memset(&geo, 0, sizeof(geo));
-	if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo)))
-		*geostr = g_strdup_printf("%s %s %s (%s)",
-				geo.longitude ? geo.longitude : "",
-				geo.latitude ? geo.latitude : "",
-				geo.altitude ? geo.altitude : "",
-				geo.accuracy ? geo.accuracy : "");
-}
-
-#ifdef HAVE_SILCMIME_H
-/* Returns MIME type of filetype */
-
-char *silcpurple_file2mime(const char *filename)
-{
-	const char *ct;
-
-	ct = strrchr(filename, '.');
-	if (!ct)
-		return NULL;
-	else if (!g_ascii_strcasecmp(".png", ct))
-		return strdup("image/png");
-	else if (!g_ascii_strcasecmp(".jpg", ct))
-		return strdup("image/jpeg");
-	else if (!g_ascii_strcasecmp(".jpeg", ct))
-		return strdup("image/jpeg");
-	else if (!g_ascii_strcasecmp(".gif", ct))
-		return strdup("image/gif");
-	else if (!g_ascii_strcasecmp(".tiff", ct))
-		return strdup("image/tiff");
-
-	return NULL;
-}
-
-/* Checks if message has images, and assembles MIME message if it has.
-   If only one image is present, creates simple MIME image message.  If
-   there are multiple images and/or text with images multipart MIME
-   message is created. */
-
-SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags)
-{
-	SilcMime mime = NULL, p;
-	SilcDList list, parts = NULL;
-	const char *start, *end, *last;
-	GData *attribs;
-	char *type;
-	gboolean images = FALSE;
-
-	last = msg;
-	while (last && *last && purple_markup_find_tag("img", last, &start,
-						     &end, &attribs)) {
-		PurpleStoredImage *image = NULL;
-		const char *id;
-
-		/* Check if there is text before image */
-		if (start - last) {
-			char *text, *tmp;
-			p = silc_mime_alloc();
-
-			/* Add content type */
-			silc_mime_add_field(p, "Content-Type",
-					    "text/plain; charset=utf-8");
-
-			tmp = g_strndup(last, start - last);
-			text = purple_unescape_html(tmp);
-			g_free(tmp);
-			/* Add text */
-			silc_mime_add_data(p, (unsigned char *)text, strlen(text));
-			g_free(text);
-
-			if (!parts)
-				parts = silc_dlist_init();
-			silc_dlist_add(parts, p);
-		}
-
-		id = g_datalist_get_data(&attribs, "id");
-		if (id && (image = purple_imgstore_find_by_id(atoi(id)))) {
-			unsigned long imglen = purple_imgstore_get_size(image);
-			gconstpointer img = purple_imgstore_get_data(image);
-
-			p = silc_mime_alloc();
-
-			/* Add content type */
-			type = silcpurple_file2mime(purple_imgstore_get_filename(image));
-			if (!type) {
-				g_datalist_clear(&attribs);
-				last = end + 1;
-				continue;
-			}
-			silc_mime_add_field(p, "Content-Type", type);
-			silc_free(type);
-
-			/* Add content transfer encoding */
-			silc_mime_add_field(p, "Content-Transfer-Encoding", "binary");
-
-			/* Add image data */
-			silc_mime_add_data(p, img, imglen);
-
-			if (!parts)
-				parts = silc_dlist_init();
-			silc_dlist_add(parts, p);
-			images = TRUE;
-		}
-
-		g_datalist_clear(&attribs);
-
-		/* Continue after tag */
-		last = end + 1;
-	}
-
-	/* Check for text after the image(s) */
-	if (images && last && *last) {
-		char *tmp = purple_unescape_html(last);
-		p = silc_mime_alloc();
-
-		/* Add content type */
-		silc_mime_add_field(p, "Content-Type",
-				    "text/plain; charset=utf-8");
-
-		/* Add text */
-		silc_mime_add_data(p, (unsigned char *)tmp, strlen(tmp));
-		g_free(tmp);
-
-		if (!parts)
-			parts = silc_dlist_init();
-		silc_dlist_add(parts, p);
-	}
-
-	/* If there weren't any images, don't return anything. */
-	if (!images) {
-		if (parts)
-			silc_dlist_uninit(parts);
-		return NULL;
-	}
-
-	if (silc_dlist_count(parts) > 1) {
-		/* Multipart MIME message */
-		char b[32];
-		mime = silc_mime_alloc();
-		silc_mime_add_field(mime, "MIME-Version", "1.0");
-		g_snprintf(b, sizeof(b), "b%4X%4X",
-			   (unsigned int)time(NULL),
-			   silc_dlist_count(parts));
-		silc_mime_set_multipart(mime, "mixed", b);
-		silc_dlist_start(parts);
-		while ((p = silc_dlist_get(parts)) != SILC_LIST_END)
-			silc_mime_add_multipart(mime, p);
-	} else {
-		/* Simple MIME message */
-		silc_dlist_start(parts);
-		mime = silc_dlist_get(parts);
-		silc_mime_add_field(mime, "MIME-Version", "1.0");
-	}
-
-	*mflags &= ~SILC_MESSAGE_FLAG_UTF8;
-	*mflags |= SILC_MESSAGE_FLAG_DATA;
-
-	/* Encode message. Fragment if it is too large */
-	list = silc_mime_encode_partial(mime, 0xfc00);
-
-	silc_dlist_uninit(parts);
-
-	/* Added multiparts gets freed here */
-	silc_mime_free(mime);
-
-	return list;
-}
-
-#endif /* HAVE_SILCMIME_H */
--- a/libpurple/protocols/silc10/wb.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,520 +0,0 @@
-/*
-
-  wb.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2005 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include "silcincludes.h"
-#include "silcclient.h"
-#include "silcpurple.h"
-#include "wb.h"
-
-/*
-  SILC Whiteboard packet:
-
-  1 byte	command
-  2 bytes	width
-  2 bytes	height
-  4 bytes	brush color
-  2 bytes	brush size
-  n bytes	data
-
-  Data:
-
-  4 bytes	x
-  4 bytes	y
-
-  Commands:
-
-  0x01		draw
-  0x02		clear
-
-  MIME:
-
-  MIME-Version: 1.0
-  Content-Type: application/x-wb
-  Content-Transfer-Encoding: binary
-
-*/
-
-#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n"
-#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11
-
-#define SILCPURPLE_WB_WIDTH 500
-#define SILCPURPLE_WB_HEIGHT 400
-#define SILCPURPLE_WB_WIDTH_MAX 1024
-#define SILCPURPLE_WB_HEIGHT_MAX 1024
-
-/* Commands */
-typedef enum {
-	SILCPURPLE_WB_DRAW 	= 0x01,
-	SILCPURPLE_WB_CLEAR	= 0x02
-} SilcPurpleWbCommand;
-
-/* Brush size */
-typedef enum {
-	SILCPURPLE_WB_BRUSH_SMALL = 2,
-	SILCPURPLE_WB_BRUSH_MEDIUM = 5,
-	SILCPURPLE_WB_BRUSH_LARGE = 10
-} SilcPurpleWbBrushSize;
-
-/* Brush color (XXX Purple should provide default colors) */
-typedef enum {
-	SILCPURPLE_WB_COLOR_BLACK		= 0,
-	SILCPURPLE_WB_COLOR_RED		= 13369344,
-	SILCPURPLE_WB_COLOR_GREEN		= 52224,
-	SILCPURPLE_WB_COLOR_BLUE		= 204,
-	SILCPURPLE_WB_COLOR_YELLOW 	= 15658496,
-	SILCPURPLE_WB_COLOR_ORANGE	= 16737792,
-	SILCPURPLE_WB_COLOR_CYAN		= 52428,
-	SILCPURPLE_WB_COLOR_VIOLET	= 5381277,
-	SILCPURPLE_WB_COLOR_PURPLE	= 13369548,
-	SILCPURPLE_WB_COLOR_TAN		= 12093547,
-	SILCPURPLE_WB_COLOR_BROWN		= 5256485,
-	SILCPURPLE_WB_COLOR_GREY		= 11184810,
-	SILCPURPLE_WB_COLOR_WHITE		= 16777215
-} SilcPurpleWbColor;
-
-typedef struct {
-	int type;		/* 0 = buddy, 1 = channel */
-	union {
-		SilcClientEntry client;
-		SilcChannelEntry channel;
-	} u;
-	int width;
-	int height;
-	int brush_size;
-	int brush_color;
-} *SilcPurpleWb;
-
-/* Initialize whiteboard */
-
-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);
-	if (!wb)
-		return NULL;
-
-	if (!wb->proto_data) {
-		wbs = silc_calloc(1, sizeof(*wbs));
-		if (!wbs)
-			return NULL;
-		wbs->type = 0;
-		wbs->u.client = client_entry;
-		wbs->width = SILCPURPLE_WB_WIDTH;
-		wbs->height = SILCPURPLE_WB_HEIGHT;
-		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
-		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
-		wb->proto_data = wbs;
-
-		/* Start the whiteboard */
-		purple_whiteboard_start(wb);
-		purple_whiteboard_clear(wb);
-	}
-
-	return wb;
-}
-
-PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel)
-{
-	PurpleWhiteboard *wb;
-	SilcPurpleWb wbs;
-
-	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);
-	if (!wb)
-		wb = purple_whiteboard_create(sg->account, channel->channel_name, 0);
-	if (!wb)
-		return NULL;
-
-	if (!wb->proto_data) {
-		wbs = silc_calloc(1, sizeof(*wbs));
-		if (!wbs)
-			return NULL;
-		wbs->type = 1;
-		wbs->u.channel = channel;
-		wbs->width = SILCPURPLE_WB_WIDTH;
-		wbs->height = SILCPURPLE_WB_HEIGHT;
-		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
-		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
-		wb->proto_data = wbs;
-
-		/* Start the whiteboard */
-		purple_whiteboard_start(wb);
-		purple_whiteboard_clear(wb);
-	}
-
-	return wb;
-}
-
-static void
-silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb,
-		  unsigned char *message, SilcUInt32 message_len)
-{
-	SilcUInt8 command;
-	SilcUInt16 width, height, brush_size;
-	SilcUInt32 brush_color, x, y, dx, dy;
-	SilcBufferStruct buf;
-	int ret;
-
-	/* Parse the packet */
-	silc_buffer_set(&buf, message, message_len);
-	ret = silc_buffer_unformat(&buf,
-				   SILC_STR_UI_CHAR(&command),
-				   SILC_STR_UI_SHORT(&width),
-				   SILC_STR_UI_SHORT(&height),
-				   SILC_STR_UI_INT(&brush_color),
-				   SILC_STR_UI_SHORT(&brush_size),
-				   SILC_STR_END);
-	if (ret < 0)
-		return;
-	silc_buffer_pull(&buf, ret);
-
-	/* Update whiteboard if its dimensions changed */
-	if (width != wbs->width || height != wbs->height)
-		silcpurple_wb_set_dimensions(wb, height, width);
-
-	if (command == SILCPURPLE_WB_DRAW) {
-		/* Parse data and draw it */
-		ret = silc_buffer_unformat(&buf,
-					   SILC_STR_UI_INT(&dx),
-					   SILC_STR_UI_INT(&dy),
-					   SILC_STR_END);
-		if (ret < 0)
-			return;
-		silc_buffer_pull(&buf, 8);
-		x = dx;
-		y = dy;
-		while (buf.len > 0) {
-			ret = silc_buffer_unformat(&buf,
-						   SILC_STR_UI_INT(&dx),
-						   SILC_STR_UI_INT(&dy),
-						   SILC_STR_END);
-			if (ret < 0)
-				return;
-			silc_buffer_pull(&buf, 8);
-
-			purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy,
-						  brush_color, brush_size);
-			x += dx;
-			y += dy;
-		}
-	}
-
-	if (command == SILCPURPLE_WB_CLEAR)
-		purple_whiteboard_clear(wb);
-}
-
-typedef struct {
-  unsigned char *message;
-  SilcUInt32 message_len;
-  SilcPurple sg;
-  SilcClientEntry sender;
-  SilcChannelEntry channel;
-} *SilcPurpleWbRequest;
-
-static void
-silcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id)
-{
-	PurpleWhiteboard *wb;
-
-        if (id != 1)
-                goto out;
-
-	if (!req->channel)
-		wb = silcpurple_wb_init(req->sg, req->sender);
-	else
-		wb = silcpurple_wb_init_ch(req->sg, req->channel);
-
-	silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len);
-
-  out:
-	silc_free(req->message);
-	silc_free(req);
-}
-
-static void
-silcpurple_wb_request(SilcClient client, const unsigned char *message,
-		    SilcUInt32 message_len, SilcClientEntry sender,
-		    SilcChannelEntry channel)
-{
-	char tmp[128];
-	SilcPurpleWbRequest req;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = client->application;
-	sg = gc->proto_data;
-
-	/* Open whiteboard automatically if requested */
-	if (purple_account_get_bool(sg->account, "open-wb", FALSE)) {
-		PurpleWhiteboard *wb;
-
-		if (!channel)
-			wb = silcpurple_wb_init(sg, sender);
-		else
-			wb = silcpurple_wb_init_ch(sg, channel);
-
-		silcpurple_wb_parse(wb->proto_data, wb, (unsigned char *)message,
-				  message_len);
-		return;
-	}
-
-	/* Close any previous unaccepted requests */
-	purple_request_close_with_handle(sender);
-
-	if (!channel) {
-		g_snprintf(tmp, sizeof(tmp),
-			_("%s sent message to whiteboard. Would you like "
-			  "to open the whiteboard?"), sender->nickname);
-	} else {
-		g_snprintf(tmp, sizeof(tmp),
-			_("%s sent message to whiteboard on %s channel. "
-			  "Would you like to open the whiteboard?"),
-			sender->nickname, channel->channel_name);
-	}
-
-	req = silc_calloc(1, sizeof(*req));
-	if (!req)
-		return;
-	req->message = silc_memdup(message, message_len);
-	req->message_len = message_len;
-	req->sender = sender;
-	req->channel = channel;
-	req->sg = sg;
-
-	purple_request_action(sender, _("Whiteboard"), tmp, NULL, 1,
-				sg->account, sender->nickname, NULL, req, 2,
-			    _("Yes"), G_CALLBACK(silcpurple_wb_request_cb),
-			    _("No"), G_CALLBACK(silcpurple_wb_request_cb));
-}
-
-/* Process incoming whiteboard message */
-
-void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,
-			 SilcClientEntry sender, SilcMessagePayload payload,
-			 SilcMessageFlags flags, const unsigned char *message,
-			 SilcUInt32 message_len)
-{
-	SilcPurple sg;
-        PurpleConnection *gc;
-	PurpleWhiteboard *wb;
-	SilcPurpleWb wbs;
-
-	gc = client->application;
-        sg = gc->proto_data;
-
-	wb = purple_whiteboard_get_session(sg->account, sender->nickname);
-	if (!wb) {
-		/* Ask user if they want to open the whiteboard */
-		silcpurple_wb_request(client, message, message_len,
-				    sender, NULL);
-		return;
-	}
-
-	wbs = wb->proto_data;
-	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);
-}
-
-/* Process incoming whiteboard message on channel */
-
-void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,
-			    SilcClientEntry sender, SilcChannelEntry channel,
-			    SilcMessagePayload payload,
-			    SilcMessageFlags flags,
-			    const unsigned char *message,
-			    SilcUInt32 message_len)
-{
-	SilcPurple sg;
-        PurpleConnection *gc;
-	PurpleWhiteboard *wb;
-	SilcPurpleWb wbs;
-
-	gc = client->application;
-        sg = gc->proto_data;
-
-	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);
-	if (!wb) {
-		/* Ask user if they want to open the whiteboard */
-		silcpurple_wb_request(client, message, message_len,
-				    sender, channel);
-		return;
-	}
-
-	wbs = wb->proto_data;
-	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);
-}
-
-/* Send whiteboard message */
-
-void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list)
-{
-	SilcPurpleWb wbs = wb->proto_data;
-	SilcBuffer packet;
-	GList *list;
-	int len;
-        PurpleConnection *gc;
-        SilcPurple sg;
-
-	g_return_if_fail(draw_list);
-	gc = purple_account_get_connection(wb->account);
-	g_return_if_fail(gc);
- 	sg = gc->proto_data;
-	g_return_if_fail(sg);
-
-	len = SILCPURPLE_WB_HEADER;
-	for (list = draw_list; list; list = list->next)
-		len += 4;
-
-	packet = silc_buffer_alloc_size(len);
-	if (!packet)
-		return;
-
-	/* Assmeble packet */
-	silc_buffer_format(packet,
-			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),
-			   SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW),
-			   SILC_STR_UI_SHORT(wbs->width),
-			   SILC_STR_UI_SHORT(wbs->height),
-			   SILC_STR_UI_INT(wbs->brush_color),
-			   SILC_STR_UI_SHORT(wbs->brush_size),
-			   SILC_STR_END);
-	silc_buffer_pull(packet, SILCPURPLE_WB_HEADER);
-	for (list = draw_list; list; list = list->next) {
-		silc_buffer_format(packet,
-				   SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)),
-				   SILC_STR_END);
-		silc_buffer_pull(packet, 4);
-	}
-
-	/* Send the message */
-	if (wbs->type == 0) {
-		/* Private message */
-		silc_client_send_private_message(sg->client, sg->conn,
-						 wbs->u.client,
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
-	} else if (wbs->type == 1) {
-		/* Channel message. Channel private keys are not supported. */
-		silc_client_send_channel_message(sg->client, sg->conn,
-						 wbs->u.channel, NULL,
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
-	}
-
-	silc_buffer_free(packet);
-}
-
-/* Purple Whiteboard operations */
-
-void silcpurple_wb_start(PurpleWhiteboard *wb)
-{
-	/* Nothing here.  Everything is in initialization */
-}
-
-void silcpurple_wb_end(PurpleWhiteboard *wb)
-{
-	silc_free(wb->proto_data);
-	wb->proto_data = NULL;
-}
-
-void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
-{
-	SilcPurpleWb wbs = wb->proto_data;
-	*width = wbs->width;
-	*height = wbs->height;
-}
-
-void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height)
-{
-	SilcPurpleWb wbs = wb->proto_data;
-	wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX :
-			width;
-	wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX :
-			height;
-
-	/* Update whiteboard */
-	purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height);
-}
-
-void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
-{
-	SilcPurpleWb wbs = wb->proto_data;
-	*size = wbs->brush_size;
-	*color = wbs->brush_color;
-}
-
-void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color)
-{
-	SilcPurpleWb wbs = wb->proto_data;
-	wbs->brush_size = size;
-	wbs->brush_color = color;
-
-	/* Update whiteboard */
-	purple_whiteboard_set_brush(wb, size, color);
-}
-
-void silcpurple_wb_clear(PurpleWhiteboard *wb)
-{
-	SilcPurpleWb wbs = wb->proto_data;
-	SilcBuffer packet;
-	int len;
-        PurpleConnection *gc;
-        SilcPurple sg;
-
-	gc = purple_account_get_connection(wb->account);
-	g_return_if_fail(gc);
- 	sg = gc->proto_data;
-	g_return_if_fail(sg);
-
-	len = SILCPURPLE_WB_HEADER;
-	packet = silc_buffer_alloc_size(len);
-	if (!packet)
-		return;
-
-	/* Assmeble packet */
-	silc_buffer_format(packet,
-			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),
-			   SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR),
-			   SILC_STR_UI_SHORT(wbs->width),
-			   SILC_STR_UI_SHORT(wbs->height),
-			   SILC_STR_UI_INT(wbs->brush_color),
-			   SILC_STR_UI_SHORT(wbs->brush_size),
-			   SILC_STR_END);
-
-	/* Send the message */
-	if (wbs->type == 0) {
-		/* Private message */
-		silc_client_send_private_message(sg->client, sg->conn,
-						 wbs->u.client,
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
-	} else if (wbs->type == 1) {
-		/* Channel message */
-		silc_client_send_channel_message(sg->client, sg->conn,
-						 wbs->u.channel, NULL,
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
-	}
-
-	silc_buffer_free(packet);
-}
--- a/libpurple/protocols/silc10/wb.h	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
-
-  silcpurple.h
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2005 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#ifndef SILCPURPLE_WB_H
-#define SILCPURPLE_WB_H
-
-#include "silcpurple.h"
-#include "whiteboard.h"
-
-PurpleWhiteboard *
-silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry);
-PurpleWhiteboard *
-silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel);
-void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,
-			 SilcClientEntry sender, SilcMessagePayload payload,
-			 SilcMessageFlags flags, const unsigned char *message,
-			 SilcUInt32 message_len);
-void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,
-			    SilcClientEntry sender, SilcChannelEntry channel,
-			    SilcMessagePayload payload,
-			    SilcMessageFlags flags,
-			    const unsigned char *message,
-			    SilcUInt32 message_len);
-void silcpurple_wb_start(PurpleWhiteboard *wb);
-void silcpurple_wb_end(PurpleWhiteboard *wb);
-void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height);
-void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height);
-void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color);
-void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color);
-void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list);
-void silcpurple_wb_clear(PurpleWhiteboard *wb);
-
-#endif /* SILCPURPLE_WB_H */
--- a/libpurple/protocols/simple/simple.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/simple/simple.c	Mon Oct 31 01:25:36 2011 +0000
@@ -67,7 +67,7 @@
 }
 
 static void simple_keep_alive(PurpleConnection *gc) {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	if(sip->udp) { /* in case of UDP send a packet only with a 0 byte to
 			 remain in the NAT table */
 		gchar buf[2] = {0, 0};
@@ -100,14 +100,15 @@
 }
 
 static void simple_set_status(PurpleAccount *account, PurpleStatus *status) {
+	PurpleConnection *gc = purple_account_get_connection(account);
 	PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_type(status));
 	struct simple_account_data *sip = NULL;
 
 	if (!purple_status_is_active(status))
 		return;
 
-	if (account->gc)
-		sip = account->gc->proto_data;
+	if (gc)
+		sip = purple_connection_get_protocol_data(gc);
 
 	if (sip)
 	{
@@ -192,9 +193,9 @@
 	}
 }
 
-static void simple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+static void simple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
 {
-	struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	struct simple_buddy *b;
 	const char *name = purple_buddy_get_name(buddy);
 	if(strncmp(name, "sip:", 4)) {
@@ -222,7 +223,7 @@
 	buddies = purple_find_buddies(account, NULL);
 	while (buddies) {
 		PurpleBuddy *buddy = buddies->data;
-		simple_add_buddy(gc, buddy, purple_buddy_get_group(buddy));
+		simple_add_buddy(gc, buddy, purple_buddy_get_group(buddy), NULL);
 
 		buddies = g_slist_delete_link(buddies, buddies);
 	}
@@ -231,7 +232,7 @@
 static void simple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
 	const char *name = purple_buddy_get_name(buddy);
-	struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	struct simple_buddy *b = g_hash_table_lookup(sip->buddies, name);
 	g_hash_table_remove(sip->buddies, name);
 	g_free(b->name);
@@ -412,7 +413,7 @@
 
 static void simple_canwrite_cb(gpointer data, gint source, PurpleInputCondition cond) {
 	PurpleConnection *gc = data;
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	gsize max_write;
 	gssize written;
 
@@ -432,7 +433,7 @@
 		/*TODO: do we really want to disconnect on a failure to write?*/
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
@@ -451,13 +452,13 @@
 	if(source < 0) {
 		gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
 				error_message);
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	}
 
-	sip = gc->proto_data;
+	sip = purple_connection_get_protocol_data(gc);
 	sip->fd = source;
 	sip->connecting = FALSE;
 
@@ -474,12 +475,12 @@
 
 
 static void sendlater(PurpleConnection *gc, const char *buf) {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 
 	if(!sip->connecting) {
 		purple_debug_info("simple", "connecting to %s port %d\n", sip->realhostname ? sip->realhostname : "{NULL}", sip->realport);
 		if (purple_proxy_connect(gc, sip->account, sip->realhostname, sip->realport, send_later_cb, gc) == NULL) {
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
 		}
 		sip->connecting = TRUE;
 	}
@@ -491,7 +492,7 @@
 }
 
 static void sendout_pkt(PurpleConnection *gc, const char *buf) {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	time_t currtime = time(NULL);
 	int writelen = strlen(buf);
 
@@ -629,7 +630,7 @@
 static void send_sip_request(PurpleConnection *gc, const gchar *method,
 		const gchar *url, const gchar *to, const gchar *addheaders,
 		const gchar *body, struct sip_dialog *dialog, TransCallback tc) {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	char *callid = dialog ? g_strdup(dialog->callid) : gencallid();
 	char *auth = NULL;
 	const char *addh = "";
@@ -1026,7 +1027,7 @@
 }
 
 static int simple_im_send(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	char *to = g_strdup(who);
 	char *text = purple_unescape_html(what);
 	simple_send_message(sip, to, text, NULL);
@@ -1120,9 +1121,9 @@
 			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);
-					purple_connection_error_reason(sip->gc,
+					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"));
 					return TRUE;
@@ -1137,7 +1138,7 @@
 			if (sip->registerstatus != SIMPLE_REGISTER_RETRY) {
 				purple_debug_info("simple", "Unrecognized return code for REGISTER.\n");
 				if (sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) {
-					purple_connection_error_reason(sip->gc,
+					purple_connection_error(sip->gc,
 						PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 						_("Unknown server response"));
 					return TRUE;
@@ -1285,7 +1286,7 @@
 }
 
 static unsigned int simple_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 
 	gchar *xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 			"<isComposing xmlns=\"urn:ietf:params:xml:ns:im-iscomposing\"\n"
@@ -1661,7 +1662,7 @@
 
 static void simple_udp_process(gpointer data, gint source, PurpleInputCondition con) {
 	PurpleConnection *gc = data;
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	struct sipmsg *msg;
 	int len;
 	time_t currtime = time(NULL);
@@ -1681,7 +1682,7 @@
 static void simple_input_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = data;
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	int len;
 	struct sip_connection *conn = connection_find(sip, source);
 	if(!conn) {
@@ -1704,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';
 
@@ -1714,7 +1715,7 @@
 /* Callback for new connections on incoming TCP port */
 static void simple_newconn_cb(gpointer data, gint source, PurpleInputCondition cond) {
 	PurpleConnection *gc = data;
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	struct sip_connection *conn;
 	int newfd, flags;
 
@@ -1739,13 +1740,13 @@
 	if(source < 0) {
 		gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
 				error_message);
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	}
 
-	sip = gc->proto_data;
+	sip = purple_connection_get_protocol_data(gc);
 	sip->fd = source;
 
 	conn = connection_create(sip, source);
@@ -1775,7 +1776,7 @@
 	sip->listen_data = NULL;
 
 	if(listenfd == -1) {
-		purple_connection_error_reason(sip->gc,
+		purple_connection_error(sip->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to create listen socket"));
 		return;
@@ -1804,7 +1805,7 @@
 	sip->query_data = NULL;
 
 	if (!hosts || !hosts->data) {
-		purple_connection_error_reason(sip->gc,
+		purple_connection_error(sip->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to resolve hostname"));
 		return;
@@ -1822,10 +1823,10 @@
 	}
 
 	/* create socket for incoming connections */
-	sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_DGRAM,
+	sip->listen_data = purple_network_listen_range(5060, 5160, AF_UNSPEC, SOCK_DGRAM, TRUE,
 				simple_udp_host_resolved_listen_cb, sip);
 	if (sip->listen_data == NULL) {
-		purple_connection_error_reason(sip->gc,
+		purple_connection_error(sip->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to create listen socket"));
 		return;
@@ -1840,7 +1841,7 @@
 
 	sip->listenfd = listenfd;
 	if(sip->listenfd == -1) {
-		purple_connection_error_reason(sip->gc,
+		purple_connection_error(sip->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to create listen socket"));
 		return;
@@ -1855,7 +1856,7 @@
 	/* open tcp connection to the server */
 	if (purple_proxy_connect(sip->gc, sip->account, sip->realhostname,
 			sip->realport, login_cb, sip->gc) == NULL) {
-		purple_connection_error_reason(sip->gc,
+		purple_connection_error(sip->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Unable to connect"));
 	}
@@ -1892,10 +1893,10 @@
 	/* TCP case */
 	if(!sip->udp) {
 		/* create socket for incoming connections */
-		sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_STREAM,
+		sip->listen_data = purple_network_listen_range(5060, 5160, AF_UNSPEC, SOCK_STREAM, TRUE,
 					simple_tcp_connect_listen_cb, sip);
 		if (sip->listen_data == NULL) {
-			purple_connection_error_reason(sip->gc,
+			purple_connection_error(sip->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to create listen socket"));
 			return;
@@ -1903,10 +1904,10 @@
 	} else { /* UDP */
 		purple_debug_info("simple", "using udp with server %s and port %d\n", hostname, port);
 
-		sip->query_data = purple_dnsquery_a_account(sip->account, hostname,
+		sip->query_data = purple_dnsquery_a(sip->account, hostname,
 			port, simple_udp_host_resolved, sip);
 		if (sip->query_data == NULL) {
-			purple_connection_error_reason(sip->gc,
+			purple_connection_error(sip->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Unable to resolve hostname"));
 		}
@@ -1924,13 +1925,14 @@
 	gc = purple_account_get_connection(account);
 
 	if (strpbrk(username, " \t\v\r\n") != NULL) {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("SIP usernames may not contain whitespaces or @ symbols"));
 		return;
 	}
 
-	gc->proto_data = sip = g_new0(struct simple_account_data, 1);
+	sip = g_new0(struct simple_account_data, 1);
+	purple_connection_set_protocol_data(gc, sip);
 	sip->gc = gc;
 	sip->fd = -1;
 	sip->listenfd = -1;
@@ -1943,7 +1945,7 @@
 
 	userserver = g_strsplit(username, "@", 2);
 	if (userserver[1] == NULL || userserver[1][0] == '\0') {
-		purple_connection_error_reason(gc,
+		purple_connection_error(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
 			_("SIP connect server not specified"));
 		return;
@@ -1968,13 +1970,13 @@
 		hosttoconnect = purple_account_get_string(account, "proxy", sip->servername);
 	}
 
-	sip->srv_query_data = purple_srv_resolve_account(account, "sip",
+	sip->srv_query_data = purple_srv_resolve(account, "sip",
 			sip->udp ? "udp" : "tcp", hosttoconnect, srvresolved, sip);
 }
 
 static void simple_close(PurpleConnection *gc)
 {
-	struct simple_account_data *sip = gc->proto_data;
+	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 
 	if (!sip)
 		return;
@@ -2005,7 +2007,7 @@
 		purple_dnsquery_destroy(sip->query_data);
 
 	if (sip->srv_query_data != NULL)
-		purple_srv_cancel(sip->srv_query_data);
+		purple_srv_txt_query_destroy(sip->srv_query_data);
 
 	if (sip->listen_data != NULL)
 		purple_network_listen_cancel(sip->listen_data);
@@ -2039,11 +2041,12 @@
 	g_free(sip->realhostname);
 
 	g_free(sip);
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 }
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	0,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
@@ -2084,7 +2087,6 @@
 	simple_keep_alive,		/* keepalive */
 	NULL,					/* register_user */
 	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
 	NULL,					/* alias_buddy */
 	NULL,					/* group_buddy */
 	NULL,					/* rename_group */
@@ -2109,15 +2111,12 @@
 	NULL,					/* unregister_user */
 	NULL,					/* send_attention */
 	NULL,					/* get_attention_types */
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,					/* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* get_media_caps */
 	NULL,					/* get_moods */
 	NULL,					/* set_public_alias */
-	NULL,					/* get_public_alias */
-	NULL,					/* add_buddy_with_invite */
-	NULL					/* add_buddies_with_invite */
+	NULL					/* get_public_alias */
 };
 
 
--- a/libpurple/protocols/yahoo/libyahoo.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/libyahoo.c	Mon Oct 31 01:25:36 2011 +0000
@@ -194,6 +194,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
 	NULL, /* user_splits */
 	NULL, /* protocol_options */
@@ -234,7 +235,6 @@
 	yahoo_keepalive,
 	NULL, /* register_user */
 	NULL, /* get_cb_info */
-	NULL, /* get_cb_away */
 	yahoo_update_alias, /* alias_buddy */
 	yahoo_change_buddys_group,
 	yahoo_rename_group,
@@ -257,19 +257,14 @@
 	NULL, /* send_raw */
 	NULL, /* roomlist_room_serialize */
 	NULL, /* unregister_user */
-
 	yahoo_send_attention,
 	yahoo_attention_types,
-
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	yahoo_get_account_text_table,    /* get_account_text_table */
 	NULL, /* initiate_media */
 	NULL,  /* get_media_caps */
 	NULL,  /* get_moods */
 	NULL,  /* set_public_alias */
-	NULL,  /* get_public_alias */
-	NULL,  /* add_buddy_with_invite */
-	NULL   /* add_buddies_with_invite */
+	NULL   /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/yahoo/libyahoojp.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/libyahoojp.c	Mon Oct 31 01:25:36 2011 +0000
@@ -90,6 +90,7 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
 	NULL, /* user_splits */
 	NULL, /* protocol_options */
@@ -130,7 +131,6 @@
 	yahoo_keepalive,
 	NULL, /* register_user */
 	NULL, /* get_cb_info */
-	NULL, /* get_cb_away */
 	yahoo_update_alias, /* alias_buddy */
 	yahoo_change_buddys_group,
 	yahoo_rename_group,
@@ -157,15 +157,12 @@
 	yahoo_send_attention,
 	yahoo_attention_types,
 
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	yahoojp_get_account_text_table,    /* get_account_text_table */
 	NULL, /* initiate_media */
 	NULL, /* get_media_caps */
 	NULL, /* get_moods */
 	NULL, /* set_public_alias */
-	NULL, /* get_public_alias */
-	NULL, /* add_buddy_with_invite */
-	NULL  /* add_buddies_with_invite */
+	NULL  /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/yahoo/libymsg.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/libymsg.c	Mon Oct 31 01:25:36 2011 +0000
@@ -159,7 +159,7 @@
 	if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
 		if (!purple_account_get_remember_password(account))
 			purple_account_set_password(account, NULL);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE,
 			_("You have signed on from another location"));
 		return;
 	}
@@ -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;
 			}
 
@@ -496,7 +496,7 @@
 	GSList *l = pkt->hash;
 
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GHashTable *ht;
 	char *norm_bud = NULL;
 	char *temp = NULL;
@@ -573,7 +573,7 @@
 						yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
 				} else {
 					/* This buddy is on the ignore list (and therefore in no group) */
-					purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n",account->username, norm_bud);
+					purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", purple_account_get_username(account), norm_bud);
 					purple_privacy_deny_add(account, norm_bud, 1);
 				}
 
@@ -638,7 +638,7 @@
 	gboolean got_serv_list = FALSE;
 	YahooFriend *f = NULL;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GHashTable *ht;
 
 	char **lines;
@@ -748,13 +748,13 @@
 	}
 
 	if (got_serv_list &&
-		((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
-		(account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
-		(account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
+		((purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
+		(purple_account_get_privacy_type(account) != PURPLE_PRIVACY_DENY_ALL) &&
+		(purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_USERS)))
 	{
-		account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+		purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
 		purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n",
-				account->username);
+				purple_account_get_username(account));
 	}
 
 	if (yd->tmp_serv_plist) {
@@ -763,7 +763,7 @@
 			f = yahoo_friend_find(gc, *bud);
 			if (f) {
 				purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n",
-						account->username, *bud);
+						purple_account_get_username(account), *bud);
 				f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
 			}
 		}
@@ -787,7 +787,7 @@
 	YahooFriend *f = NULL;
 	GSList *l = pkt->hash;
 	gint val_11 = 0;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	YahooFederation fed = YAHOO_FEDERATION_NONE;
 
 	account = purple_connection_get_account(gc);
@@ -899,7 +899,7 @@
 	char *server_msg = NULL;
 	char *m;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	account = purple_connection_get_account(gc);
 
 	while (l != NULL) {
@@ -960,7 +960,7 @@
 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
 {
 	PurpleAccount *account;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GSList *l = pkt->hash;
 	GSList *list = NULL;
 	struct _yahoo_im *im = NULL;
@@ -1061,7 +1061,7 @@
 							doodle_session *ds;
 							wb = purple_whiteboard_create(account, im->from,
 											DOODLE_STATE_REQUESTED);
-							ds = wb->proto_data;
+							ds = purple_whiteboard_get_protocol_data(wb);
 							ds->imv_key = g_strdup(pair->value);
 
 							yahoo_doodle_command_send_request(gc, im->from, pair->value);
@@ -1202,7 +1202,7 @@
 {
 	struct yahoo_add_request *add_req = data;
 	struct yahoo_packet *pkt;
-	YahooData *yd = add_req->gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(add_req->gc);
 	const char *who = add_req->who;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -1233,7 +1233,7 @@
 static void
 yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg)
 {
-	YahooData *yd = add_req->gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(add_req->gc);
 	struct yahoo_packet *pkt;
 	char *encoded_msg = NULL;
 	const char *who = add_req->who;
@@ -1295,7 +1295,7 @@
 static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
 {
 	char *notify_msg;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (who == NULL)
 		return;
@@ -1625,7 +1625,7 @@
 static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	const char *who = NULL;
 	const char *email = NULL;
 	const char *subj = NULL;
@@ -1709,7 +1709,7 @@
 
 static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	const char *name = purple_normalize(account, purple_account_get_username(account));
 	PurpleCipher *md5_cipher;
@@ -1803,7 +1803,7 @@
 
 	if (error_message != NULL) {
 		purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
 		g_free(auth_data->seed);
 		g_free(auth_data);
 		return;
@@ -1890,7 +1890,7 @@
 			if(error_reason) {
 				purple_debug_error("yahoo", "Authentication error: %s. "
 				                   "Code %d\n", error_reason, response_no);
-				purple_connection_error_reason(gc, error, error_reason);
+				purple_connection_error(gc, error, error_reason);
 				g_free(error_reason);
 				g_free(auth_data->seed);
 				g_free(auth_data);
@@ -1919,7 +1919,7 @@
 
 	if (error_message != NULL) {
 		purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
 		g_free(auth_data->seed);
 		g_free(auth_data);
 		return;
@@ -2000,7 +2000,7 @@
 			}
 			purple_debug_error("yahoo", "Authentication error: %s. Code %d\n",
 			                   error_reason, response_no);
-			purple_connection_error_reason(gc, error, error_reason);
+			purple_connection_error(gc, error, error_reason);
 			g_free(error_reason);
 			g_free(auth_data->seed);
 			g_free(auth_data);
@@ -2014,7 +2014,7 @@
 			gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
 
 			url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token);
-			url_data = purple_util_fetch_url_request_len_with_account(
+			url_data = purple_util_fetch_url_request(
 					proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT,
 					TRUE, NULL, TRUE, -1, yahoo_auth16_stage2, auth_data);
 			if (url_data)
@@ -2040,7 +2040,7 @@
 	purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n");
 
 	if(!purple_ssl_is_supported()) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable"));
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable"));
 		return;
 	}
 
@@ -2055,7 +2055,7 @@
 	g_free(encoded_password);
 	g_free(encoded_username);
 
-	url_data = purple_util_fetch_url_request_len_with_account(
+	url_data = purple_util_fetch_url_request(
 			proxy_ssl ? account : NULL, url, TRUE,
 			YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1,
 			yahoo_auth16_stage1_cb, auth_data);
@@ -2180,12 +2180,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));
@@ -2207,14 +2207,14 @@
 static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 #ifdef TRY_WEBMESSENGER_LOGIN
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 #endif /* TRY_WEBMESSENGER_LOGIN */
 	GSList *l = pkt->hash;
 	int err = 0;
 	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,10 +2244,12 @@
 			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, yahoo_login_page_cb, gc);
+					"Purple/" VERSION, FALSE, -1, yahoo_login_page_cb, gc);
 			if (url_data != NULL)
 				yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
 			return;
@@ -2285,7 +2287,7 @@
 	else
 		fullmsg = g_strdup(msg);
 
-	purple_connection_error_reason(gc, reason, fullmsg);
+	purple_connection_error(gc, reason, fullmsg);
 	g_free(msg);
 	g_free(fullmsg);
 }
@@ -2300,7 +2302,7 @@
 	char *buf;
 	YahooFriend *f;
 	GSList *l = pkt->hash;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	YahooFederation fed = YAHOO_FEDERATION_NONE;
 
 	while (l) {
@@ -2394,7 +2396,7 @@
 	PurpleConnection *gc = user_data;
 	struct yahoo_packet *pkt_to_send;
 	PurpleAccount *account;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	account = purple_connection_get_account(gc);
 
@@ -2413,7 +2415,7 @@
 static gboolean yahoo_p2p_keepalive(gpointer data)
 {
 	PurpleConnection *gc = data;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc);
 
@@ -2460,7 +2462,7 @@
 	if(!(p2p_data = data))
 		return ;
 
-	yd = p2p_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(p2p_data->gc);
 
 	/* lets see whats in the packet */
 	while (l) {
@@ -2545,7 +2547,7 @@
 
 	if(!(p2p_data = data))
 		return ;
-	yd = p2p_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(p2p_data->gc);
 
 	len = read(source, buf, sizeof(buf));
 	if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
@@ -2617,7 +2619,7 @@
 
 	if(!(p2p_data = data))
 		return ;
-	yd = p2p_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(p2p_data->gc);
 
 	acceptfd = accept(source, NULL, 0);
 	if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
@@ -2657,7 +2659,7 @@
 	if(!(p2p_data = data))
 		return FALSE;
 
-	yd = p2p_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(p2p_data->gc);
 
 	purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect\n");
 	yahoo_p2p_disconnect_destroy_data(data);
@@ -2678,7 +2680,7 @@
 	if(!(p2p_data = data))
 		return ;
 
-	yd = p2p_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(p2p_data->gc);
 	yd->listen_data = NULL;
 
 	if(listenfd == -1) {
@@ -2706,7 +2708,7 @@
 	YahooFriend *f;
 	struct yahoo_packet *pkt;
 	PurpleAccount *account;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_p2p_data *p2p_data;
 	const char *norm_username;
 
@@ -2770,7 +2772,7 @@
 	if (yd->listen_data)
 		purple_debug_warning("yahoo","p2p: Failed to create p2p server - server already exists\n");
 	else {
-		yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data);
+		yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_server_listen_cb, p2p_data);
 		if (yd->listen_data == NULL)
 			purple_debug_warning("yahoo","p2p: Failed to created p2p server\n");
 	}
@@ -2787,7 +2789,7 @@
 	YahooData *yd;
 
 	p2p_data = data;
-	yd = p2p_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(p2p_data->gc);
 
 	if(error_message != NULL) {
 		purple_debug_warning("yahoo","p2p: %s\n",error_message);
@@ -3132,7 +3134,7 @@
 static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = data;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	char buf[1024];
 	int len;
 
@@ -3147,15 +3149,15 @@
 
 		tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	} else if (len == 0) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("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;
@@ -3235,20 +3237,20 @@
 	if (source < 0) {
 		gchar *tmp;
 		tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	}
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	yd->fd = source;
 
 	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
@@ -3261,31 +3263,31 @@
 	if (source < 0) {
 		gchar *tmp;
 		tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	}
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	yd->fd = source;
 
 	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)
 {
 	PurpleConnection *gc = data;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	char bufread[2048], *i = bufread, *buf = bufread;
 	int len;
 	GString *s;
@@ -3301,11 +3303,11 @@
 
 		tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	} else if (len == 0) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 				_("Server closed the connection"));
 		return;
 	}
@@ -3321,7 +3323,7 @@
 
 	if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) &&
 			  strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Received unexpected HTTP response from server"));
 		purple_debug_misc("yahoo", "Unexpected HTTP response: %s\n", buf);
 		return;
@@ -3342,7 +3344,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;
@@ -3351,7 +3354,7 @@
 	if (purple_proxy_connect(gc, account, "wcs2.msg.dcn.yahoo.com",
 	                         purple_account_get_int(account, "port", YAHOO_PAGER_PORT),
 	                         yahoo_got_web_connected, gc) == NULL) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                               _("Unable to connect"));
 		return;
 	}
@@ -3359,13 +3362,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 = gc->proto_data;
-
 	remaining = strlen(yd->auth) - yd->auth_written;
 	written = write(source, yd->auth + yd->auth_written, remaining);
 
@@ -3375,12 +3375,13 @@
 		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_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		return;
 	}
@@ -3393,26 +3394,27 @@
 	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;
 		tmp = g_strdup_printf(_("Unable to establish a connection with %s: %s"),
 				"login.yahoo.com:80", error_message);
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 		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);
 	}
@@ -3474,7 +3476,7 @@
 {
 	PurpleConnection *gc = (PurpleConnection *)user_data;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	const char *sn = purple_account_get_username(account);
 	const char *pass = purple_connection_get_password(gc);
 	GHashTable *hash = yahoo_login_page_hash(url_text, len);
@@ -3489,7 +3491,7 @@
 
 	if (error_message != NULL)
 	{
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                               error_message);
 		return;
 	}
@@ -3539,7 +3541,7 @@
 	g_hash_table_destroy(hash);
 	yd->auth = g_string_free(url, FALSE);
 	if (purple_proxy_connect(gc, account, "login.yahoo.com", 80, yahoo_got_cookies, gc) == NULL) {
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                               _("Unable to connect"));
 		return;
 	}
@@ -3619,12 +3621,12 @@
 				error_message ? error_message : "(null)");
 
 		if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					_("Unable to connect: The server returned an empty response."));
 		} else {
 				if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
 							yahoo_got_connected, gc) == NULL) {
-					purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+					purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 							_("Unable to connect"));
 				}
 		}
@@ -3646,20 +3648,20 @@
 
 		if(cs_server) { /* got an address; get on with connecting */
 			if(purple_proxy_connect(gc, a, cs_server, port, yahoo_got_connected, gc) == NULL)
-				purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 								_("Unable to connect"));
 		} else {
 			purple_debug_error("yahoo", "No CS address retrieved!  Server "
 					"response:\n%s\n", url_text ? url_text : "(null)");
 
 			if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
-				purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 						_("Unable to connect: The server's response did not contain "
 							"the necessary information"));
 			} else
 				if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
 							yahoo_got_connected, gc) == NULL) {
-					purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+					purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 							_("Unable to connect"));
 				}
 		}
@@ -3671,13 +3673,14 @@
 
 void yahoo_login(PurpleAccount *account) {
 	PurpleConnection *gc = purple_account_get_connection(account);
-	YahooData *yd = gc->proto_data = g_new0(YahooData, 1);
+	YahooData *yd = g_new0(YahooData, 1);
 	PurpleStatus *status = purple_account_get_active_status(account);
 	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
 	gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
 	PurpleUtilFetchUrlData *url_data;
 
-	gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC;
+	purple_connection_set_protocol_data(gc, yd);
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC);
 
 	purple_connection_update_progress(gc, _("Connecting"), 1, 2);
 
@@ -3708,7 +3711,7 @@
 
 	/* Get the pager server.  Actually start connecting in the callback since we
 	 * must have the contents of the HTTP response to proceed. */
-	url_data = purple_util_fetch_url_request_len_with_account(
+	url_data = purple_util_fetch_url_request(
 			proxy_ssl ? purple_connection_get_account(gc) : NULL,
 			yd->jp ? YAHOOJP_PAGER_HOST_REQ_URL : YAHOO_PAGER_HOST_REQ_URL,
 			use_whole_url ? TRUE : FALSE,
@@ -3721,11 +3724,13 @@
 }
 
 void yahoo_close(PurpleConnection *gc) {
-	YahooData *yd = (YahooData *)gc->proto_data;
+	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);
@@ -3810,7 +3815,7 @@
 	g_free(yd->current_list15_grp);
 
 	g_free(yd);
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 }
 
 const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b)
@@ -3827,7 +3832,7 @@
 
 	if (!b || !(account = purple_buddy_get_account(b)) ||
 			!(gc = purple_account_get_connection(account)) ||
-			!gc->proto_data)
+			!purple_connection_get_protocol_data(gc))
 		return NULL;
 
 	f = yahoo_friend_find(gc, purple_buddy_get_name(b));
@@ -3892,7 +3897,7 @@
 
 	buddy = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	id = yd->conf_id;
 
 	components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
@@ -4036,22 +4041,12 @@
 
 	if (f && full) {
 		YahooPersonalDetails *ypd = &f->ypd;
-		int i;
-		struct {
-			char *id;
-			char *text;
-			char *value;
-		} yfields[] = {
-			{"hp", N_("Home Phone Number"), ypd->phone.home},
-			{"wp", N_("Work Phone Number"), ypd->phone.work},
-			{"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
-			{NULL, NULL, NULL}
-		};
-		for (i = 0; yfields[i].id; i++) {
-			if (!yfields[i].value || !*yfields[i].value)
-				continue;
-			purple_notify_user_info_add_pair(user_info, _(yfields[i].text), yfields[i].value);
-		}
+		if (ypd->phone.home && *ypd->phone.home)
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), ypd->phone.home);
+		if (ypd->phone.work && *ypd->phone.work)
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), ypd->phone.work);
+		if (ypd->phone.mobile && *ypd->phone.mobile)
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), ypd->phone.mobile);
 	}
 }
 
@@ -4065,7 +4060,7 @@
 	buddy = (PurpleBuddy *) node;
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
-	yahoo_add_buddy(gc, buddy, NULL);
+	yahoo_add_buddy(gc, buddy, NULL, NULL);
 }
 
 
@@ -4085,7 +4080,7 @@
 static GList *build_presence_submenu(YahooFriend *f, PurpleConnection *gc) {
 	GList *m = NULL;
 	PurpleMenuAction *act;
-	YahooData *yd = (YahooData *) gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
 		if (f->presence != YAHOO_PRESENCE_ONLINE) {
@@ -4145,7 +4140,7 @@
 	PurpleMenuAction *act;
 
 	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	static char buf2[1024];
 	YahooFriend *f;
 
@@ -4228,7 +4223,7 @@
 
 static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	const char *name = yd->profiles[purple_request_fields_get_choice(fields, "id")];
 
 	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -4245,7 +4240,7 @@
 	PurpleConnection *gc = user_data;
 	gboolean set_cookie = FALSE;
 	gchar *url;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
@@ -4281,7 +4276,7 @@
 	/* XXX I have no idea how this will work with Yahoo! Japan. */
 
 	PurpleConnection *gc = action->context;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	PurpleUtilFetchUrlData *url_data;
 	const char* base_url = "http://login.yahoo.com";
@@ -4296,7 +4291,7 @@
 		use_whole_url ? base_url : "",
 		yd->cookie_t, yd->cookie_y);
 
-	url_data = purple_util_fetch_url_request_len_with_account(
+	url_data = purple_util_fetch_url_request(
 			purple_connection_get_account(gc), base_url, use_whole_url,
 			YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
 			yahoo_get_inbox_token_cb, gc);
@@ -4395,7 +4390,7 @@
 {
 	struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data;
 	PurpleConnection *gc = sms_cb_data->gc;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	char *status = NULL;
 	char *carrier = NULL;
 	PurpleAccount *account = purple_connection_get_account(gc);
@@ -4450,7 +4445,7 @@
 
 static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleUtilFetchUrlData *url_data;
 	struct yahoo_sms_carrier_cb_data *sms_cb_data;
 	char *validate_request_str = NULL;
@@ -4485,10 +4480,10 @@
 		YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str);
 
 	/* use whole URL if using HTTP Proxy */
-	if ((gc->account->proxy_info) && (gc->account->proxy_info->type == 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_len_with_account(
+	url_data = purple_util_fetch_url_request(
 			purple_connection_get_account(gc), YAHOO_SMS_CARRIER_URL, use_whole_url,
 			YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
 			yahoo_get_sms_carrier_cb, data);
@@ -4510,7 +4505,7 @@
 
 int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt = NULL;
 	char *msg = yahoo_html_to_codes(what);
 	char *msg2;
@@ -4621,7 +4616,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
@@ -4667,7 +4662,7 @@
 
 unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_p2p_data *p2p_data;
 	YahooFederation fed = YAHOO_FEDERATION_NONE;
 	struct yahoo_packet *pkt = NULL;
@@ -4738,7 +4733,7 @@
 
 	gc = purple_account_get_connection(account);
 	presence = purple_status_get_presence(status);
-	yd = (YahooData *)gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	old_status = yd->current_status;
 
 	yd->current_status = get_yahoo_status_from_purple_status(status);
@@ -4804,7 +4799,7 @@
 
 void yahoo_set_idle(PurpleConnection *gc, int idle)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt = NULL;
 	char *msg = NULL, *msg2 = NULL;
 	PurpleStatus *status = NULL;
@@ -4923,7 +4918,7 @@
 void yahoo_keepalive(PurpleConnection *gc)
 {
 	struct yahoo_packet *pkt;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	time_t now = time(NULL);
 
 	/* We're only allowed to send a ping once an hour or the servers will boot us */
@@ -4954,9 +4949,9 @@
 
 }
 
-void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
+void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g, const char *message)
 {
-	YahooData *yd = (YahooData *)gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	const char *group = NULL;
 	char *group2;
@@ -5019,7 +5014,7 @@
 
 void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	YahooData *yd = (YahooData *)gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	GSList *buddies, *l;
 	PurpleGroup *g;
@@ -5075,7 +5070,7 @@
 }
 
 void yahoo_add_deny(PurpleConnection *gc, const char *who) {
-	YahooData *yd = (YahooData *)gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	YahooFederation fed = YAHOO_FEDERATION_NONE;
 
@@ -5098,7 +5093,7 @@
 }
 
 void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
-	YahooData *yd = (YahooData *)gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	YahooFederation fed = YAHOO_FEDERATION_NONE;
 
@@ -5126,7 +5121,7 @@
 
 	account = purple_connection_get_account(gc);
 
-	switch (account->perm_deny)
+	switch (purple_account_get_privacy_type(account))
 	{
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			for (deny = account->deny; deny; deny = deny->next)
@@ -5146,7 +5141,7 @@
 void yahoo_change_buddys_group(PurpleConnection *gc, const char *who,
 				   const char *old_group, const char *new_group)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	char *gpn, *gpo;
 	YahooFriend *f = yahoo_friend_find(gc, who);
@@ -5193,7 +5188,7 @@
 void yahoo_rename_group(PurpleConnection *gc, const char *old_name,
 							   PurpleGroup *group, GList *moved_buddies)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	char *gpn, *gpo;
 
@@ -5222,7 +5217,7 @@
 	if (*args && args[0])
 		return PURPLE_CMD_RET_FAILED;
 
-	purple_prpl_send_attention(account->gc, c->name, YAHOO_BUZZ);
+	purple_prpl_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), YAHOO_BUZZ);
 
 	return PURPLE_CMD_RET_OK;
 }
@@ -5237,7 +5232,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);
@@ -5271,12 +5266,12 @@
 	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);
 
 	purple_debug_info("yahoo", "Sending <ding> on account %s to buddy %s.\n",
-			username, c->name);
+			username, purple_conversation_get_name(c));
 	purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "<ding>", PURPLE_MESSAGE_INVISIBLE);
 
 	return TRUE;
--- a/libpurple/protocols/yahoo/libymsg.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/libymsg.h	Mon Oct 31 01:25:36 2011 +0000
@@ -188,6 +188,7 @@
 typedef struct {
 	PurpleConnection *gc;
 	int fd;
+	guint inpa;
 	guchar *rxqueue;
 	int rxlen;
 	PurpleCircBuffer *txbuf;
@@ -371,7 +372,7 @@
 unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state);
 void yahoo_set_status(PurpleAccount *account, PurpleStatus *status);
 void yahoo_set_idle(PurpleConnection *gc, int idle);
-void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g);
+void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g, const char *message);
 void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
 void yahoo_add_deny(PurpleConnection *gc, const char *who);
 void yahoo_rem_deny(PurpleConnection *gc, const char *who);
--- a/libpurple/protocols/yahoo/util.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/util.c	Mon Oct 31 01:25:36 2011 +0000
@@ -63,8 +63,9 @@
 	char firstflag = 1;
 	gchar *t1,*t2,*t3;
 	GSList *tmp;
-	GSList *cookies;
-	cookies = ((YahooData*)(gc->proto_data))->cookies;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
+	GSList *cookies = yd->cookies;
+
 	tmp = cookies;
 	while(tmp)
 	{
@@ -129,7 +130,7 @@
  */
 char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	char *ret;
 	const char *to_codeset;
 
@@ -158,7 +159,7 @@
  */
 char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	char *ret;
 	const char *from_codeset;
 
--- a/libpurple/protocols/yahoo/yahoo_aliases.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_aliases.c	Mon Oct 31 01:25:36 2011 +0000
@@ -74,7 +74,7 @@
 yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
 {
 	PurpleConnection *gc = user_data;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
@@ -186,7 +186,7 @@
 void
 yahoo_fetch_aliases(PurpleConnection *gc)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	const char *url;
 	gchar *request, *webpage, *webaddress;
 	PurpleUtilFetchUrlData *url_data;
@@ -207,7 +207,7 @@
 				  webaddress);
 
 	/* We have a URL and some header information, let's connect and get some aliases  */
-	url_data = purple_util_fetch_url_request_len_with_account(purple_connection_get_account(gc),
+	url_data = purple_util_fetch_url_request(purple_connection_get_account(gc),
 				url, use_whole_url, NULL, TRUE, request, FALSE, -1,
 				yahoo_fetch_aliases_cb, gc);
 	if (url_data != NULL)
@@ -230,7 +230,7 @@
 	PurpleConnection *gc = cb->gc;
 	YahooData *yd;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
 	if (len == 0 || error_message != NULL) {
@@ -310,7 +310,7 @@
 		return;
 	}
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	/* Using callback_data so I have access to gc in the callback function */
 	cb = g_new0(struct callback_data, 1);
@@ -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);
 		}
@@ -379,7 +379,7 @@
 				  content);
 
 	/* We have a URL and some header information, let's connect and update the alias  */
-	url_data = purple_util_fetch_url_request_len_with_account(
+	url_data = purple_util_fetch_url_request(
 			purple_connection_get_account(gc), url, use_whole_url, NULL, TRUE,
 			request, FALSE, -1, yahoo_update_alias_cb, cb);
 	if (url_data != NULL)
@@ -517,7 +517,7 @@
 	}
 #endif
 
-	url_data = purple_util_fetch_url_request_len_with_account(account, webaddress, FALSE,
+	url_data = purple_util_fetch_url_request(account, webaddress, FALSE,
 			YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
 			yahoo_fetch_aliases_cb, gc);
 	if (url_data != NULL)
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_doodle.c	Mon Oct 31 01:25:36 2011 +0000
@@ -161,7 +161,7 @@
 		*/
 
 		wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED);
-		ds = wb->proto_data;
+		ds = purple_whiteboard_get_protocol_data(wb);
 		ds->imv_key = g_strdup(imv_key);
 
 		yahoo_doodle_command_send_ready(gc, from, imv_key);
@@ -189,19 +189,19 @@
 	if(wb == NULL)
 		return;
 
-	if(wb->state == DOODLE_STATE_REQUESTING)
+	if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTING)
 	{
-		doodle_session *ds = wb->proto_data;
+		doodle_session *ds = purple_whiteboard_get_protocol_data(wb);
 		purple_whiteboard_start(wb);
 
-		wb->state = DOODLE_STATE_ESTABLISHED;
+		purple_whiteboard_set_state(wb, DOODLE_STATE_ESTABLISHED);
 
 		yahoo_doodle_command_send_confirm(gc, from, imv_key);
 		/* Let's steal the imv_key and reuse it */
 		g_free(ds->imv_key);
 		ds->imv_key = g_strdup(imv_key);
 	}
-	else if(wb->state == DOODLE_STATE_ESTABLISHED)
+	else if(purple_whiteboard_get_state(wb) == DOODLE_STATE_ESTABLISHED)
 	{
 		/* TODO Ask whether to save picture too */
 		purple_whiteboard_clear(wb);
@@ -211,7 +211,7 @@
 	 * already thinks we're in a session with them (when their chat message
 	 * contains the doodle imv key)
 	 */
-	else if(wb->state == DOODLE_STATE_REQUESTED)
+	else if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTED)
 	{
 		/* purple_whiteboard_start(wb); */
 		yahoo_doodle_command_send_ready(gc, from, imv_key);
@@ -292,7 +292,7 @@
 	if(wb == NULL)
 		return;
 
-	if(wb->state == DOODLE_STATE_ESTABLISHED)
+	if(purple_whiteboard_get_state(wb) == DOODLE_STATE_ESTABLISHED)
 	{
 		/* TODO Ask user whether to save the image before clearing it */
 
@@ -333,9 +333,9 @@
 	/* TODO Combine the following IF's? */
 
 	/* Check if we requested a doodle session */
-	/*if(wb->state == DOODLE_STATE_REQUESTING)
+	/*if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTING)
 	{
-		wb->state = DOODLE_STATE_ESTABLISHED;
+		purple_whiteboard_set_state(wb, DOODLE_STATE_ESTABLISHED);
 
 		purple_whiteboard_start(wb);
 
@@ -343,9 +343,9 @@
 	}*/
 
 	/* Check if we accepted a request for a doodle session */
-	if(wb->state == DOODLE_STATE_REQUESTED)
+	if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTED)
 	{
-		wb->state = DOODLE_STATE_ESTABLISHED;
+		purple_whiteboard_set_state(wb, DOODLE_STATE_ESTABLISHED);
 
 		purple_whiteboard_start(wb);
 	}
@@ -372,7 +372,7 @@
 
 	/* TODO Ask if user wants to save picture before the session is closed */
 
-	wb->state = DOODLE_STATE_CANCELLED;
+	purple_whiteboard_set_state(wb, DOODLE_STATE_CANCELLED);
 	purple_whiteboard_destroy(wb);
 }
 
@@ -389,12 +389,12 @@
 
 	purple_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to);
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	/* 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);
@@ -450,21 +450,23 @@
 	ds->brush_size  = DOODLE_BRUSH_SMALL;
 	ds->brush_color = DOODLE_COLOR_RED;
 
-	wb->proto_data = ds;
+	purple_whiteboard_set_protocol_data(wb, ds);
 }
 
 void yahoo_doodle_end(PurpleWhiteboard *wb)
 {
-	PurpleConnection *gc = purple_account_get_connection(wb->account);
-	doodle_session *ds = wb->proto_data;
+	PurpleAccount *account = purple_whiteboard_get_account(wb);
+	PurpleConnection *gc = purple_account_get_connection(account);
+	doodle_session *ds = purple_whiteboard_get_protocol_data(wb);
 
 	/* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
 
-	if (gc && wb->state != DOODLE_STATE_CANCELLED)
-		yahoo_doodle_command_send_shutdown(gc, wb->who);
+	if (gc && (purple_whiteboard_get_state(wb) != DOODLE_STATE_CANCELLED))
+		yahoo_doodle_command_send_shutdown(gc, purple_whiteboard_get_who(wb));
 
 	g_free(ds->imv_key);
-	g_free(wb->proto_data);
+	g_free(ds);
+	purple_whiteboard_set_protocol_data(wb, NULL);
 }
 
 void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
@@ -494,20 +496,25 @@
 
 void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list)
 {
-	doodle_session *ds = wb->proto_data;
+	PurpleAccount *account = purple_whiteboard_get_account(wb);
+	PurpleConnection *gc = purple_account_get_connection(account);
+	doodle_session *ds = purple_whiteboard_get_protocol_data(wb);
 	char *message;
 
 	g_return_if_fail(draw_list != NULL);
 
 	message = yahoo_doodle_build_draw_string(ds, draw_list);
-	yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message, ds->imv_key);
+	yahoo_doodle_command_send_draw(gc, purple_whiteboard_get_who(wb), message, ds->imv_key);
 	g_free(message);
 }
 
 void yahoo_doodle_clear(PurpleWhiteboard *wb)
 {
-	doodle_session *ds = wb->proto_data;
-	yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key);
+	PurpleAccount *account = purple_whiteboard_get_account(wb);
+	PurpleConnection *gc = purple_account_get_connection(account);
+	doodle_session *ds = purple_whiteboard_get_protocol_data(wb);
+
+	yahoo_doodle_command_send_clear(gc, purple_whiteboard_get_who(wb), ds->imv_key);
 }
 
 
@@ -560,14 +567,14 @@
 
 void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
 {
-	doodle_session *ds = wb->proto_data;
+	doodle_session *ds = purple_whiteboard_get_protocol_data(wb);
 	*size = ds->brush_size;
 	*color = ds->brush_color;
 }
 
 void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color)
 {
-	doodle_session *ds = wb->proto_data;
+	doodle_session *ds = purple_whiteboard_get_protocol_data(wb);
 	ds->brush_size = size;
 	ds->brush_color = color;
 
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Mon Oct 31 01:25:36 2011 +0000
@@ -43,7 +43,7 @@
 	PurpleConnection *gc;
 	long expires;
 	gboolean started;
-	gchar *txbuf;
+	guchar *txbuf;
 	gsize txbuflen;
 	gsize txbuf_written;
 	guint tx_handler;
@@ -85,7 +85,7 @@
 	GSList *l;
 
 	gc = xd->gc;
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	/* remove entry from map */
 	if(xd->xfer_peer_idstring) {
@@ -120,13 +120,13 @@
 {
 	PurpleXfer *xfer;
 	struct yahoo_xfer_data *xd;
-	int remaining, written;
+	gssize remaining, written;
 
 	xfer = data;
-	xd = xfer->data;
+	xd = purple_xfer_get_protocol_data(xfer);
 
 	remaining = xd->txbuflen - xd->txbuf_written;
-	written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
+	written = purple_xfer_write(xfer, xd->txbuf + xd->txbuf_written, remaining);
 
 	if (written < 0 && errno == EAGAIN)
 		written = 0;
@@ -160,22 +160,23 @@
 
 	if (!(xfer = data))
 		return;
-	if (!(xd = xfer->data))
+	if (!(xd = purple_xfer_get_protocol_data(xfer)))
 		return;
 	if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
 		purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-				xfer->who, _("Unable to connect."));
+				purple_xfer_get_remote_user(xfer), _("Unable to connect."));
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
 
-	xfer->fd = source;
+	purple_xfer_set_fd(xfer, source);
 
 	/* The first time we get here, assemble the tx buffer */
 	if (xd->txbuflen == 0) {
-		xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
+		gchar *header = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
 			      xd->path, xd->host);
-		xd->txbuflen = strlen(xd->txbuf);
+		xd->txbuf = (guchar*) header;
+		xd->txbuflen = strlen(header);
 		xd->txbuf_written = 0;
 	}
 
@@ -191,13 +192,13 @@
 {
 	PurpleXfer *xfer;
 	struct yahoo_xfer_data *xd;
-	int written, remaining;
+	gssize written, remaining;
 
 	xfer = data;
-	xd = xfer->data;
+	xd = purple_xfer_get_protocol_data(xfer);
 
 	remaining = xd->txbuflen - xd->txbuf_written;
-	written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
+	written = purple_xfer_write(xfer, xd->txbuf + xd->txbuf_written, remaining);
 
 	if (written < 0 && errno == EAGAIN)
 		written = 0;
@@ -239,32 +240,32 @@
 
 	if (!(xfer = data))
 		return;
-	if (!(xd = xfer->data))
+	if (!(xd = purple_xfer_get_protocol_data(xfer)))
 		return;
 
 	if (source < 0) {
 		purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-				xfer->who, _("Unable to connect."));
+				purple_xfer_get_remote_user(xfer), _("Unable to connect."));
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
 
-	xfer->fd = source;
+	purple_xfer_set_fd(xfer, source);
 
 	/* Assemble the tx buffer */
 	gc = xd->gc;
 	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	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);
 
 	yahoo_packet_hash(pkt, "sssss", 0, purple_connection_get_display_name(gc),
-	  5, xfer->who, 14, "", 27, encoded_filename, 28, size);
+	  5, purple_xfer_get_remote_user(xfer), 14, "", 27, encoded_filename, 28, size);
 	g_free(size);
 	g_free(encoded_filename);
 	g_free(filename);
@@ -278,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",
@@ -313,9 +314,9 @@
 	PurpleAccount *account;
 	YahooData *yd;
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 	gc = xfer_data->gc;
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	account = purple_connection_get_account(gc);
 
 	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
@@ -339,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"),
@@ -357,9 +358,9 @@
 	YahooData *yd;
 	struct yahoo_packet *pkt;
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 	gc = xfer_data->gc;
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	account = purple_connection_get_account(gc);
 
 	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)	{
@@ -370,14 +371,14 @@
 							   yd->session_id);
 		yahoo_packet_hash(pkt, "sssiiiisiii",
 			1, purple_normalize(account, purple_account_get_username(account)),
-			5, xfer->who,
+			5, purple_xfer_get_remote_user(xfer),
 			265, xfer_data->xfer_peer_idstring,
 			222, 1,
 			266, 1,
 			302, 268,
 			300, 268,
 			27,  filename,
-			28,  xfer->size,
+			28,  (int)purple_xfer_get_size(xfer),
 			301, 268,
 			303, 268);
 		g_free(filename);
@@ -388,7 +389,7 @@
 
 			yahoo_packet_hash(pkt, "sssi",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xfer_data->xfer_peer_idstring,
 				222, 3);
 		} else {
@@ -397,7 +398,7 @@
 
 			yahoo_packet_hash(pkt, "sssi",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xfer_data->xfer_peer_idstring,
 				271, 1);
 		}
@@ -410,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;
 }
@@ -429,14 +430,14 @@
 	gchar *start = NULL;
 	gchar *length;
 	gchar *end;
-	int filelen;
-	struct yahoo_xfer_data *xd = xfer->data;
+	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) &&
@@ -490,7 +491,7 @@
 static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer)
 {
 	gssize len;
-	struct yahoo_xfer_data *xd = xfer->data;
+	struct yahoo_xfer_data *xd = purple_xfer_get_protocol_data(xfer);
 
 	if (!xd)
 		return -1;
@@ -499,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))
@@ -516,7 +517,7 @@
 {
 	struct yahoo_xfer_data *xfer_data;
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 
 	if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
 	{
@@ -526,7 +527,7 @@
 		struct yahoo_packet *pkt;
 
 		gc = xfer_data->gc;
-		yd = gc->proto_data;
+		yd = purple_connection_get_protocol_data(gc);
 		account = purple_connection_get_account(gc);
 		if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
 		{
@@ -535,7 +536,7 @@
 								   yd->session_id);
 			yahoo_packet_hash(pkt, "sssi",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xfer_data->xfer_peer_idstring,
 				66, -1);
 		}
@@ -546,7 +547,7 @@
 								   yd->session_id);
 			yahoo_packet_hash(pkt, "sssi",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xfer_data->xfer_peer_idstring,
 				222, 2);
 		}
@@ -556,14 +557,14 @@
 
 	if (xfer_data)
 		yahoo_xfer_data_free(xfer_data);
-	xfer->data = NULL;
+	purple_xfer_set_protocol_data(xfer, NULL);
 }
 
 static void yahoo_xfer_cancel_recv(PurpleXfer *xfer)
 {
 	struct yahoo_xfer_data *xfer_data;
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 
 	if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
 	{
@@ -574,7 +575,7 @@
 		struct yahoo_packet *pkt;
 
 		gc = xfer_data->gc;
-		yd = gc->proto_data;
+		yd = purple_connection_get_protocol_data(gc);
 		account = purple_connection_get_account(gc);
 		if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
 		{
@@ -583,7 +584,7 @@
 								   yd->session_id);
 			yahoo_packet_hash(pkt, "sssi",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xfer_data->xfer_peer_idstring,
 				222, 4);
 		}
@@ -594,7 +595,7 @@
 								   yd->session_id);
 			yahoo_packet_hash(pkt, "sssi",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xfer_data->xfer_peer_idstring,
 				66, -1);
 		}
@@ -603,7 +604,7 @@
 
 	if (xfer_data)
 		yahoo_xfer_data_free(xfer_data);
-	xfer->data = NULL;
+	purple_xfer_set_protocol_data(xfer, NULL);
 }
 
 /* Send HTTP OK after receiving file */
@@ -611,9 +612,10 @@
 {
 	char *tx = NULL;
 	int written;
+	int fd = purple_xfer_get_fd(xfer);
 
-	tx = g_strdup_printf("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));
+	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(fd, tx, strlen(tx));
 
 	if (written < 0 && errno == EAGAIN)
 		written = 0;
@@ -621,9 +623,8 @@
 		purple_debug_info("yahoo", "p2p filetransfer: Unable to write HTTP OK");
 
 	/* close connection */
-	close(xfer->fd);
-	xfer->fd = -1;
-	g_free(tx);
+	close(fd);
+	purple_xfer_set_fd(xfer, -1);
 }
 
 static void yahoo_xfer_end(PurpleXfer *xfer_old)
@@ -633,13 +634,13 @@
 	PurpleConnection *gc;
 	YahooData *yd;
 
-	xfer_data = xfer_old->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer_old);
 	if(xfer_data && xfer_data->version == 15
 	   && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE
 	   && 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,13 +657,13 @@
 		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 = gc->proto_data;
+			yd = purple_connection_get_protocol_data(gc);
 
 			/* setting up xfer_data for next file's tranfer */
 			g_free(xfer_data->host);
@@ -689,10 +690,10 @@
 			xfer_data->firstoflist = FALSE;
 
 			/* Dereference xfer_data from old xfer */
-			xfer_old->data = NULL;
+			purple_xfer_set_protocol_data(xfer_old, NULL);
 
 			/* Build the file transfer handle. */
-			xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who);
+			xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, purple_xfer_get_remote_user(xfer_old));
 
 
 			if (xfer) {
@@ -702,7 +703,7 @@
 				g_free(utf8_filename);
 				purple_xfer_set_size(xfer, filesize);
 
-				xfer->data = xfer_data;
+				purple_xfer_set_protocol_data(xfer, xfer_data);
 
 				/* Setup our I/O op functions */
 				purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init_15);
@@ -726,8 +727,7 @@
 	}
 	if (xfer_data)
 		yahoo_xfer_data_free(xfer_data);
-	xfer_old->data = NULL;
-
+	purple_xfer_set_protocol_data(xfer_old, NULL);
 }
 
 void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
@@ -803,10 +803,10 @@
 	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 = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
@@ -831,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;
@@ -880,13 +880,13 @@
 	                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();
 	}
 
-	xfer->data = xfer_data;
+	purple_xfer_set_protocol_data(xfer, xfer_data);
 
 	/* Set the info about the incoming file. */
 	if (filename) {
@@ -936,14 +936,14 @@
 	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);
 		g_return_val_if_reached(NULL);
 	}
 
-	xfer->data = xfer_data;
+	purple_xfer_set_protocol_data(xfer, xfer_data);
 
 	/* Setup our I/O op functions */
 	purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init);
@@ -993,11 +993,11 @@
 
 	if (!(xfer = data))
 		return;
-	if (!(xd = xfer->data))
+	if (!(xd = purple_xfer_get_protocol_data(xfer)))
 		return;
 	gc = xd->gc;
 	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	if(!hosts)
 	{
@@ -1057,7 +1057,7 @@
 
 	yahoo_packet_hash(pkt, "ssssis",
 		1, purple_normalize(account, purple_account_get_username(account)),
-		5, xfer->who,
+		5, purple_xfer_get_remote_user(xfer),
 		265, xd->xfer_peer_idstring,
 		27,  filename,
 		249, 3,
@@ -1077,7 +1077,7 @@
 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
 {
 	struct yahoo_xfer_data *xfer_data;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleXfer *xfer = yahoo_new_xfer(gc, who);
 
 	g_return_if_fail(xfer != NULL);
@@ -1086,7 +1086,7 @@
 	if( !g_hash_table_lookup(yd->peers, who) )
 		yahoo_send_p2p_pkt(gc, who, 0);
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 	xfer_data->status_15 = STARTED;
 	purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
 	xfer_data->version = 15;
@@ -1108,26 +1108,22 @@
 	PurpleXfer *xfer;
 	struct yahoo_xfer_data *xd;
 	int did;
-	gchar* buf;
-	gchar* t;
+	guchar buf[1000];
 	PurpleAccount *account;
 	PurpleConnection *gc;
 
 	xfer = data;
-	xd = xfer->data;
+	xd = purple_xfer_get_protocol_data(xfer);
 	account = purple_connection_get_account(xd->gc);
 	gc = xd->gc;
 
-	buf=g_strnfill(1000, 0);
-	while((did = read(source, buf, 998)) > 0)
+	while((did = read(source, buf, sizeof(buf))) > 0)
 	{
+		/* TODO: Convert to circ buffer, this all is pretty horrible */
+		xd->txbuf = g_realloc(xd->txbuf, xd->txbuflen + did);
+		g_memmove(xd->txbuf + xd->txbuflen, buf, did);
 		xd->txbuflen += did;
-		buf[did] = '\0';
-		t = xd->txbuf;
-		xd->txbuf = g_strconcat(t,buf,NULL);
-		g_free(t);
 	}
-	g_free(buf);
 
 	if (did < 0 && errno == EAGAIN)
 		return;
@@ -1167,7 +1163,7 @@
 	int remaining, written;
 
 	xfer = data;
-	xd = xfer->data;
+	xd = purple_xfer_get_protocol_data(xfer);
 	remaining = xd->txbuflen - xd->txbuf_written;
 	written = write(source, xd->txbuf + xd->txbuf_written, remaining);
 
@@ -1200,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;
@@ -1219,9 +1215,9 @@
 		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, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer);
+		purple_network_listen(xd->yahoo_local_p2p_ft_server_port, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer);
 	}
 	else
 	{
@@ -1239,13 +1235,13 @@
 
 	if (!(xfer = data))
 		return;
-	if (!(xd = xfer->data))
+	if (!(xd = purple_xfer_get_protocol_data(xfer)))
 		return;
 	gc = xd->gc;
 	account = purple_connection_get_account(gc);
 	if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
 		purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-			xfer->who, _("Unable to connect."));
+			purple_xfer_get_remote_user(xfer), _("Unable to connect."));
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
@@ -1253,7 +1249,8 @@
 	if (xd->txbuflen == 0)
 	{
 		gchar* cookies;
-		YahooData *yd = gc->proto_data;
+		gchar* initial_buffer;
+		YahooData *yd = purple_connection_get_protocol_data(gc);
 
 		/* cookies = yahoo_get_cookies(gc);
 		 * This doesn't seem to be working. The function is returning NULL, which yahoo servers don't like
@@ -1266,30 +1263,30 @@
 			if(xd->info_val_249 == 2)
 				{
 				/* sending file via p2p, we are connected as client */
-				xd->txbuf = g_strdup_printf("POST /%s HTTP/1.1\r\n"
+				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: %ld\r\n"
+						"Content-Length: %" G_GOFFSET_FORMAT "\r\n"
 						"Cache-Control: no-cache\r\n\r\n",
 										xd->path,
 										xd->host,
-										(long int)xfer->size);	/* to do, add Referer */
+										purple_xfer_get_size(xfer));	/* to do, add Referer */
 				}
 			else
 				{
 				/* sending file via relaying */
-				xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
+				initial_buffer = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
 						"Cookie:%s\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
 						"Host: %s\r\n"
-						"Content-Length: %ld\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)),
-										xfer->who,
+										purple_xfer_get_remote_user(xfer),
 										cookies,
 										xd->host,
-										(long int)xfer->size);
+										purple_xfer_get_size(xfer));	/* to do, add Referer */
 				}
 		}
 		else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
@@ -1297,7 +1294,7 @@
 			if(xd->info_val_249 == 1)
 				{
 				/* receiving file via p2p, connected as client */
-				xd->txbuf = g_strdup_printf("HEAD /%s HTTP/1.1\r\n"
+				initial_buffer = g_strdup_printf("HEAD /%s HTTP/1.1\r\n"
 						"Accept: */*\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
 						"Host: %s\r\n"
@@ -1308,7 +1305,7 @@
 			else
 				{
 				/* receiving file via relaying */
-				xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
+				initial_buffer = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
 						"Accept: */*\r\n"
 						"Cookie: %s\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
@@ -1317,7 +1314,7 @@
 						"Cache-Control: no-cache\r\n\r\n",
 										purple_url_encode(xd->xfer_idstring_for_relay),
 										purple_normalize(account, purple_account_get_username(account)),
-										xfer->who,
+										purple_xfer_get_remote_user(xfer),
 										cookies,
 										xd->host);
 			}
@@ -1327,7 +1324,7 @@
 			if(xd->info_val_249 == 1)
 				{
 				/* receiving file via p2p, connected as client */
-				xd->txbuf = g_strdup_printf("GET /%s HTTP/1.1\r\n"
+				initial_buffer = g_strdup_printf("GET /%s HTTP/1.1\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
 						"Host: %s\r\n"
 						"Connection: Keep-Alive\r\n\r\n",
@@ -1336,14 +1333,14 @@
 			else
 				{
 				/* receiving file via relaying */
-				xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
+				initial_buffer = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
 						"Cookie: %s\r\n"
 						"User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
 						"Host: %s\r\n"
 						"Connection: Keep-Alive\r\n\r\n",
 										purple_url_encode(xd->xfer_idstring_for_relay),
 										purple_normalize(account, purple_account_get_username(account)),
-										xfer->who,
+										purple_xfer_get_remote_user(xfer),
 										cookies,
 										xd->host);
 			}
@@ -1354,7 +1351,8 @@
 			g_free(cookies);
 			return;
 		}
-		xd->txbuflen = strlen(xd->txbuf);
+		xd->txbuf = (guchar*) initial_buffer;
+		xd->txbuflen = strlen(initial_buffer);
 		xd->txbuf_written = 0;
 		g_free(cookies);
 	}
@@ -1373,14 +1371,14 @@
 	struct yahoo_xfer_data *xd;
 
 	xfer = data;
-	if (!(xd = xfer->data))	{
+	if (!(xd = purple_xfer_get_protocol_data(xfer))) {
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
 
 	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);
 }
 
@@ -1396,7 +1394,7 @@
 	char *time_str;
 
 	xfer = data;
-	if (!(xd = xfer->data))	{
+	if (!(xd = purple_xfer_get_protocol_data(xfer))) {
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
@@ -1431,14 +1429,15 @@
 	time_str[strlen(time_str) - 1] = '\0';
 
 	if (xd->txbuflen == 0)	{
-		xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\n"
+		gchar *initial_buffer = g_strdup_printf("HTTP/1.0 200 OK\r\n"
 		                            "Date: %s GMT\r\n"
 		                            "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",
-		                            time_str, time_str, xfer->size);
-		xd->txbuflen = strlen(xd->txbuf);
+		                            "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);
 		xd->txbuf_written = 0;
 	}
 
@@ -1458,7 +1457,7 @@
 	struct yahoo_xfer_data *xd;
 
 	xfer = data;
-	if (!(xd = xfer->data))	{
+	if (!(xd = purple_xfer_get_protocol_data(xfer))) {
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
@@ -1480,8 +1479,8 @@
 	close(xd->yahoo_local_p2p_ft_server_fd);
 
 	/* Add an Input Read event to the file descriptor */
-	xfer->fd = acceptfd;
-	if(xfer->type == PURPLE_XFER_RECEIVE)
+	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
 		xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_HEAD_GET_cb, data);
@@ -1500,14 +1499,14 @@
 	char *filename_without_spaces = NULL;
 
 	xfer = data;
-	if (!(xd = xfer->data) || (listenfd == -1))	{
+	if (!(xd = purple_xfer_get_protocol_data(xfer)) || (listenfd == -1))	{
 		purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n");
 		purple_xfer_cancel_remote(xfer);
 		return;
 	}
 
-	if( (xfer->type == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) )	{
-		yd = xd->gc->proto_data;
+	if( (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) )	{
+		yd = purple_connection_get_protocol_data(xd->gc);
 		account = purple_connection_get_account(xd->gc);
 		local_ip = purple_network_get_my_ip(listenfd);
 		xd->yahoo_local_p2p_ft_server_port = purple_network_get_port_from_fd(listenfd);
@@ -1515,18 +1514,18 @@
 		filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
 		filename_without_spaces = g_strdup(filename);
 		purple_util_chrreplace(filename_without_spaces, ' ', '+');
-		xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", xfer->who, (int)time(NULL), filename_without_spaces, xfer->who);
+		xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", purple_xfer_get_remote_user(xfer), (int)time(NULL), filename_without_spaces, purple_xfer_get_remote_user(xfer));
 		url_to_send = g_strdup_printf("http://%s:%d%s", local_ip, xd->yahoo_local_p2p_ft_server_port, xd->xfer_url);
 
-		if(xfer->type == PURPLE_XFER_RECEIVE)	{
+		if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
 			xd->info_val_249 = 2;	/* 249=2: we are p2p server, and receiving file */
 			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
 				YAHOO_STATUS_AVAILABLE, yd->session_id);
 			yahoo_packet_hash(pkt, "ssssis",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xd->xfer_peer_idstring,
-				27, xfer->filename,
+				27, purple_xfer_get_filename(xfer),
 				249, 2,
 				250, url_to_send);
 		}
@@ -1535,7 +1534,7 @@
 			pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
 			yahoo_packet_hash(pkt, "ssssis",
 				1, purple_normalize(account, purple_account_get_username(account)),
-				5, xfer->who,
+				5, purple_xfer_get_remote_user(xfer),
 				265, xd->xfer_peer_idstring,
 				27,  filename,
 				249, 1,
@@ -1564,15 +1563,15 @@
 	gchar *filename;
 	struct yahoo_p2p_data *p2p_data;
 
-	if (!(xd = xfer->data))
+	if (!(xd = purple_xfer_get_protocol_data(xfer)))
 		return;
 
 	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
-	p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
+	p2p_data = g_hash_table_lookup(yd->peers, purple_xfer_get_remote_user(xfer));
 	if( p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER )
-		if(purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer))
+		if(purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer))
 			return;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -1580,7 +1579,7 @@
 
 	yahoo_packet_hash(pkt, "ssssi",
 		1, purple_normalize(account, purple_account_get_username(account)),
-		5, xfer->who,
+		5, purple_xfer_get_remote_user(xfer),
 		265, xd->xfer_peer_idstring,
 		27,  filename,
 		249, 2);	/* 249=2: we are p2p client */
@@ -1603,13 +1602,13 @@
 	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;
 	int nooffiles = 0;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
@@ -1683,13 +1682,13 @@
 		account = purple_connection_get_account(gc);
 		if (yd->jp)
 		{
-			purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST,
+			purple_dnsquery_a(account, YAHOOJP_XFER_RELAY_HOST,
 							YAHOOJP_XFER_RELAY_PORT,
 							yahoo_xfer_dns_connected_15, xfer);
 		}
 		else
 		{
-			purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST,
+			purple_dnsquery_a(account, YAHOO_XFER_RELAY_HOST,
 							YAHOO_XFER_RELAY_PORT,
 							yahoo_xfer_dns_connected_15, xfer);
 		}
@@ -1720,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);
@@ -1732,22 +1731,20 @@
 	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);
 		g_return_if_reached();
 	}
 
-	xfer->message = NULL;
-
 	/* Set the info about the incoming file. */
 	utf8_filename = yahoo_string_decode(gc, filename, TRUE);
 	purple_xfer_set_filename(xfer, utf8_filename);
 	g_free(utf8_filename);
 	purple_xfer_set_size(xfer, filesize);
 
-	xfer->data = xfer_data;
+	purple_xfer_set_protocol_data(xfer, xfer_data);
 
 	/* Setup our I/O op functions */
 	purple_xfer_set_init_fnc(xfer,        yahoo_xfer_init_15);
@@ -1765,7 +1762,7 @@
 
 	if(nooffiles > 1) {
 		gchar* message;
-		message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles);
+		message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), purple_xfer_get_remote_user(xfer), nooffiles);
 		purple_xfer_conversation_write(xfer, message, FALSE);
 		g_free(message);
 	}
@@ -1790,7 +1787,7 @@
 	struct yahoo_packet *pkt_to_send;
 	struct yahoo_p2p_data *p2p_data;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
@@ -1837,7 +1834,7 @@
 		return;
 	}
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 
 	xfer_data->info_val_249 = val_249;
 	xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
@@ -1854,9 +1851,9 @@
 			YAHOO_STATUS_AVAILABLE, yd->session_id);
 		yahoo_packet_hash(pkt_to_send, "ssssis",
 			1, purple_normalize(account, purple_account_get_username(account)),
-			5, xfer->who,
+			5, purple_xfer_get_remote_user(xfer),
 			265, xfer_data->xfer_peer_idstring,
-			27, xfer->filename,
+			27, purple_xfer_get_filename(xfer),
 			249, xfer_data->info_val_249,
 			251, xfer_data->xfer_idstring_for_relay);
 
@@ -1870,12 +1867,12 @@
 		}
 	}
 	else if(val_249 == 2)	{
-		p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
+		p2p_data = g_hash_table_lookup(yd->peers, purple_xfer_get_remote_user(xfer));
 		if( !( p2p_data && (p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) ) )	{
 			purple_xfer_cancel_remote(xfer);
 			return;
 		}
-		if(!purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) {
+		if(!purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer)) {
 			purple_xfer_cancel_remote(xfer);
 			return;
 		}
@@ -1896,7 +1893,7 @@
 	gchar *url = NULL;
 	int val_249 = 0;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
 
@@ -1934,7 +1931,7 @@
 		return;
 	}
 
-	xfer_data = xfer->data;
+	xfer_data = purple_xfer_get_protocol_data(xfer);
 	if(url)
 		purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL);
 
--- a/libpurple/protocols/yahoo/yahoo_friend.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_friend.c	Mon Oct 31 01:25:36 2011 +0000
@@ -46,9 +46,10 @@
 	const char *norm;
 
 	g_return_val_if_fail(gc != NULL, NULL);
-	g_return_val_if_fail(gc->proto_data != NULL, NULL);
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
+	g_return_val_if_fail(yd != NULL, NULL);
+
 	norm = purple_normalize(purple_connection_get_account(gc), name);
 
 	return g_hash_table_lookup(yd->friends, norm);
@@ -61,9 +62,10 @@
 	const char *norm;
 
 	g_return_val_if_fail(gc != NULL, NULL);
-	g_return_val_if_fail(gc->proto_data != NULL, NULL);
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
+	g_return_val_if_fail(yd != NULL, NULL);
+
 	norm = purple_normalize(purple_connection_get_account(gc), name);
 
 	f = g_hash_table_lookup(yd->friends, norm);
@@ -225,7 +227,7 @@
 void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
 		YahooPresenceVisibility presence)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt = NULL;
 	YahooFriend *f;
 	const char *thirtyone, *thirteen;
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Mon Oct 31 01:25:36 2011 +0000
@@ -302,7 +302,7 @@
 		return;
 	else if (ret < 0) {
 		/* TODO: what to do here - do we really have to disconnect? */
-		purple_connection_error_reason(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		purple_connection_error(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 		                               _("Write Error"));
 		return;
 	}
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_picture.c	Mon Oct 31 01:25:36 2011 +0000
@@ -52,7 +52,7 @@
 	YahooData *yd;
 
 	d = user_data;
-	yd = d->gc->proto_data;
+	yd = purple_connection_get_protocol_data(d->gc);
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
 	if (error_message != NULL) {
@@ -132,10 +132,10 @@
 		data->checksum = checksum;
 		/* TODO: Does this need to be MSIE 5.0? */
 		url_data = purple_util_fetch_url(url, use_whole_url,
-				"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE,
+				"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, -1,
 				yahoo_fetch_picture_cb, data);
 		if (url_data != NULL) {
-			yd = gc->proto_data;
+			yd = purple_connection_get_protocol_data(gc);
 			yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
 		} else {
 			g_free(data->who);
@@ -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. */
@@ -185,7 +185,7 @@
 void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GSList *l = pkt->hash;
 	char *url = NULL;
 
@@ -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);
@@ -261,7 +261,7 @@
 
 void yahoo_send_picture_info(PurpleConnection *gc, const char *who)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 
 	if (!yd->picture_url) {
@@ -278,7 +278,7 @@
 
 void yahoo_send_picture_request(PurpleConnection *gc, const char *who)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -290,7 +290,7 @@
 
 void yahoo_send_picture_checksum(PurpleConnection *gc)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -301,7 +301,7 @@
 
 void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_AVATAR_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
@@ -326,7 +326,7 @@
 
 void yahoo_send_picture_update(PurpleConnection *gc, int type)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yspufe data;
 
 	data.gc = gc;
@@ -425,7 +425,7 @@
 	gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
 
 	account = purple_connection_get_account(gc);
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	/* Buddy icon connect is now complete; clear the PurpleProxyConnectData */
 	yd->buddy_icon_connect_data = NULL;
@@ -490,7 +490,7 @@
 void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (yd->buddy_icon_connect_data != NULL) {
 		/* Cancel any in-progress buddy icon upload */
@@ -535,8 +535,8 @@
 
 void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
-	YahooData *yd = gc->proto_data;
-	PurpleAccount *account = gc->account;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
+	PurpleAccount *account = purple_connection_get_account(gc);
 
 	if (img == NULL) {
 		g_free(yd->picture_url);
--- a/libpurple/protocols/yahoo/yahoo_profile.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoo_profile.c	Mon Oct 31 01:25:36 2011 +0000
@@ -789,7 +789,7 @@
 
 	purple_debug_info("yahoo", "In yahoo_got_info\n");
 
-	yd = info_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(info_data->gc);
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
 	user_info = purple_notify_user_info_new();
@@ -805,7 +805,7 @@
 	 * to send back HTML, with a 200 status code.
 	 */
 	if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) {
-		purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), NULL);
+		purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL);
 		purple_notify_userinfo(info_data->gc, info_data->name,
 			user_info, NULL, NULL);
 		purple_notify_user_info_destroy(user_info);
@@ -840,7 +840,7 @@
 						 _("If you wish to view this profile, "
 						"you will need to visit this link in your web browser:"),
 						 profile_url_text, profile_url_text);
-		purple_notify_user_info_add_pair(user_info, NULL, tmp);
+		purple_notify_user_info_add_pair_html(user_info, NULL, tmp);
 		g_free(tmp);
 
 		purple_notify_userinfo(info_data->gc, info_data->name,
@@ -940,7 +940,7 @@
 		 * we specify HTTP 1.1. So we have to specify 1.0 & fix purple_util_fetch_url
 		 */
 		url_data = purple_util_fetch_url(photo_url_text, use_whole_url, NULL,
-				FALSE, yahoo_got_photo, info2_data);
+				FALSE, -1, yahoo_got_photo, info2_data);
 		if (url_data != NULL)
 			yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
 	} else {
@@ -983,7 +983,7 @@
 	/* in to purple_markup_strip_html*/
 	char *fudged_buffer;
 
-	yd = info_data->gc->proto_data;
+	yd = purple_connection_get_protocol_data(info_data->gc);
 	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
 	fudged_buffer = purple_strcasereplace(url_buffer, "</dd>", "</dd><br>");
@@ -1048,7 +1048,7 @@
 			id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
 
 			tmp = g_strdup_printf("<img id=\"%d\"><br>", id);
-			purple_notify_user_info_add_pair(user_info, NULL, tmp);
+			purple_notify_user_info_add_pair_html(user_info, NULL, tmp);
 			g_free(tmp);
 		}
 	}
@@ -1195,7 +1195,7 @@
 		const gchar *str;
 
 		purple_notify_user_info_add_section_break(user_info);
-		purple_notify_user_info_add_pair(user_info,
+		purple_notify_user_info_add_pair_html(user_info,
 				_("Error retrieving profile"), NULL);
 
 		if (profile_state == PROFILE_STATE_UNKNOWN_LANGUAGE) {
@@ -1228,14 +1228,14 @@
 			str = _("The user's profile is empty.");
 		}
 
-		purple_notify_user_info_add_pair(user_info, NULL, str);
+		purple_notify_user_info_add_pair_plaintext(user_info, NULL, str);
 	}
 
 	/* put a link to the actual profile URL */
 	purple_notify_user_info_add_section_break(user_info);
 	tmp = g_strdup_printf("<a href=\"%s\">%s</a>",
 			profile_url_text, _("View web profile"));
-	purple_notify_user_info_add_pair(user_info, NULL, tmp);
+	purple_notify_user_info_add_pair_html(user_info, NULL, tmp);
 	g_free(tmp);
 
 	g_free(stripped);
@@ -1262,7 +1262,7 @@
 
 void yahoo_get_info(PurpleConnection *gc, const char *name)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	YahooGetInfoData *data;
 	char *url;
 	PurpleUtilFetchUrlData *url_data;
@@ -1274,7 +1274,7 @@
 	url = g_strdup_printf("%s%s",
 			(yd->jp ? YAHOOJP_PROFILE_URL : YAHOO_PROFILE_URL), name);
 
-	url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data);
+	url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, -1, yahoo_got_info, data);
 	if (url_data != NULL)
 		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
 	else {
--- a/libpurple/protocols/yahoo/yahoochat.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Mon Oct 31 01:25:36 2011 +0000
@@ -53,7 +53,7 @@
 /* special function to log us on to the yahoo chat service */
 static void yahoo_chat_online(PurpleConnection *gc)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	const char *rll;
 
@@ -101,7 +101,7 @@
 	YahooData *yd;
 	GSList *l;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	for (l = yd->confs; l; l = l->next) {
 		PurpleConversation *c = l->data;
@@ -372,7 +372,7 @@
 
 static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	char *room2;
 	gboolean utf8 = TRUE;
@@ -400,7 +400,7 @@
 /* this is a confirmation of yahoo_chat_online(); */
 void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
-	YahooData *yd = (YahooData *) gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (pkt->status == 1) {
 		yd->chat_online = TRUE;
@@ -432,7 +432,7 @@
 /* this is basicly the opposite of chat_online */
 void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
-	YahooData *yd = (YahooData *) gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GSList *l;
 
 	for (l = pkt->hash; l; l = l->next) {
@@ -462,7 +462,7 @@
 void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = (YahooData *) gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleConversation *c = NULL;
 	GSList *l;
 	GList *members = NULL;
@@ -786,7 +786,7 @@
 static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
 							GList *members, const char *what)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	GList *who;
 	char *msg, *msg2;
@@ -843,7 +843,7 @@
 static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c,
 		const char *dn, const char *buddy, const char *room, const char *msg)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	GList *members;
 	char *msg2 = NULL;
@@ -873,7 +873,7 @@
 
 static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 
 	char *eroom;
@@ -924,7 +924,7 @@
 
 static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	int me = 0;
 	char *msg1, *msg2, *room2;
@@ -969,7 +969,7 @@
 static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy,
 							const char *room, const char *msg)
 {
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	struct yahoo_packet *pkt;
 	char *room2, *msg2 = NULL;
 	gboolean utf8 = TRUE;
@@ -997,7 +997,7 @@
 	YahooData *yd;
 	struct yahoo_packet *pkt;
 
-	yd = gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 
 	if (yd->wm) {
 		g_return_if_fail(yd->ycht != NULL);
@@ -1029,7 +1029,7 @@
 
 void yahoo_c_leave(PurpleConnection *gc, int id)
 {
-	YahooData *yd = (YahooData *) gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleConversation *c;
 
 	if (!yd)
@@ -1056,7 +1056,7 @@
 	int ret;
 	YahooData *yd;
 
-	yd = (YahooData *) gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	if (!yd)
 		return -1;
 
@@ -1114,7 +1114,7 @@
 	char *room, *topic, *type;
 	PurpleConversation *c;
 
-	yd = (YahooData *) gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	if (!yd)
 		return;
 
@@ -1166,7 +1166,7 @@
 	PurpleConversation *c;
 
 	c = purple_find_chat(gc, id);
-	if (!c || !c->name)
+	if (!c || !purple_conversation_get_name(c))
 		return;
 
 	if (id != YAHOO_CHAT_ID) {
@@ -1375,7 +1375,9 @@
 	purple_roomlist_set_in_progress(list, FALSE);
 
 	if (yrl) {
-		list->proto_data = g_list_remove(list->proto_data, yrl);
+		GList *proto_data = purple_roomlist_get_proto_data(list);
+		proto_data = g_list_remove(proto_data, yrl);
+		purple_roomlist_set_proto_data(list, proto_data);
 		yahoo_roomlist_destroy(yrl);
 	}
 
@@ -1451,7 +1453,7 @@
 		yrl->inpa = 0;
 		g_free(yrl->txbuf);
 		yrl->txbuf = NULL;
-		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
+		purple_notify_error(purple_account_get_connection(purple_roomlist_get_account(list)), NULL, _("Unable to connect"), _("Fetching the room list failed."));
 		yahoo_roomlist_cleanup(list, yrl);
 		return;
 	}
@@ -1474,10 +1476,12 @@
 {
 	struct yahoo_roomlist *yrl = data;
 	PurpleRoomlist *list = yrl->list;
-	YahooData *yd = purple_account_get_connection(list->account)->proto_data;
+	PurpleAccount *account = purple_roomlist_get_account(list);
+	PurpleConnection *pc = purple_account_get_connection(account);
+	YahooData *yd = purple_connection_get_protocol_data(pc);
 
 	if (source < 0) {
-		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
+		purple_notify_error(pc, NULL, _("Unable to connect"), _("Fetching the room list failed."));
 		yahoo_roomlist_cleanup(list, yrl);
 		return;
 	}
@@ -1506,6 +1510,7 @@
 	struct yahoo_roomlist *yrl;
 	const char *rll, *rlurl;
 	char *url;
+	GList *proto_data;
 
 	account = purple_connection_get_account(gc);
 
@@ -1556,7 +1561,9 @@
 		return NULL;
 	}
 
-	rl->proto_data = g_list_append(rl->proto_data, yrl);
+	proto_data = purple_roomlist_get_proto_data(rl);
+	proto_data = g_list_append(proto_data, yrl);
+	purple_roomlist_set_proto_data(rl, proto_data);
 
 	purple_roomlist_set_in_progress(rl, TRUE);
 	return rl;
@@ -1566,8 +1573,8 @@
 {
 	GList *l, *k;
 
-	k = l = list->proto_data;
-	list->proto_data = NULL;
+	k = l = purple_roomlist_get_proto_data(list);
+	purple_roomlist_set_proto_data(list, NULL);
 
 	purple_roomlist_set_in_progress(list, FALSE);
 
@@ -1580,36 +1587,42 @@
 
 void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category)
 {
+	PurpleAccount *account;
 	struct yahoo_roomlist *yrl;
 	char *url;
 	char *id;
 	const char *rll;
+	GList *proto_data;
 
-	if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
+	if (purple_roomlist_room_get_type(category) != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
 		return;
 
-	if (!(id = g_list_nth_data(category->fields, 1))) {
+	if (!(id = g_list_nth_data(purple_roomlist_room_get_fields(category), 1))) {
 		purple_roomlist_set_in_progress(list, FALSE);
 		return;
 	}
 
-	rll = purple_account_get_string(list->account, "room_list_locale",
+	account = purple_roomlist_get_account(list);
+	rll = purple_account_get_string(account, "room_list_locale",
 								  YAHOO_ROOMLIST_LOCALE);
 
 	if (rll != NULL && *rll != '\0') {
 		url = g_strdup_printf("%s?chatroom_%s=0&intl=%s",
-	       purple_account_get_string(list->account,"room_list",
+	       purple_account_get_string(account,"room_list",
 	       YAHOO_ROOMLIST_URL), id, rll);
 	} else {
 		url = g_strdup_printf("%s?chatroom_%s=0",
-	       purple_account_get_string(list->account,"room_list",
+	       purple_account_get_string(account,"room_list",
 	       YAHOO_ROOMLIST_URL), id);
 	}
 
 	yrl = g_new0(struct yahoo_roomlist, 1);
 	yrl->list = list;
 	yrl->cat = category;
-	list->proto_data = g_list_append(list->proto_data, yrl);
+
+	proto_data = purple_roomlist_get_proto_data(list);
+	proto_data = g_list_append(proto_data, yrl);
+	purple_roomlist_set_proto_data(list, proto_data);
 
 	purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
 	g_free(url);
@@ -1617,11 +1630,11 @@
 	yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat);
 	purple_roomlist_room_add(list, yrl->ucat);
 
-	if (purple_proxy_connect(purple_account_get_connection(list->account),
-			list->account, yrl->host, 80,
+	if (purple_proxy_connect(purple_account_get_connection(account),
+			account, yrl->host, 80,
 			yahoo_roomlist_got_connected, yrl) == NULL)
 	{
-		purple_notify_error(purple_account_get_connection(list->account),
+		purple_notify_error(purple_account_get_connection(account),
 		                  NULL, _("Connection problem"), _("Unable to fetch room list."));
 		purple_roomlist_ref(list);
 		yahoo_roomlist_cleanup(list, yrl);
--- a/libpurple/protocols/yahoo/ycht.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/yahoo/ycht.c	Mon Oct 31 01:25:36 2011 +0000
@@ -53,7 +53,7 @@
 static void ycht_process_login(YchtConn *ycht, YchtPkt *pkt)
 {
 	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (ycht->logged_in)
 		return;
@@ -68,7 +68,7 @@
 static void ycht_process_logout(YchtConn *ycht, YchtPkt *pkt)
 {
 	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	yd->chat_online = FALSE;
 	ycht->logged_in = FALSE;
@@ -173,7 +173,7 @@
 {
 #if 0
 	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (ycht->logged_in)
 		return;
@@ -285,7 +285,7 @@
 /*
 		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 				g_strerror(errno));
-		purple_connection_error_reason(purple_account_get_connection(irc->account),
+		purple_connection_error(purple_account_get_connection(irc->account),
 			      PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
 		g_free(tmp);
 */
@@ -429,7 +429,7 @@
 
 void ycht_connection_close(YchtConn *ycht)
 {
-	YahooData *yd = ycht->gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(ycht->gc);
 
 	if (yd) {
 		yd->ycht = NULL;
@@ -541,7 +541,7 @@
 {
 	YchtConn *ycht = data;
 	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	YchtPkt *pkt;
 	char *buf;
 
@@ -568,7 +568,7 @@
 void ycht_connection_open(PurpleConnection *gc)
 {
 	YchtConn *ycht;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 
 	ycht = g_new0(YchtConn, 1);
--- a/libpurple/protocols/zephyr/zephyr.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Mon Oct 31 01:25:36 2011 +0000
@@ -146,7 +146,7 @@
 					return TRUE;
 
 #define z_call_s(func, err)	if (func != ZERR_NONE) {\
-					purple_connection_error(gc, err);\
+					purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, err);\
 					return;\
 				}
 
@@ -347,7 +347,7 @@
 {
 	gchar *utf8;
 	GError *err = NULL;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if (g_utf8_validate(string, -1, NULL)) {
 		return g_strdup(string);
 	} else {
@@ -762,7 +762,7 @@
 
 static void handle_message(PurpleConnection *gc,ZNotice_t notice)
 {
-	zephyr_account* zephyr = gc->proto_data;
+	zephyr_account* zephyr = purple_connection_get_protocol_data(gc);
 
 	if (!g_ascii_strcasecmp(notice.z_class, LOGIN_CLASS)) {
 		/* well, we'll be updating in 20 seconds anyway, might as well ignore this. */
@@ -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);
 			}
 
@@ -791,20 +791,23 @@
 				char *tmp;
 				const char *balias;
 
-				purple_notify_user_info_add_pair(user_info, _("User"), (b ? bname : user));
+				/* TODO: Check whether it's correct to call add_pair_html,
+				         or if we should be using add_pair_plaintext */
+				purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user));
 				balias = purple_buddy_get_local_buddy_alias(b);
 				if (b && balias)
-					purple_notify_user_info_add_pair(user_info, _("Alias"), balias);
+					purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias);
 
 				if (!nlocs) {
-					purple_notify_user_info_add_pair(user_info, NULL, _("Hidden or not logged-in"));
+					purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in"));
 				}
 				for (; nlocs > 0; nlocs--) {
 					/* XXX add real error reporting */
 
 					ZGetLocations(&locs, &one);
+					/* TODO: Need to escape locs.host and locs.time? */
 					tmp = g_strdup_printf(_("<br>At %s since %s"), locs.host, locs.time);
-					purple_notify_user_info_add_pair(user_info, _("Location"), tmp);
+					purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp);
 					g_free(tmp);
 				}
 				purple_notify_userinfo(gc, (b ? bname : user),
@@ -812,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);
@@ -869,7 +872,7 @@
 		} else {
 			zephyr_triple *zt1, *zt2;
 			gchar *send_inst_utf8;
-			zephyr_account *zephyr = gc->proto_data;
+			zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 			zt1 = new_triple(zephyr,notice.z_class, notice.z_class_inst, notice.z_recipient);
 			zt2 = find_sub_by_triple(zephyr,zt1);
 			if (!zt2) {
@@ -897,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
@@ -1106,7 +1109,7 @@
 static gint check_notify_tzc(gpointer data)
 {
 	PurpleConnection *gc = (PurpleConnection *)data;
-	zephyr_account* zephyr = gc->proto_data;
+	zephyr_account* zephyr = purple_connection_get_protocol_data(gc);
 	parse_tree *newparsetree = read_from_tzc(zephyr);
 	if (newparsetree != NULL) {
 		gchar *spewtype;
@@ -1153,15 +1156,15 @@
 				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");
 				locval = tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents;
 
-				if (!locval || !g_ascii_strcasecmp(locval," ") || (strlen(locval) == 0)) {
+				if (!locval || !g_ascii_strcasecmp(locval," ") || !*locval) {
 					nlocs = 0;
 				} else {
 					nlocs = 1;
@@ -1173,19 +1176,22 @@
 					char *tmp;
 					const char *balias;
 
-					purple_notify_user_info_add_pair(user_info, _("User"), (b ? bname : user));
+					/* TODO: Check whether it's correct to call add_pair_html,
+					         or if we should be using add_pair_plaintext */
+					purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user));
 
 					balias = b ? purple_buddy_get_local_buddy_alias(b) : NULL;
 					if (balias)
-						purple_notify_user_info_add_pair(user_info, _("Alias"), balias);
+						purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias);
 
 					if (!nlocs) {
-						purple_notify_user_info_add_pair(user_info, NULL, _("Hidden or not logged-in"));
+						purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in"));
 					} else {
+						/* TODO: Need to escape the two strings that make up tmp? */
 						tmp = g_strdup_printf(_("<br>At %s since %s"),
 									  tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents,
 									  tree_child(tree_child(tree_child(tree_child(locations,2),0),2),2)->contents);
-						purple_notify_user_info_add_pair(user_info, _("Location"), tmp);
+						purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp);
 						g_free(tmp);
 					}
 
@@ -1194,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)) {
@@ -1259,7 +1265,7 @@
 	GSList *buddies;
 	ZLocations_t locations;
 	PurpleConnection *gc = data;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	int numlocs;
 	int one = 1;
@@ -1290,7 +1296,7 @@
 	GSList *buddies;
 	ZAsyncLocateData_t ald;
 	PurpleConnection *gc = (PurpleConnection *)data;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 
 	if (use_zeph02(zephyr)) {
@@ -1515,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);
@@ -1558,34 +1564,35 @@
 	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;
-	gc->proto_data = zephyr=g_new0(zephyr_account,1);
+	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);
 
 	zephyr->account = account;
 
 	/* 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 */
 	if (use_tzc(zephyr)) {
 		pid_t pid;
-		/*		  purple_connection_error(gc,"tzc not supported yet"); */
+		/*		  purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "tzc not supported yet"); */
 		if ((pipe(zephyr->totzc) != 0) || (pipe(zephyr->fromtzc) != 0)) {
 			purple_debug_error("zephyr", "pipe creation failed. killing\n");
 			exit(-1);
@@ -1600,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);
 			}
@@ -1706,7 +1713,7 @@
 				ptr++;
 			}
 			if (ptr >=bufcur) {
-				purple_connection_error(gc,"invalid output by tzc (or bad parsing code)");
+				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "invalid output by tzc (or bad parsing code)");
 				free(buf);
 				return;
 			}
@@ -1772,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";
 							}
@@ -1809,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();
 		}
@@ -1821,7 +1828,7 @@
 		purple_debug_info("zephyr","realm: %s\n",zephyr->realm);
 	}
 	else {
-		purple_connection_error(gc,"Only ZEPH0.2 supported currently");
+		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "Only ZEPH0.2 supported currently");
 		return;
 	}
 	purple_debug_info("zephyr","does it get here\n");
@@ -1835,7 +1842,7 @@
 	if (zephyr_subscribe_to(zephyr,"MESSAGE","PERSONAL",zephyr->username,NULL) != ZERR_NONE) {
 		/* XXX don't translate this yet. It could be written better */
 		/* XXX error messages could be handled with more detail */
-		purple_notify_error(account->gc, NULL,
+		purple_notify_error(purple_account_get_connection(account), NULL,
 				  "Unable to subscribe to messages", "Unable to subscribe to initial messages");
 		return;
 	}
@@ -1955,7 +1962,7 @@
 {
 	GList *l;
 	GSList *s;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	pid_t tzc_pid = zephyr->tzc_pid;
 
 	l = zephyr->pending_zloc_names;
@@ -1965,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;
@@ -2030,7 +2037,7 @@
 	PurpleConvChat *gcc;
 	char *inst;
 	char *recipient;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 
 	zt = find_sub_by_id(zephyr,id);
 	if (!zt)
@@ -2040,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)))
@@ -2059,7 +2066,7 @@
 static int zephyr_send_im(PurpleConnection * gc, const char *who, const char *im, PurpleMessageFlags flags)
 {
 	const char *sig;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if (flags & PURPLE_MESSAGE_AUTO_RESP)
 		sig = "Automated reply:";
 	else {
@@ -2079,7 +2086,7 @@
 	int pos2 = 0;
 	char *newmsg;
 
-	if (message && (strlen(message) > 0)) {
+	if (message && *message) {
 		newmsg = g_new0(char,1+strlen(message)*2);
 		while(pos < strlen(message)) {
 			if (message[pos]=='\\') {
@@ -2111,7 +2118,7 @@
 	int pos2 = 0;
 	char *newmsg;
 
-	if (message && (strlen(message) > 0)) {
+	if (message && *message) {
 		newmsg = g_new0(char,strlen(message)+1);
 		while(pos < strlen(message)) {
 			if (message[pos]=='\\') {
@@ -2228,7 +2235,7 @@
 	if (gc == NULL)
 		return NULL;
 
-	tmp = local_zephyr_normalize(gc->proto_data, who);
+	tmp = local_zephyr_normalize(purple_connection_get_protocol_data(gc), who);
 
 	if (strlen(tmp) >= sizeof(buf)) {
 		g_free(tmp);
@@ -2244,7 +2251,7 @@
 static void zephyr_zloc(PurpleConnection *gc, const char *who)
 {
 	ZAsyncLocateData_t ald;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	gchar* normalized_who = local_zephyr_normalize(zephyr,who);
 
 	if (use_zeph02(zephyr)) {
@@ -2271,7 +2278,8 @@
 static void zephyr_set_status(PurpleAccount *account, PurpleStatus *status) {
 	size_t len;
 	size_t result;
-	zephyr_account *zephyr = purple_account_get_connection(account)->proto_data;
+	PurpleConnection *gc = purple_account_get_connection(account);
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_type(status));
 
 	if (zephyr->away) {
@@ -2405,7 +2413,7 @@
 	const char *classname;
 	const char *instname;
 	const char *recip;
-	zephyr_account *zephyr=gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	classname = g_hash_table_lookup(data, "class");
 	instname = g_hash_table_lookup(data, "instance");
 	recip = g_hash_table_lookup(data, "recipient");
@@ -2468,7 +2476,7 @@
 static void zephyr_chat_leave(PurpleConnection * gc, int id)
 {
 	zephyr_triple *zt;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	zt = find_sub_by_id(zephyr,id);
 
 	if (zt) {
@@ -2518,7 +2526,7 @@
 
 static unsigned int zephyr_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) {
 	gchar *recipient;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	if (use_tzc(zephyr))
 		return 0;
 
@@ -2560,7 +2568,7 @@
 	PurpleConversation *gconv;
 	PurpleConvChat *gcc;
 	gchar *topic_utf8;
-	zephyr_account* zephyr = gc->proto_data;
+	zephyr_account* zephyr = purple_connection_get_protocol_data(gc);
 	char *sender = (char *)zephyr->username;
 
 	zt = find_sub_by_id(zephyr,id);
@@ -2568,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);
@@ -2583,7 +2591,8 @@
 				      const char *cmd, char **args, char **error, void *data)
 {
 	char *recipient;
-	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
+	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 */
 	else
@@ -2601,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;
 }
 
@@ -2613,9 +2622,8 @@
 	 * one word isn't ideal either.	 */
 
 	PurpleConvChat *gcc = purple_conversation_get_chat_data(conv);
-	int id = gcc->id;
 	const char* instance = args[0];
-	zephyr_chat_set_topic(purple_conversation_get_gc(conv),id,instance);
+	zephyr_chat_set_topic(purple_conversation_get_connection(conv),purple_conv_chat_get_id(gcc),instance);
 	return PURPLE_CMD_RET_OK;
 }
 
@@ -2627,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;
 }
 
@@ -2635,7 +2643,8 @@
 				     const char *cmd, char **args, char **error, void *data)
 {
 	/* args = instance, message */
-	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
+	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;
 	else
@@ -2646,7 +2655,8 @@
 				      const char *cmd, char **args, char **error, void *data)
 {
 	/* args = class, instance, message */
-	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
+	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;
 	else
@@ -2657,7 +2667,8 @@
 				       const char *cmd, char **args, char **error, void *data)
 {
 	/* args = class, instance, recipient, message */
-	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
+	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;
 	else
@@ -2668,7 +2679,8 @@
 				      const char *cmd, char **args, char **error, void *data)
 {
 	/* args = instance, recipient, message */
-	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
+	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;
 	else
@@ -2679,7 +2691,8 @@
 				     const char *cmd, char **args, char **error, void *data)
 {
 	/* args = class, message */
-	zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data;
+	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;
 	else
@@ -2760,7 +2773,7 @@
 {
 	/* Resubscribe to the in-memory list of subscriptions and also
 	   unsubscriptions*/
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	GSList *s = zephyr->subscrips;
 	zephyr_triple *zt;
 	while (s) {
@@ -2785,7 +2798,7 @@
 static void zephyr_action_get_subs_from_server(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
-	zephyr_account *zephyr = gc->proto_data;
+	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	gchar *title;
 	int retval, nsubs, one,i;
 	ZSubscription_t subs;
@@ -2839,6 +2852,7 @@
 static PurplePlugin *my_protocol = NULL;
 
 static PurplePluginProtocolInfo prpl_info = {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD,
 	NULL,					/* ??? user_splits */
 	NULL,					/* ??? protocol_options */
@@ -2879,7 +2893,6 @@
 	NULL,					/* keepalive -- Not necessary*/
 	NULL,					/* register_user -- Not supported*/
 	NULL,					/* XXX get_cb_info */
-	NULL,					/* get_cb_away */
 	NULL,					/* alias_buddy */
 	NULL,					/* group_buddy */
 	NULL,					/* rename_group */
@@ -2905,15 +2918,12 @@
 	NULL,
 	NULL,
 	NULL,
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,					/* get_account_text_table */
 	NULL,					/* initate_media */
 	NULL,					/* get_media_caps */
 	NULL,					/* get_moods */
 	NULL,					/* set_public_alias */
-	NULL,					/* get_public_alias */
-	NULL,					/* add_buddy_with_invite */
-	NULL					/* add_buddies_with_invite */
+	NULL					/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/proxy.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/proxy.c	Mon Oct 31 01:25:36 2011 +0000
@@ -41,6 +41,16 @@
 #include "proxy.h"
 #include "util.h"
 
+struct _PurpleProxyInfo
+{
+	PurpleProxyType type;   /**< The proxy type.  */
+
+	char *host;           /**< The host.        */
+	int   port;           /**< The port number. */
+	char *username;       /**< The username.    */
+	char *password;       /**< The password.    */
+};
+
 struct _PurpleProxyConnectData {
 	void *handle;
 	PurpleProxyConnectFunction connect_cb;
@@ -1369,7 +1379,7 @@
 
 		proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
 	} else {
-		connect_data->query_data = purple_dnsquery_a_account(
+		connect_data->query_data = purple_dnsquery_a(
 				connect_data->account, connect_data->host,
 				connect_data->port, s4_host_resolved, connect_data);
 
@@ -2088,7 +2098,7 @@
 
 /**
  * This function attempts to connect to the next IP address in the list
- * of IP addresses returned to us by purple_dnsquery_a() and attemps
+ * of IP addresses returned to us by purple_dnsquery_a() and attempts
  * to connect to each one.  This is called after the hostname is
  * resolved, and each time a connection attempt fails (assuming there
  * is another IP address to try).
@@ -2317,7 +2327,7 @@
 			return NULL;
 	}
 
-	connect_data->query_data = purple_dnsquery_a_account(account, connecthost,
+	connect_data->query_data = purple_dnsquery_a(account, connecthost,
 			connectport, connection_host_resolved, connect_data);
 	if (connect_data->query_data == NULL)
 	{
@@ -2385,7 +2395,7 @@
 			return NULL;
 	}
 
-	connect_data->query_data = purple_dnsquery_a_account(account, connecthost,
+	connect_data->query_data = purple_dnsquery_a(account, connecthost,
 			connectport, connection_host_resolved, connect_data);
 	if (connect_data->query_data == NULL)
 	{
@@ -2398,17 +2408,6 @@
 	return connect_data;
 }
 
-PurpleProxyConnectData *
-purple_proxy_connect_socks5(void *handle, PurpleProxyInfo *gpi,
-						  const char *host, int port,
-						  PurpleProxyConnectFunction connect_cb,
-						  gpointer data)
-{
-	return purple_proxy_connect_socks5_account(NULL, handle, gpi,
-						  host, port, connect_cb, data);
-}
-
-
 /* This is called when we connect to the SOCKS5 proxy server (through any
  * relevant account proxy)
  */
--- a/libpurple/proxy.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/proxy.h	Mon Oct 31 01:25:36 2011 +0000
@@ -47,16 +47,7 @@
 /**
  * Information on proxy settings.
  */
-typedef struct
-{
-	PurpleProxyType type;   /**< The proxy type.  */
-
-	char *host;           /**< The host.        */
-	int   port;           /**< The port number. */
-	char *username;       /**< The username.    */
-	char *password;       /**< The password.    */
-
-} PurpleProxyInfo;
+typedef struct _PurpleProxyInfo PurpleProxyInfo;
 
 typedef struct _PurpleProxyConnectData PurpleProxyConnectData;
 
@@ -191,7 +182,6 @@
  * Set purple's global proxy information.
  *
  * @param info     The proxy information.
- * @since 2.6.0
  */
 void purple_global_proxy_set_info(PurpleProxyInfo *info);
 
@@ -316,35 +306,6 @@
 			const char *host, int port,
 			PurpleProxyConnectFunction connect_cb, gpointer data);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PROXY_C_)
-/**
- * Makes a connection through a SOCKS5 proxy.
- *
- * @param handle     A handle that should be associated with this
- *                   connection attempt.  The handle can be used
- *                   to cancel the connection attempt using the
- *                   purple_proxy_connect_cancel_with_handle()
- *                   function.
- * @param gpi        The PurpleProxyInfo specifying the proxy settings
- * @param host       The destination host.
- * @param port       The destination port.
- * @param connect_cb The function to call when the connection is
- *                   established.  If the connection failed then
- *                   fd will be -1 and error message will be set
- *                   to something descriptive (hopefully).
- * @param data       User-defined data.
- *
- * @return NULL if there was an error, or a reference to an
- *         opaque data structure that can be used to cancel
- *         the pending connection, if needed.
- * @deprecated Use purple_proxy_connect_socks5_account instead
- */
-PurpleProxyConnectData *purple_proxy_connect_socks5(void *handle,
-			PurpleProxyInfo *gpi,
-			const char *host, int port,
-			PurpleProxyConnectFunction connect_cb, gpointer data);
-#endif
-
 /**
  * Cancel an in-progress connection attempt.  This should be called
  * by the PRPL if the user disables an account while it is still
--- a/libpurple/prpl.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/prpl.c	Mon Oct 31 01:25:36 2011 +0000
@@ -32,6 +32,17 @@
 /**************************************************************************/
 /** @name Attention Type API                                              */
 /**************************************************************************/
+
+struct _PurpleAttentionType
+{
+	const char *name;                  /**< Shown in GUI elements */
+	const char *incoming_description;  /**< Shown when sent */
+	const char *outgoing_description;  /**< Shown when receied */
+	const char *icon_name;             /**< Icon to display (optional) */
+	const char *unlocalized_name;      /**< Unlocalized name for UIs needing it */
+};
+
+
 PurpleAttentionType *
 purple_attention_type_new(const char *ulname, const char *name,
 						const char *inc_desc, const char *out_desc)
@@ -435,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);
@@ -462,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));
 
@@ -481,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/prpl.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/prpl.h	Mon Oct 31 01:25:36 2011 +0000
@@ -31,7 +31,10 @@
 #define _PURPLE_PRPL_H_
 
 typedef struct _PurplePluginProtocolInfo PurplePluginProtocolInfo;
-/** @copydoc _PurpleAttentionType */
+
+/** Represents "nudges" and "buzzes" that you may send to a buddy to attract
+ *  their attention (or vice-versa).
+ */
 typedef struct _PurpleAttentionType PurpleAttentionType;
 
 /**************************************************************************/
@@ -111,23 +114,6 @@
 	gboolean secret;         /**< True if the entry is secret (password) */
 };
 
-/** Represents "nudges" and "buzzes" that you may send to a buddy to attract
- *  their attention (or vice-versa).
- */
-struct _PurpleAttentionType
-{
-	const char *name;                  /**< Shown in GUI elements */
-	const char *incoming_description;  /**< Shown when sent */
-	const char *outgoing_description;  /**< Shown when receied */
-	const char *icon_name;             /**< Icon to display (optional) */
-	const char *unlocalized_name;      /**< Unlocalized name for UIs needing it */
-
-	/* Reserved fields for future purposes */
-	gpointer _reserved2;
-	gpointer _reserved3;
-	gpointer _reserved4;
-};
-
 /**
  * Protocol options
  *
@@ -200,14 +186,12 @@
 	/**
 	 * Indicates that slash commands are native to this protocol.
 	 * Used as a hint that unknown commands should not be sent as messages.
-	 * @since 2.1.0
 	 */
 	OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400,
 
 	/**
 	 * Indicates that this protocol supports sending a user-supplied message
 	 * along with an invitation.
-	 * @since 2.8.0
 	 */
 	OPT_PROTO_INVITE_MESSAGE = 0x00000800
 
@@ -222,6 +206,27 @@
  */
 struct _PurplePluginProtocolInfo
 {
+	/**
+	 * The size of the PurplePluginProtocolInfo. This should always be sizeof(PurplePluginProtocolInfo).
+	 * This allows adding more functions to this struct without requiring a major version bump.
+	 */
+	unsigned long struct_size;
+
+	/* NOTE:
+	 * If more functions are added, they should accessed using the following syntax:
+	 *
+	 *		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, new_function))
+	 *			prpl->new_function(...);
+	 *
+	 * instead of
+	 *
+	 *		if (prpl->new_function != NULL)
+	 *			prpl->new_function(...);
+	 *
+	 * The PURPLE_PROTOCOL_PLUGIN_HAS_FUNC macro can be used for the older member
+	 * functions (e.g. login, send_im etc.) too.
+	 */
+
 	PurpleProtocolOptions options;  /**< Protocol options.          */
 
 	GList *user_splits;      /**< A GList of PurpleAccountUserSplit */
@@ -333,6 +338,7 @@
 	void (*set_idle)(PurpleConnection *, int idletime);
 	void (*change_passwd)(PurpleConnection *, const char *old_pass,
 						  const char *new_pass);
+
 	/**
 	 * Add a buddy to a group on the server.
 	 *
@@ -341,11 +347,10 @@
 	 * authorization and the user is not already authorized to see the
 	 * status of \a buddy, \a add_buddy should request authorization.
 	 *
-	 * @deprecated Since 2.8.0, add_buddy_with_invite is preferred.
-	 * @see add_buddy_with_invite
+	 * If authorization is required, then use the supplied invite message.
 	 */
-	void (*add_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group);
-	void (*add_buddies)(PurpleConnection *, GList *buddies, GList *groups);
+	void (*add_buddy)(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message);
+	void (*add_buddies)(PurpleConnection *pc, GList *buddies, GList *groups, const char *message);
 	void (*remove_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group);
 	void (*remove_buddies)(PurpleConnection *, GList *buddies, GList *groups);
 	void (*add_permit)(PurpleConnection *, const char *name);
@@ -444,11 +449,6 @@
 	 * @deprecated Use #PurplePluginProtocolInfo.get_info instead.
 	 */
 	void (*get_cb_info)(PurpleConnection *, int, const char *who);
-	/**
-	 * @deprecated Use #PurplePluginProtocolInfo.get_cb_real_name and
-	 *             #PurplePluginProtocolInfo.status_text instead.
-	 */
-	void (*get_cb_away)(PurpleConnection *, int, const char *who);
 
 	/** save/store buddy's alias on server list/roster */
 	void (*alias_buddy)(PurpleConnection *, const char *who,
@@ -534,27 +534,6 @@
 	gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type);
 	GList *(*get_attention_types)(PurpleAccount *acct);
 
-	/**
-	 * The size of the PurplePluginProtocolInfo. This should always be sizeof(PurplePluginProtocolInfo).
-	 * This allows adding more functions to this struct without requiring a major version bump.
-	 */
-	unsigned long struct_size;
-
-	/* NOTE:
-	 * If more functions are added, they should accessed using the following syntax:
-	 *
-	 *		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, new_function))
-	 *			prpl->new_function(...);
-	 *
-	 * instead of
-	 *
-	 *		if (prpl->new_function != NULL)
-	 *			prpl->new_function(...);
-	 *
-	 * The PURPLE_PROTOCOL_PLUGIN_HAS_FUNC macro can be used for the older member
-	 * functions (e.g. login, send_im etc.) too.
-	 */
-
 	/** This allows protocols to specify additional strings to be used for
 	 * various purposes.  The idea is to stuff a bunch of strings in this hash
 	 * table instead of expanding the struct for every addition.  This hash
@@ -590,7 +569,6 @@
 	/**
 	 * Returns an array of "PurpleMood"s, with the last one having
 	 * "mood" set to @c NULL.
-	 * @since 2.7.0
 	 */
 	PurpleMood *(*get_moods)(PurpleAccount *account);
 
@@ -610,7 +588,6 @@
 	 * @param failure_cb Callback to be called if setting the public alias
 	 *                   fails
 	 * @see purple_account_set_public_alias
-	 * @since 2.7.0
 	 */
 	void (*set_public_alias)(PurpleConnection *gc, const char *alias,
 	                         PurpleSetPublicAliasSuccessCallback success_cb,
@@ -627,31 +604,14 @@
 	 * @param failure_cb Callback to be called if the prpl is unable to
 	 *                   retrieve the alias
 	 * @see purple_account_get_public_alias
-	 * @since 2.7.0
 	 */
 	void (*get_public_alias)(PurpleConnection *gc,
 	                         PurpleGetPublicAliasSuccessCallback success_cb,
 	                         PurpleGetPublicAliasFailureCallback failure_cb);
-
-	/**
-	 * Add a buddy to a group on the server.
-	 *
-	 * This PRPL function may be called in situations in which the buddy is
-	 * already in the specified group. If the protocol supports
-	 * authorization and the user is not already authorized to see the
-	 * status of \a buddy, \a add_buddy should request authorization.
-	 *
-	 * If authorization is required, then use the supplied invite message.
-	 *
-	 * @since 2.8.0
-	 */
-	void (*add_buddy_with_invite)(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message);
-	void (*add_buddies_with_invite)(PurpleConnection *pc, GList *buddies, GList *groups, const char *message);
 };
 
 #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
-	(((G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < G_STRUCT_OFFSET(PurplePluginProtocolInfo, struct_size)) \
-	  || (G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size)) && \
+	(G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size && \
 	 prpl->member != NULL)
 
 
@@ -680,8 +640,8 @@
  *             should be the same string as @a ulname, with localization.
  * @param inc_desc A localized description shown when the event is received.
  * @param out_desc A localized description shown when the event is sent.
+ *
  * @return A pointer to the new object.
- * @since 2.4.0
  */
 PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name,
 								const char *inc_desc, const char *out_desc);
@@ -693,7 +653,6 @@
  * @param name The localized name that will be displayed by UIs. This should be
  *             the same string given as the unlocalized name, but with
  *             localization.
- * @since 2.4.0
  */
 void purple_attention_type_set_name(PurpleAttentionType *type, const char *name);
 
@@ -703,7 +662,6 @@
  *
  * @param type The attention type.
  * @param desc The localized description for incoming events.
- * @since 2.4.0
  */
 void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc);
 
@@ -713,7 +671,6 @@
  *
  * @param type The attention type.
  * @param desc The localized description for outgoing events.
- * @since 2.4.0
  */
 void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc);
 
@@ -723,7 +680,6 @@
  * @param type The attention type.
  * @param name The icon's name.
  * @note Icons are optional for attention events.
- * @since 2.4.0
  */
 void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name);
 
@@ -734,7 +690,6 @@
  * @param type The attention type.
  * @param ulname The unlocalized name.  This should be the same string given as
  *               the localized name, but without localization.
- * @since 2.4.0
  */
 void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname);
 
@@ -742,8 +697,8 @@
  * Get the attention type's name as displayed by the UI.
  *
  * @param type The attention type.
+ *
  * @return The name.
- * @since 2.4.0
  */
 const char *purple_attention_type_get_name(const PurpleAttentionType *type);
 
@@ -752,7 +707,6 @@
  *
  * @param type The attention type.
  * @return The description.
- * @since 2.4.0
  */
 const char *purple_attention_type_get_incoming_desc(const PurpleAttentionType *type);
 
@@ -761,7 +715,6 @@
  *
  * @param type The attention type.
  * @return The description.
- * @since 2.4.0
  */
 const char *purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type);
 
@@ -771,7 +724,6 @@
  * @param type The attention type.
  * @return The icon name or @c NULL if unset/empty.
  * @note Icons are optional for attention events.
- * @since 2.4.0
  */
 const char *purple_attention_type_get_icon_name(const PurpleAttentionType *type);
 
@@ -780,7 +732,6 @@
  *
  * @param type The attention type
  * @return The unlocalized name.
- * @since 2.4.0
  */
 const char *purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type);
 
@@ -836,7 +787,6 @@
  * @param account   The account.
  *
  * @see account-actions-changed
- * @since 2.6.0
  */
 void purple_prpl_got_account_actions(PurpleAccount *account);
 
@@ -927,8 +877,6 @@
  *
  * Note that you can't send arbitrary PurpleAttentionType's, because there is
  * only a fixed set of attention commands.
- *
- * @since 2.5.0
  */
 void purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code);
 
@@ -939,8 +887,6 @@
  * @param who Who requested your attention.
  * @param type_code An index into the prpl's attention_types list determining the type
  *        of the attention request command to send.
- *
- * @since 2.5.0
  */
 void purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code);
 
@@ -952,8 +898,6 @@
  * @param who Who requested your attention.
  * @param type_code An index into the prpl's attention_types list determining the type
  *        of the attention request command to send.
- *
- * @since 2.5.0
  */
 void purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code);
 
@@ -988,7 +932,6 @@
  *
  * @param account The account the user is on.
  * @param who The name of the contact for which capabilities have been received.
- * @since 2.7.0
  */
 void purple_prpl_got_media_caps(PurpleAccount *account, const char *who);
 
--- a/libpurple/purple-2-uninstalled.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-abs_srcdir=@abs_srcdir@
-abs_builddir=@abs_builddir@
-
-abs_top_srcdir=@abs_top_srcdir@
-abs_top_builddir=@abs_top_builddir@
-
-plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@
-
-Name: libpurple
-Description: libpurple is a GLib-based instant messenger library.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${abs_top_srcdir} -I${abs_top_builddir}
-Libs: ${abs_builddir}/libpurple.la
--- a/libpurple/purple-2.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@
-
-Name: libpurple
-Description: libpurple is a GLib-based instant messenger library.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${includedir}
-Libs: -L${libdir} -lpurple
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purple-3-uninstalled.pc.in	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,22 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+
+abs_srcdir=@abs_srcdir@
+abs_builddir=@abs_builddir@
+
+abs_top_srcdir=@abs_top_srcdir@
+abs_top_builddir=@abs_top_builddir@
+
+plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@
+
+Name: libpurple
+Description: libpurple is a GLib-based instant messenger library.
+Version: @VERSION@
+Requires: glib-2.0
+Cflags: -I${abs_top_srcdir} -I${abs_top_builddir}
+Libs: ${abs_builddir}/libpurple.la
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purple-3.pc.in	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,16 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+
+plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@
+
+Name: libpurple
+Description: libpurple is a GLib-based instant messenger library.
+Version: @VERSION@
+Requires: glib-2.0
+Cflags: -I${includedir}
+Libs: -L${libdir} -lpurple
--- a/libpurple/purple-uninstalled.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-abs_srcdir=@abs_srcdir@
-abs_builddir=@abs_builddir@
-
-plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@
-
-Name: libpurple
-Description: libpurple is a GLib-based instant messenger library.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${abs_srcdir} -I${abs_builddir}
-Libs: ${abs_builddir}/libpurple.la
--- a/libpurple/purple.h.in	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/purple.h.in	Mon Oct 31 01:25:36 2011 +0000
@@ -6,7 +6,6 @@
  * include any other libpurple files.
  *
  * @ingroup core libpurple
- * @since 2.3.0
  */
 
 /* purple
--- a/libpurple/purple.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@
-
-Name: libpurple
-Description: libpurple is a GLib-based instant messenger library.
-Version: @VERSION@
-Requires: glib-2.0
-Cflags: -I${includedir}/libpurple
-Libs: -L${libdir} -lpurple
--- a/libpurple/request.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/request.c	Mon Oct 31 01:25:36 2011 +0000
@@ -42,6 +42,108 @@
 
 } PurpleRequestInfo;
 
+struct _PurpleRequestField
+{
+	PurpleRequestFieldType type;
+	PurpleRequestFieldGroup *group;
+
+	char *id;
+	char *label;
+	char *type_hint;
+
+	gboolean visible;
+	gboolean required;
+
+	union
+	{
+		struct
+		{
+			gboolean multiline;
+			gboolean masked;
+			gboolean editable;
+			char *default_value;
+			char *value;
+
+		} string;
+
+		struct
+		{
+			int default_value;
+			int value;
+
+		} integer;
+
+		struct
+		{
+			gboolean default_value;
+			gboolean value;
+
+		} boolean;
+
+		struct
+		{
+			int default_value;
+			int value;
+
+			GList *labels;
+
+		} choice;
+
+		struct
+		{
+			GList *items;
+			GList *icons;
+			GHashTable *item_data;
+			GList *selected;
+			GHashTable *selected_table;
+
+			gboolean multiple_selection;
+
+		} list;
+
+		struct
+		{
+			PurpleAccount *default_account;
+			PurpleAccount *account;
+			gboolean show_all;
+
+			PurpleFilterAccountFunc filter_func;
+
+		} account;
+
+		struct
+		{
+			unsigned int scale_x;
+			unsigned int scale_y;
+			const char *buffer;
+			gsize size;
+		} image;
+
+	} u;
+
+	void *ui_data;
+	char *tooltip;
+};
+
+struct _PurpleRequestFields
+{
+	GList *groups;
+
+	GHashTable *fields;
+
+	GList *required_fields;
+
+	void *ui_data;
+};
+
+struct _PurpleRequestFieldGroup
+{
+	PurpleRequestFields *fields_list;
+
+	char *title;
+
+	GList *fields;
+};
 
 PurpleRequestFields *
 purple_request_fields_new(void)
@@ -271,6 +373,20 @@
 	return purple_request_field_account_get_value(field);
 }
 
+gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields)
+{
+	g_return_val_if_fail(fields != NULL, NULL);
+
+	return fields->ui_data;
+}
+
+void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data)
+{
+	g_return_if_fail(fields != NULL);
+
+	fields->ui_data = ui_data;
+}
+
 PurpleRequestFieldGroup *
 purple_request_field_group_new(const char *title)
 {
@@ -337,6 +453,14 @@
 	return group->fields;
 }
 
+PurpleRequestFields *
+purple_request_field_group_get_fields_list(const PurpleRequestFieldGroup *group)
+{
+	g_return_val_if_fail(group != NULL, NULL);
+
+	return group->fields_list;
+}
+
 PurpleRequestField *
 purple_request_field_new(const char *id, const char *text,
 					   PurpleRequestFieldType type)
@@ -365,6 +489,7 @@
 	g_free(field->id);
 	g_free(field->label);
 	g_free(field->type_hint);
+	g_free(field->tooltip);
 
 	if (field->type == PURPLE_REQUEST_FIELD_STRING)
 	{
@@ -428,6 +553,15 @@
 }
 
 void
+purple_request_field_set_tooltip(PurpleRequestField *field, const char *tooltip)
+{
+	g_return_if_fail(field != NULL);
+
+	g_free(field->tooltip);
+	field->tooltip = g_strdup(tooltip);
+}
+
+void
 purple_request_field_set_required(PurpleRequestField *field, gboolean required)
 {
 	g_return_if_fail(field != NULL);
@@ -502,6 +636,14 @@
 	return field->type_hint;
 }
 
+const char *
+purple_request_field_get_tooltip(const PurpleRequestField *field)
+{
+	g_return_val_if_fail(field != NULL, NULL);
+
+	return field->tooltip;
+}
+
 gboolean
 purple_request_field_is_required(const PurpleRequestField *field)
 {
@@ -847,13 +989,6 @@
 }
 
 void
-purple_request_field_list_add(PurpleRequestField *field, const char *item,
-							void *data)
-{
-	purple_request_field_list_add_icon(field, item, NULL, data);
-}
-
-void
 purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path,
 							void *data)
 {
--- a/libpurple/request.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/request.h	Mon Oct 31 01:25:36 2011 +0000
@@ -30,9 +30,21 @@
 #include <glib-object.h>
 #include <glib.h>
 
-/** @copydoc _PurpleRequestField */
+/**
+ * A request field.
+ */
 typedef struct _PurpleRequestField PurpleRequestField;
 
+/**
+ * Multiple fields request data.
+ */
+typedef struct _PurpleRequestFields PurpleRequestFields;
+
+/**
+ * A group of fields with a title.
+ */
+typedef struct _PurpleRequestFieldGroup PurpleRequestFieldGroup;
+
 #include "account.h"
 
 #define PURPLE_DEFAULT_ACTION_NONE	-1
@@ -69,122 +81,6 @@
 } PurpleRequestFieldType;
 
 /**
- * Multiple fields request data.
- */
-typedef struct
-{
-	GList *groups;
-
-	GHashTable *fields;
-
-	GList *required_fields;
-
-	void *ui_data;
-
-} PurpleRequestFields;
-
-/**
- * A group of fields with a title.
- */
-typedef struct
-{
-	PurpleRequestFields *fields_list;
-
-	char *title;
-
-	GList *fields;
-
-} PurpleRequestFieldGroup;
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_REQUEST_C_)
-/**
- * A request field.
- */
-struct _PurpleRequestField
-{
-	PurpleRequestFieldType type;
-	PurpleRequestFieldGroup *group;
-
-	char *id;
-	char *label;
-	char *type_hint;
-
-	gboolean visible;
-	gboolean required;
-
-	union
-	{
-		struct
-		{
-			gboolean multiline;
-			gboolean masked;
-			gboolean editable;
-			char *default_value;
-			char *value;
-
-		} string;
-
-		struct
-		{
-			int default_value;
-			int value;
-
-		} integer;
-
-		struct
-		{
-			gboolean default_value;
-			gboolean value;
-
-		} boolean;
-
-		struct
-		{
-			int default_value;
-			int value;
-
-			GList *labels;
-
-		} choice;
-
-		struct
-		{
-			GList *items;
-			GList *icons;
-			GHashTable *item_data;
-			GList *selected;
-			GHashTable *selected_table;
-
-			gboolean multiple_selection;
-
-		} list;
-
-		struct
-		{
-			PurpleAccount *default_account;
-			PurpleAccount *account;
-			gboolean show_all;
-
-			PurpleFilterAccountFunc filter_func;
-
-		} account;
-
-		struct
-		{
-			unsigned int scale_x;
-			unsigned int scale_y;
-			const char *buffer;
-			gsize size;
-		} image;
-
-	} u;
-
-	void *ui_data;
-
-};
-#endif
-
-/**
  * Request UI operations.
  */
 typedef struct
@@ -410,6 +306,25 @@
 PurpleAccount *purple_request_fields_get_account(const PurpleRequestFields *fields,
 											 const char *id);
 
+/**
+ * Returns the UI data associated with this object.
+ *
+ * @param fields The fields list.
+ *
+ * @return The UI data associated with this object.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libuprple core.
+ */
+gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields);
+
+/**
+ * Set the UI data associated with this object.
+ *
+ * @param fields The fields list.
+ * @param ui_data A pointer to associate with this object.
+ */
+void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data);
+
 /*@}*/
 
 /**************************************************************************/
@@ -462,6 +377,16 @@
 GList *purple_request_field_group_get_fields(
 		const PurpleRequestFieldGroup *group);
 
+/**
+ * Returns a list of all fields in a group.
+ *
+ * @param group The group.
+ *
+ * @constreturn The list of fields in the group.
+ */
+PurpleRequestFields *purple_request_field_group_get_fields_list(
+		const PurpleRequestFieldGroup *group);
+
 /*@}*/
 
 /**************************************************************************/
@@ -517,6 +442,18 @@
 									  const char *type_hint);
 
 /**
+ * Sets the tooltip for the field.
+ *
+ * This is optionally used by the UIs to provide a tooltip for
+ * the field.
+ *
+ * @param field     The field.
+ * @param tooltip   The tooltip text.
+ */
+void purple_request_field_set_tooltip(PurpleRequestField *field,
+									const char *tooltip);
+
+/**
  * Sets whether or not a field is required.
  *
  * @param field    The field.
@@ -540,8 +477,6 @@
  * @param field The field.
  *
  * @return The UI data.
- *
- * @since 2.6.0
  */
 PurpleRequestFieldGroup *purple_request_field_get_group(const PurpleRequestField *field);
 
@@ -582,6 +517,15 @@
 const char *purple_request_field_get_type_hint(const PurpleRequestField *field);
 
 /**
+ * Returns the field's tooltip.
+ *
+ * @param field The field.
+ *
+ * @return The field's tooltip.
+ */
+const char *purple_request_field_get_tooltip(const PurpleRequestField *field);
+
+/**
  * Returns whether or not a field is required.
  *
  * @param field The field.
@@ -596,8 +540,6 @@
  * @param field The field.
  *
  * @return The UI data.
- *
- * @since 2.6.0
  */
 gpointer purple_request_field_get_ui_data(const PurpleRequestField *field);
 
@@ -608,8 +550,6 @@
  * @param ui_data The UI data.
  *
  * @return The UI data.
- *
- * @since 2.6.0
  */
 void purple_request_field_set_ui_data(PurpleRequestField *field,
                                       gpointer ui_data);
@@ -961,18 +901,6 @@
  *
  * @param field The list field.
  * @param item  The list item.
- * @param data  The associated data.
- *
- * @deprecated Use purple_request_field_list_add_icon() instead.
- */
-void purple_request_field_list_add(PurpleRequestField *field,
-								 const char *item, void *data);
-
-/**
- * Adds an item to a list field.
- *
- * @param field The list field.
- * @param item  The list item.
  * @param icon_path The path to icon file, or @c NULL for no icon.
  * @param data  The associated data.
  */
@@ -1402,8 +1330,7 @@
 
 /**
  * Version of purple_request_action() supplying an image for the UI to
- * optionally display as an icon in the dialog; see its documentation
- * @since 2.7.0
+ * optionally display as an icon in the dialog; see its documentation.
  */
 void *purple_request_action_with_icon(void *handle, const char *title,
 	const char *primary, const char *secondary, int default_action,
@@ -1414,7 +1341,6 @@
 /**
  * <tt>va_list</tt> version of purple_request_action_with_icon();
  * see its documentation.
- * @since 2.7.0
  */
 void *purple_request_action_with_icon_varg(void *handle, const char *title,
 	const char *primary, const char *secondary, int default_action,
--- a/libpurple/roomlist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/roomlist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -32,6 +32,39 @@
 #include "roomlist.h"
 #include "server.h"
 
+/**
+ * Represents a list of rooms for a given connection on a given protocol.
+ */
+struct _PurpleRoomlist {
+	PurpleAccount *account; /**< The account this list belongs to. */
+	GList *fields; /**< The fields. */
+	GList *rooms; /**< The list of rooms. */
+	gboolean in_progress; /**< The listing is in progress. */
+	gpointer ui_data; /**< UI private data. */
+	gpointer proto_data; /** Prpl private data. */
+	guint ref; /**< The reference count. */
+};
+
+/**
+ * Represents a room.
+ */
+struct _PurpleRoomlistRoom {
+	PurpleRoomlistRoomType type; /**< The type of room. */
+	gchar *name; /**< The name of the room. */
+	GList *fields; /**< Other fields. */
+	PurpleRoomlistRoom *parent; /**< The parent room, or NULL. */
+	gboolean expanded_once; /**< A flag the UI uses to avoid multiple expand prpl cbs. */
+};
+
+/**
+ * A field a room might have.
+ */
+struct _PurpleRoomlistField {
+	PurpleRoomlistFieldType type; /**< The type of field. */
+	gchar *label; /**< The i18n user displayed name of the field. */
+	gchar *name; /**< The internal name of the field. */
+	gboolean hidden; /**< Hidden? */
+};
 
 static PurpleRoomlistUiOps *ops = NULL;
 
@@ -127,6 +160,13 @@
 		purple_roomlist_destroy(list);
 }
 
+PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list)
+{
+	g_return_val_if_fail(list != NULL, NULL);
+
+	return list->account;
+}
+
 void purple_roomlist_set_fields(PurpleRoomlist *list, GList *fields)
 {
 	g_return_if_fail(list != NULL);
@@ -234,6 +274,34 @@
 	return list->fields;
 }
 
+gpointer purple_roomlist_get_proto_data(PurpleRoomlist *list)
+{
+	g_return_val_if_fail(list != NULL, NULL);
+
+	return list->proto_data;
+}
+
+void purple_roomlist_set_proto_data(PurpleRoomlist *list, gpointer proto_data)
+{
+	g_return_if_fail(list != NULL);
+
+	list->proto_data = proto_data;
+}
+
+gpointer purple_roomlist_get_ui_data(PurpleRoomlist *list)
+{
+	g_return_val_if_fail(list != NULL, NULL);
+
+	return list->ui_data;
+}
+
+void purple_roomlist_set_ui_data(PurpleRoomlist *list, gpointer ui_data)
+{
+	g_return_if_fail(list != NULL);
+
+	list->ui_data = ui_data;
+}
+
 /*@}*/
 
 /**************************************************************************/
@@ -329,7 +397,21 @@
 	return room->parent;
 }
 
-GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room)
+gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room)
+{
+	g_return_val_if_fail(room != NULL, FALSE);
+
+	return room->expanded_once;
+}
+
+void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once)
+{
+	g_return_if_fail(room != NULL);
+
+	room->expanded_once = expanded_once;
+}
+
+GList *purple_roomlist_room_get_fields(PurpleRoomlistRoom *room)
 {
 	return room->fields;
 }
--- a/libpurple/roomlist.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/roomlist.h	Mon Oct 31 01:25:36 2011 +0000
@@ -64,40 +64,6 @@
 /**************************************************************************/
 
 /**
- * Represents a list of rooms for a given connection on a given protocol.
- */
-struct _PurpleRoomlist {
-	PurpleAccount *account; /**< The account this list belongs to. */
-	GList *fields; /**< The fields. */
-	GList *rooms; /**< The list of rooms. */
-	gboolean in_progress; /**< The listing is in progress. */
-	gpointer ui_data; /**< UI private data. */
-	gpointer proto_data; /** Prpl private data. */
-	guint ref; /**< The reference count. */
-};
-
-/**
- * Represents a room.
- */
-struct _PurpleRoomlistRoom {
-	PurpleRoomlistRoomType type; /**< The type of room. */
-	gchar *name; /**< The name of the room. */
-	GList *fields; /**< Other fields. */
-	PurpleRoomlistRoom *parent; /**< The parent room, or NULL. */
-	gboolean expanded_once; /**< A flag the UI uses to avoid multiple expand prpl cbs. */
-};
-
-/**
- * A field a room might have.
- */
-struct _PurpleRoomlistField {
-	PurpleRoomlistFieldType type; /**< The type of field. */
-	gchar *label; /**< The i18n user displayed name of the field. */
-	gchar *name; /**< The internal name of the field. */
-	gboolean hidden; /**< Hidden? */
-};
-
-/**
  * The room list ops to be filled out by the UI.
  */
 struct _PurpleRoomlistUiOps {
@@ -163,6 +129,14 @@
 void purple_roomlist_unref(PurpleRoomlist *list);
 
 /**
+ * Retrieve the PurpleAccount that was given when the room list was
+ * created.
+ *
+ * @return The PurpleAccount tied to this room list.
+ */
+PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list);
+
+/**
  * Set the different field types and their names for this protocol.
  *
  * This must be called before purple_roomlist_room_add().
@@ -241,11 +215,48 @@
 /**
  * Get the list of fields for a roomlist.
  *
- * @param roomlist  The roomlist, which must not be @c NULL.
+ * @param roomlist The roomlist, which must not be @c NULL.
  * @constreturn A list of fields
- * @since 2.4.0
+ */
+GList *purple_roomlist_get_fields(PurpleRoomlist *roomlist);
+
+/**
+ * Get the protocol data associated with this room list.
+ *
+ * @param list The roomlist, which must not be @c NULL.
+ *
+ * @return The protocol data associated with this room list.  This is a
+ *         convenience field provided to the protocol plugin--it is not
+ *         used the libpurple core.
+ */
+gpointer purple_roomlist_get_proto_data(PurpleRoomlist *list);
+
+/**
+ * Set the protocol data associated with this room list.
+ *
+ * @param list The roomlist, which must not be @c NULL.
+ * @param proto_data A pointer to associate with this room list.
  */
-GList * purple_roomlist_get_fields(PurpleRoomlist *roomlist);
+void purple_roomlist_set_proto_data(PurpleRoomlist *list, gpointer proto_data);
+
+/**
+ * Get the UI data associated with this room list.
+ *
+ * @param list The roomlist, which must not be @c NULL.
+ *
+ * @return The UI data associated with this room list.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libpurple core.
+ */
+gpointer purple_roomlist_get_ui_data(PurpleRoomlist *list);
+
+/**
+ * Set the UI data associated with this room list.
+ *
+ * @param list The roomlist, which must not be @c NULL.
+ * @param ui_data A pointer to associate with this room list.
+ */
+void purple_roomlist_set_ui_data(PurpleRoomlist *list, gpointer ui_data);
 
 /*@}*/
 
@@ -287,7 +298,6 @@
  * Get the type of a room.
  * @param room  The room, which must not be @c NULL.
  * @return The type of the room.
- * @since 2.4.0
  */
 PurpleRoomlistRoomType purple_roomlist_room_get_type(PurpleRoomlistRoom *room);
 
@@ -295,7 +305,6 @@
  * Get the name of a room.
  * @param room  The room, which must not be @c NULL.
  * @return The name of the room.
- * @since 2.4.0
  */
 const char * purple_roomlist_room_get_name(PurpleRoomlistRoom *room);
 
@@ -303,16 +312,31 @@
  * Get the parent of a room.
  * @param room  The room, which must not be @c NULL.
  * @return The parent of the room, which can be @c NULL.
- * @since 2.4.0
  */
 PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room);
 
 /**
+ * Get the value of the expanded_once flag.
+ *
+ * @param room  The room, which must not be @c NULL.
+ *
+ * @return The value of the expanded_once flag.
+ */
+gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room);
+
+/**
+ * Set the expanded_once flag.
+ *
+ * @param room The room, which must not be @c NULL.
+ * @param expanded_once The new value of the expanded_once flag.
+ */
+void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once);
+
+/**
  * Get the list of fields for a room.
  *
  * @param room  The room, which must not be @c NULL.
  * @constreturn A list of fields
- * @since 2.4.0
  */
 GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room);
 
@@ -344,7 +368,6 @@
  * @param field  A PurpleRoomlistField, which must not be @c NULL.
  *
  * @return  The type of the field.
- * @since 2.4.0
  */
 PurpleRoomlistFieldType purple_roomlist_field_get_type(PurpleRoomlistField *field);
 
@@ -354,7 +377,6 @@
  * @param field  A PurpleRoomlistField, which must not be @c NULL.
  *
  * @return  The label of the field.
- * @since 2.4.0
  */
 const char * purple_roomlist_field_get_label(PurpleRoomlistField *field);
 
@@ -363,7 +385,6 @@
  * @param field  A PurpleRoomlistField, which must not be @c NULL.
  *
  * @return  @c TRUE if the field is hidden, @c FALSE otherwise.
- * @since 2.4.0
  */
 gboolean purple_roomlist_field_get_hidden(PurpleRoomlistField *field);
 
--- a/libpurple/savedstatuses.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/savedstatuses.c	Mon Oct 31 01:25:36 2011 +0000
@@ -387,7 +387,6 @@
 		const char *protocol;
 		acct_name = xmlnode_get_data(node);
 		protocol = xmlnode_get_attrib(node, "protocol");
-		protocol = _purple_oscar_convert(acct_name, protocol); /* XXX: Remove */
 		if ((acct_name != NULL) && (protocol != NULL))
 			ret->account = purple_accounts_find(acct_name, protocol);
 		g_free(acct_name);
@@ -404,7 +403,7 @@
 	if ((node != NULL) && ((data = xmlnode_get_data(node)) != NULL))
 	{
 		ret->type = purple_status_type_find_with_id(
-							ret->account->status_types, data);
+							purple_account_get_status_types(ret->account), data);
 		g_free(data);
 	}
 
--- a/libpurple/server.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/server.c	Mon Oct 31 01:25:36 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")) {
 
@@ -325,18 +325,6 @@
 	return attn;
 }
 
-void
-serv_send_attention(PurpleConnection *gc, const char *who, guint type_code)
-{
-	purple_prpl_send_attention(gc, who, type_code);
-}
-
-void
-serv_got_attention(PurpleConnection *gc, const char *who, guint type_code)
-{
-	purple_prpl_got_attention(gc, who, type_code);
-}
-
 
 /*
  * Move a buddy from one group to another on server.
@@ -582,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
@@ -593,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) {
@@ -605,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);
@@ -627,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;
@@ -700,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);
 
@@ -710,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;
 		}
 	}
@@ -732,12 +720,12 @@
 	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);
 
-		if (im->typing_state == PURPLE_NOT_TYPING)
+		if (purple_conv_im_get_typing_state(im) == PURPLE_NOT_TYPING)
 			return;
 
 		purple_conv_im_stop_typing_timeout(im);
@@ -746,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);
 	}
 }
 
@@ -937,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) {
@@ -949,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/server.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/server.h	Mon Oct 31 01:25:36 2011 +0000
@@ -61,32 +61,6 @@
  */
 PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code);
 
-/** Send an attention request message.
- *
- * @deprecated Use purple_prpl_send_attention() instead.
- *
- * @param gc The connection to send the message on.
- * @param who Whose attention to request.
- * @param type_code An index into the prpl's attention_types list determining the type
- * 	of the attention request command to send. 0 if prpl only defines one
- * 	(for example, Yahoo and MSN), but some protocols define more (MySpaceIM).
- *
- * Note that you can't send arbitrary PurpleAttentionType's, because there is
- * only a fixed set of attention commands.
- */
-void serv_send_attention(PurpleConnection *gc, const char *who, guint type_code);
-
-/** Process an incoming attention message.
- *
- * @deprecated Use purple_prpl_got_attention() instead.
- *
- * @param gc The connection that received the attention message.
- * @param who Who requested your attention.
- * @param type_code An index into the prpl's attention_types list determining the type
- * 	of the attention request command to send.
- */
-void serv_got_attention(PurpleConnection *gc, const char *who, guint type_code);
-
 void serv_get_info(PurpleConnection *, const char *);
 void serv_set_info(PurpleConnection *, const char *);
 
--- a/libpurple/smiley.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/smiley.h	Mon Oct 31 01:25:36 2011 +0000
@@ -1,7 +1,6 @@
 /**
  * @file smiley.h Smiley API
  * @ingroup core
- * @since 2.5.0
  */
 
 /* purple
--- a/libpurple/sound-theme.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/sound-theme.c	Mon Oct 31 01:25:36 2011 +0000
@@ -24,7 +24,7 @@
 #include "sound-theme.h"
 
 #define PURPLE_SOUND_THEME_GET_PRIVATE(Gobject) \
-	((PurpleSoundThemePrivate *) ((PURPLE_SOUND_THEME(Gobject))->priv))
+	(G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PURPLE_TYPE_SOUND_THEME, PurpleSoundThemePrivate))
 
 /******************************************************************************
  * Structs
@@ -55,8 +55,6 @@
 {
 	PurpleSoundThemePrivate *priv;
 
-	(PURPLE_SOUND_THEME(instance))->priv = g_new0(PurpleSoundThemePrivate, 1);
-
 	priv = PURPLE_SOUND_THEME_GET_PRIVATE(instance);
 
 	priv->sound_files = g_hash_table_new_full(g_str_hash,
@@ -82,6 +80,8 @@
 
 	parent_class = g_type_class_peek_parent(klass);
 
+	g_type_class_add_private(klass, sizeof(PurpleSoundThemePrivate));
+
 	obj_class->finalize = purple_sound_theme_finalize;
 }
 
--- a/libpurple/sound-theme.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/sound-theme.h	Mon Oct 31 01:25:36 2011 +0000
@@ -51,7 +51,6 @@
 struct _PurpleSoundTheme
 {
 	PurpleTheme parent;
-	gpointer priv;
 };
 
 struct _PurpleSoundThemeClass
--- a/libpurple/sound.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/sound.h	Mon Oct 31 01:25:36 2011 +0000
@@ -38,7 +38,7 @@
  * A type of sound.
  */
 
-typedef enum _PurpleSoundEventID
+typedef enum
 {
 	PURPLE_SOUND_BUDDY_ARRIVE = 0, /**< Buddy signs on.                       */
 	PURPLE_SOUND_BUDDY_LEAVE,      /**< Buddy signs off.                      */
--- a/libpurple/sslconn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/sslconn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -185,15 +185,6 @@
 }
 
 PurpleSslConnection *
-purple_ssl_connect_fd(PurpleAccount *account, int fd,
-					PurpleSslInputFunction func,
-					PurpleSslErrorFunction error_func,
-                    void *data)
-{
-    return purple_ssl_connect_with_host_fd(account, fd, func, error_func, NULL, data);
-}
-
-PurpleSslConnection *
 purple_ssl_connect_with_host_fd(PurpleAccount *account, int fd,
                       PurpleSslInputFunction func,
                       PurpleSslErrorFunction error_func,
--- a/libpurple/sslconn.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/sslconn.h	Mon Oct 31 01:25:36 2011 +0000
@@ -203,7 +203,6 @@
  * @param data       User-defined data.
  *
  * @return The SSL connection handle.
- * @since 2.6.0
  */
 PurpleSslConnection *purple_ssl_connect_with_ssl_cn(PurpleAccount *account, const char *host,
 									int port, PurpleSslInputFunction func,
@@ -211,26 +210,6 @@
 									const char *ssl_host,
 									void *data);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_SSLCONN_C_)
-/**
- * Makes a SSL connection using an already open file descriptor.
- *
- * @deprecated Use purple_ssl_connect_with_host_fd() instead.
- *
- * @param account    The account making the connection.
- * @param fd         The file descriptor.
- * @param func       The SSL input handler function.
- * @param error_func The SSL error handler function.
- * @param data       User-defined data.
- *
- * @return The SSL connection handle.
- */
-PurpleSslConnection *purple_ssl_connect_fd(PurpleAccount *account, int fd,
-									   PurpleSslInputFunction func,
-									   PurpleSslErrorFunction error_func,
- 									   void *data);
-#endif
-
 /**
  * Makes a SSL connection using an already open file descriptor.
  *
@@ -242,8 +221,6 @@
  * @param data       User-defined data.
  *
  * @return The SSL connection handle.
- *
- * @since 2.2.0
  */
 PurpleSslConnection *purple_ssl_connect_with_host_fd(PurpleAccount *account, int fd,
                                            PurpleSslInputFunction func,
@@ -298,8 +275,6 @@
  *
  * @return The peer certificate chain, in the order of certificate, issuer,
  *         issuer's issuer, etc. @a NULL if no certificates have been provided,
- *
- * @since 2.2.0
  */
 GList * purple_ssl_get_peer_certificates(PurpleSslConnection *gsc);
 
--- a/libpurple/status.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/status.c	Mon Oct 31 01:25:36 2011 +0000
@@ -44,7 +44,6 @@
 
 	char *id;
 	char *name;
-	char *primary_attr_id;
 
 	gboolean saveable;
 	gboolean user_settable;
@@ -258,6 +257,42 @@
 			user_settable, FALSE);
 }
 
+static void
+status_type_add_attr(PurpleStatusType *status_type, const char *id,
+		const char *name, PurpleValue *value)
+{
+	PurpleStatusAttr *attr;
+
+	g_return_if_fail(status_type != NULL);
+	g_return_if_fail(id          != NULL);
+	g_return_if_fail(name        != NULL);
+	g_return_if_fail(value       != NULL);
+
+	attr = purple_status_attr_new(id, name, value);
+
+	status_type->attrs = g_list_append(status_type->attrs, attr);
+}
+
+static void
+status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args)
+{
+	const char *id, *name;
+	PurpleValue *value;
+
+	g_return_if_fail(status_type != NULL);
+
+	while ((id = va_arg(args, const char *)) != NULL)
+	{
+		name = va_arg(args, const char *);
+		g_return_if_fail(name != NULL);
+
+		value = va_arg(args, PurpleValue *);
+		g_return_if_fail(value != NULL);
+
+		status_type_add_attr(status_type, id, name, value);
+	}
+}
+
 PurpleStatusType *
 purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive,
 		const char *id, const char *name,
@@ -278,10 +313,10 @@
 			user_settable, independent);
 
 	/* Add the first attribute */
-	purple_status_type_add_attr(status_type, attr_id, attr_name, attr_value);
+	status_type_add_attr(status_type, attr_id, attr_name, attr_value);
 
 	va_start(args, attr_value);
-	purple_status_type_add_attrs_vargs(status_type, args);
+	status_type_add_attrs_vargs(status_type, args);
 	va_end(args);
 
 	return status_type;
@@ -294,7 +329,6 @@
 
 	g_free(status_type->id);
 	g_free(status_type->name);
-	g_free(status_type->primary_attr_id);
 
 	g_list_foreach(status_type->attrs, (GFunc)purple_status_attr_destroy, NULL);
 	g_list_free(status_type->attrs);
@@ -303,70 +337,6 @@
 	g_free(status_type);
 }
 
-void
-purple_status_type_set_primary_attr(PurpleStatusType *status_type, const char *id)
-{
-	g_return_if_fail(status_type != NULL);
-
-	g_free(status_type->primary_attr_id);
-	status_type->primary_attr_id = g_strdup(id);
-}
-
-void
-purple_status_type_add_attr(PurpleStatusType *status_type, const char *id,
-		const char *name, PurpleValue *value)
-{
-	PurpleStatusAttr *attr;
-
-	g_return_if_fail(status_type != NULL);
-	g_return_if_fail(id          != NULL);
-	g_return_if_fail(name        != NULL);
-	g_return_if_fail(value       != NULL);
-
-	attr = purple_status_attr_new(id, name, value);
-
-	status_type->attrs = g_list_append(status_type->attrs, attr);
-}
-
-void
-purple_status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args)
-{
-	const char *id, *name;
-	PurpleValue *value;
-
-	g_return_if_fail(status_type != NULL);
-
-	while ((id = va_arg(args, const char *)) != NULL)
-	{
-		name = va_arg(args, const char *);
-		g_return_if_fail(name != NULL);
-
-		value = va_arg(args, PurpleValue *);
-		g_return_if_fail(value != NULL);
-
-		purple_status_type_add_attr(status_type, id, name, value);
-	}
-}
-
-void
-purple_status_type_add_attrs(PurpleStatusType *status_type, const char *id,
-		const char *name, PurpleValue *value, ...)
-{
-	va_list args;
-
-	g_return_if_fail(status_type != NULL);
-	g_return_if_fail(id          != NULL);
-	g_return_if_fail(name        != NULL);
-	g_return_if_fail(value       != NULL);
-
-	/* Add the first attribute */
-	purple_status_type_add_attr(status_type, id, name, value);
-
-	va_start(args, value);
-	purple_status_type_add_attrs_vargs(status_type, args);
-	va_end(args);
-}
-
 PurpleStatusPrimitive
 purple_status_type_get_primitive(const PurpleStatusType *status_type)
 {
@@ -435,14 +405,6 @@
 	return (primitive == PURPLE_STATUS_AVAILABLE);
 }
 
-const char *
-purple_status_type_get_primary_attr(const PurpleStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->primary_attr_id;
-}
-
 PurpleStatusAttr *
 purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id)
 {
@@ -706,6 +668,68 @@
 	notify_status_update(presence, old_status, status);
 }
 
+static void
+status_set_attr_boolean(PurpleStatus *status, const char *id,
+		gboolean value)
+{
+	PurpleValue *attr_value;
+
+	g_return_if_fail(status != NULL);
+	g_return_if_fail(id     != NULL);
+
+	/* Make sure this attribute exists and is the correct type. */
+	attr_value = purple_status_get_attr_value(status, id);
+	g_return_if_fail(attr_value != NULL);
+	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN);
+
+	purple_value_set_boolean(attr_value, value);
+}
+
+static void
+status_set_attr_int(PurpleStatus *status, const char *id, int value)
+{
+	PurpleValue *attr_value;
+
+	g_return_if_fail(status != NULL);
+	g_return_if_fail(id     != NULL);
+
+	/* Make sure this attribute exists and is the correct type. */
+	attr_value = purple_status_get_attr_value(status, id);
+	g_return_if_fail(attr_value != NULL);
+	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT);
+
+	purple_value_set_int(attr_value, value);
+}
+
+static void
+status_set_attr_string(PurpleStatus *status, const char *id,
+		const char *value)
+{
+	PurpleValue *attr_value;
+
+	g_return_if_fail(status != NULL);
+	g_return_if_fail(id     != NULL);
+
+	/* Make sure this attribute exists and is the correct type. */
+	attr_value = purple_status_get_attr_value(status, id);
+	/* This used to be g_return_if_fail, but it's failing a LOT, so
+	 * let's generate a log error for now. */
+	/* g_return_if_fail(attr_value != NULL); */
+	if (attr_value == NULL) {
+		purple_debug_error("status",
+				 "Attempted to set status attribute '%s' for "
+				 "status '%s', which is not legal.  Fix "
+                                 "this!\n", id,
+				 purple_status_type_get_name(purple_status_get_type(status)));
+		return;
+	}
+	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING);
+
+	/* XXX: Check if the value has actually changed. If it has, and the status
+	 * is active, should this trigger 'status_has_changed'? */
+	purple_value_set_string(attr_value, value);
+}
+
 void
 purple_status_set_active(PurpleStatus *status, gboolean active)
 {
@@ -782,31 +806,31 @@
 
 		specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id);
 
-		if (value->type == PURPLE_TYPE_STRING)
+		if (purple_value_get_type(value) == PURPLE_TYPE_STRING)
 		{
 			const gchar *string_data = l->data;
 			l = l->next;
-			if (purple_strequal(string_data, value->data.string_data))
+			if (purple_strequal(string_data, purple_value_get_string(value)))
 				continue;
-			purple_status_set_attr_string(status, id, string_data);
+			status_set_attr_string(status, id, string_data);
 			changed = TRUE;
 		}
-		else if (value->type == PURPLE_TYPE_INT)
+		else if (purple_value_get_type(value) == PURPLE_TYPE_INT)
 		{
 			int int_data = GPOINTER_TO_INT(l->data);
 			l = l->next;
-			if (int_data == value->data.int_data)
+			if (int_data == purple_value_get_int(value))
 				continue;
-			purple_status_set_attr_int(status, id, int_data);
+			status_set_attr_int(status, id, int_data);
 			changed = TRUE;
 		}
-		else if (value->type == PURPLE_TYPE_BOOLEAN)
+		else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN)
 		{
 			gboolean boolean_data = GPOINTER_TO_INT(l->data);
 			l = l->next;
-			if (boolean_data == value->data.boolean_data)
+			if (boolean_data == purple_value_get_boolean(value))
 				continue;
-			purple_status_set_attr_boolean(status, id, boolean_data);
+			status_set_attr_boolean(status, id, boolean_data);
 			changed = TRUE;
 		}
 		else
@@ -828,7 +852,7 @@
 		if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) {
 			PurpleValue *default_value;
 			default_value = purple_status_attr_get_value(attr);
-			if (default_value->type == PURPLE_TYPE_STRING) {
+			if (purple_value_get_type(default_value) == PURPLE_TYPE_STRING) {
 				const char *cur = purple_status_get_attr_string(status, attr->id);
 				const char *def = purple_value_get_string(default_value);
 				if ((cur == NULL && def == NULL)
@@ -837,21 +861,21 @@
 					continue;
 				}
 
-				purple_status_set_attr_string(status, attr->id, def);
-			} else if (default_value->type == PURPLE_TYPE_INT) {
+				status_set_attr_string(status, attr->id, def);
+			} else if (purple_value_get_type(default_value) == PURPLE_TYPE_INT) {
 				int cur = purple_status_get_attr_int(status, attr->id);
 				int def = purple_value_get_int(default_value);
 				if (cur == def)
 					continue;
 
-				purple_status_set_attr_int(status, attr->id, def);
-			} else if (default_value->type == PURPLE_TYPE_BOOLEAN) {
+				status_set_attr_int(status, attr->id, def);
+			} else if (purple_value_get_type(default_value) == PURPLE_TYPE_BOOLEAN) {
 				gboolean cur = purple_status_get_attr_boolean(status, attr->id);
 				gboolean def = purple_value_get_boolean(default_value);
 				if (cur == def)
 					continue;
 
-				purple_status_set_attr_boolean(status, attr->id, def);
+				status_set_attr_boolean(status, attr->id, def);
 			}
 			changed = TRUE;
 		}
@@ -863,68 +887,6 @@
 	status_has_changed(status);
 }
 
-void
-purple_status_set_attr_boolean(PurpleStatus *status, const char *id,
-		gboolean value)
-{
-	PurpleValue *attr_value;
-
-	g_return_if_fail(status != NULL);
-	g_return_if_fail(id     != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = purple_status_get_attr_value(status, id);
-	g_return_if_fail(attr_value != NULL);
-	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN);
-
-	purple_value_set_boolean(attr_value, value);
-}
-
-void
-purple_status_set_attr_int(PurpleStatus *status, const char *id, int value)
-{
-	PurpleValue *attr_value;
-
-	g_return_if_fail(status != NULL);
-	g_return_if_fail(id     != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = purple_status_get_attr_value(status, id);
-	g_return_if_fail(attr_value != NULL);
-	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT);
-
-	purple_value_set_int(attr_value, value);
-}
-
-void
-purple_status_set_attr_string(PurpleStatus *status, const char *id,
-		const char *value)
-{
-	PurpleValue *attr_value;
-
-	g_return_if_fail(status != NULL);
-	g_return_if_fail(id     != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = purple_status_get_attr_value(status, id);
-	/* This used to be g_return_if_fail, but it's failing a LOT, so
-	 * let's generate a log error for now. */
-	/* g_return_if_fail(attr_value != NULL); */
-	if (attr_value == NULL) {
-		purple_debug_error("status",
-				 "Attempted to set status attribute '%s' for "
-				 "status '%s', which is not legal.  Fix "
-                                 "this!\n", id,
-				 purple_status_type_get_name(purple_status_get_type(status)));
-		return;
-	}
-	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING);
-
-	/* XXX: Check if the value has actually changed. If it has, and the status
-	 * is active, should this trigger 'status_has_changed'? */
-	purple_value_set_string(attr_value, value);
-}
-
 PurpleStatusType *
 purple_status_get_type(const PurpleStatus *status)
 {
@@ -1137,7 +1099,7 @@
 
 	presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_CONV);
 	presence->u.chat.conv = conv;
-	/* presence->statuses = purple_prpl_get_statuses(conv->account, presence); ? */
+	/* presence->statuses = purple_prpl_get_statuses(purple_conversation_get_account(conv), presence); ? */
 
 	return presence;
 }
@@ -1186,30 +1148,6 @@
 }
 
 void
-purple_presence_add_status(PurplePresence *presence, PurpleStatus *status)
-{
-	g_return_if_fail(presence != NULL);
-	g_return_if_fail(status   != NULL);
-
-	presence->statuses = g_list_append(presence->statuses, status);
-
-	g_hash_table_insert(presence->status_table,
-	g_strdup(purple_status_get_id(status)), status);
-}
-
-void
-purple_presence_add_list(PurplePresence *presence, GList *source_list)
-{
-	GList *l;
-
-	g_return_if_fail(presence    != NULL);
-	g_return_if_fail(source_list != NULL);
-
-	for (l = source_list; l != NULL; l = l->next)
-		purple_presence_add_status(presence, (PurpleStatus *)l->data);
-}
-
-void
 purple_presence_set_status_active(PurplePresence *presence, const char *status_id,
 		gboolean active)
 {
--- a/libpurple/status.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/status.h	Mon Oct 31 01:25:36 2011 +0000
@@ -271,73 +271,6 @@
  */
 void purple_status_type_destroy(PurpleStatusType *status_type);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Sets a status type's primary attribute.
- *
- * The value for the primary attribute is used as the description for
- * the particular status type. An example is an away message. The message
- * would be the primary attribute.
- *
- * @param status_type The status type.
- * @param attr_id     The ID of the primary attribute.
- *
- * @deprecated This function isn't used and should be removed in 3.0.0.
- */
-void purple_status_type_set_primary_attr(PurpleStatusType *status_type,
-									   const char *attr_id);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Adds an attribute to a status type.
- *
- * @param status_type The status type to add the attribute to.
- * @param id          The ID of the attribute.
- * @param name        The name presented to the user.
- * @param value       The value type of this attribute.
- *
- * @deprecated This function isn't needed and should be removed in 3.0.0.
- *             Status type attributes should be set when the status type
- *             is created, in the call to purple_status_type_new_with_attrs.
- */
-void purple_status_type_add_attr(PurpleStatusType *status_type, const char *id,
-							   const char *name, PurpleValue *value);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Adds multiple attributes to a status type.
- *
- * @param status_type The status type to add the attribute to.
- * @param id          The ID of the first attribute.
- * @param name        The description of the first attribute.
- * @param value       The value type of the first attribute attribute.
- * @param ...         Additional attribute information.
- *
- * @deprecated This function isn't needed and should be removed in 3.0.0.
- *             Status type attributes should be set when the status type
- *             is created, in the call to purple_status_type_new_with_attrs.
- */
-void purple_status_type_add_attrs(PurpleStatusType *status_type, const char *id,
-								const char *name, PurpleValue *value, ...) G_GNUC_NULL_TERMINATED;
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Adds multiple attributes to a status type using a va_list.
- *
- * @param status_type The status type to add the attribute to.
- * @param args        The va_list of attributes.
- *
- * @deprecated This function isn't needed and should be removed in 3.0.0.
- *             Status type attributes should be set when the status type
- *             is created, in the call to purple_status_type_new_with_attrs.
- */
-void purple_status_type_add_attrs_vargs(PurpleStatusType *status_type,
-									  va_list args);
-#endif
-
 /**
  * Returns the primitive type of a status type.
  *
@@ -419,19 +352,6 @@
  */
 gboolean purple_status_type_is_available(const PurpleStatusType *status_type);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Returns a status type's primary attribute ID.
- *
- * @param type The status type.
- *
- * @return The primary attribute's ID.
- *
- * @deprecated This function isn't used and should be removed in 3.0.0.
- */
-const char *purple_status_type_get_primary_attr(const PurpleStatusType *type);
-#endif
-
 /**
  * Returns the attribute with the specified ID.
  *
@@ -582,51 +502,6 @@
 void purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
 											GList *attrs);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Sets the boolean value of an attribute in a status with the specified ID.
- *
- * @param status The status.
- * @param id     The attribute ID.
- * @param value  The boolean value.
- *
- * @deprecated This function is only used by status.c and should be made
- *             static in 3.0.0.
- */
-void purple_status_set_attr_boolean(PurpleStatus *status, const char *id,
-								  gboolean value);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Sets the integer value of an attribute in a status with the specified ID.
- *
- * @param status The status.
- * @param id     The attribute ID.
- * @param value  The integer value.
- *
- * @deprecated This function is only used by status.c and should be made
- *             static in 3.0.0.
- */
-void purple_status_set_attr_int(PurpleStatus *status, const char *id,
-							  int value);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Sets the string value of an attribute in a status with the specified ID.
- *
- * @param status The status.
- * @param id     The attribute ID.
- * @param value  The string value.
- *
- * @deprecated This function is only used by status.c and should be made
- *             static in 3.0.0.
- */
-void purple_status_set_attr_string(PurpleStatus *status, const char *id,
-								 const char *value);
-#endif
-
 /**
  * Returns the status's type.
  *
@@ -833,32 +708,6 @@
  */
 void purple_presence_destroy(PurplePresence *presence);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Adds a status to a presence.
- *
- * @param presence The presence.
- * @param status   The status to add.
- *
- * @deprecated This function is only used by purple_presence_add_list,
- *             and both should be removed in 3.0.0.
- */
-void purple_presence_add_status(PurplePresence *presence, PurpleStatus *status);
-#endif
-
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_)
-/**
- * Adds a list of statuses to the presence.
- *
- * @param presence    The presence.
- * @param source_list The source list of statuses to add, which is not
- *                    modified or freed by this function.
- *
- * @deprecated This function isn't used and should be removed in 3.0.0.
- */
-void purple_presence_add_list(PurplePresence *presence, GList *source_list);
-#endif
-
 /**
  * Sets the active state of a status in a presence.
  *
--- a/libpurple/stun.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/stun.c	Mon Oct 31 01:25:36 2011 +0000
@@ -338,7 +338,7 @@
 		return;
 	}
 
-	if (!purple_network_listen_range(12108, 12208, SOCK_DGRAM, hbn_listen_cb, hosts)) {
+	if (!purple_network_listen_range(12108, 12208, AF_UNSPEC, SOCK_DGRAM, TRUE, hbn_listen_cb, hosts)) {
 		while (hosts) {
 			hosts = g_slist_delete_link(hosts, hosts);
 			g_free(hosts->data);
@@ -365,7 +365,7 @@
 	purple_debug_info("stun", "got %d SRV responses, server: %s, port: %d\n",
 		results, servername, port);
 
-	purple_dnsquery_a_account(NULL, servername, port, hbn_cb, NULL);
+	purple_dnsquery_a(NULL, servername, port, hbn_cb, NULL);
 	g_free(resp);
 }
 
@@ -424,7 +424,7 @@
 	nattype.servername = g_strdup(servername);
 
 	callbacks = g_slist_append(callbacks, cb);
-	purple_srv_resolve_account(NULL, "stun", "udp", servername, do_test1,
+	purple_srv_resolve(NULL, "stun", "udp", servername, do_test1,
 		(gpointer) servername);
 
 	return &nattype;
--- a/libpurple/tests/test_xmlnode.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/tests/test_xmlnode.c	Mon Oct 31 01:25:36 2011 +0000
@@ -21,6 +21,101 @@
 }
 END_TEST
 
+#define check_doc_structure(x) { \
+	xmlnode *ping, *child1, *child2; \
+	fail_if(x == NULL, "Failed to parse document"); \
+	ping = xmlnode_get_child(x, "ping"); \
+	fail_if(ping == NULL, "Failed to find 'ping' child"); \
+	child1 = xmlnode_get_child(ping, "child1"); \
+	fail_if(child1 == NULL, "Failed to find 'child1'"); \
+	child2 = xmlnode_get_child(child1, "child2"); \
+	fail_if(child2 == NULL, "Failed to find 'child2'"); \
+	xmlnode_new_child(child2, "a"); \
+	\
+	assert_string_equal("jabber:client", xmlnode_get_namespace(x)); \
+	/* NOTE: xmlnode_get_namespace() returns the namespace of the element, not the
+	 * current default namespace.  See http://www.w3.org/TR/xml-names/#defaulting and
+	 * http://www.w3.org/TR/xml-names/#dt-defaultNS.
+	 */ \
+	assert_string_equal("urn:xmpp:ping", xmlnode_get_namespace(ping)); \
+	assert_string_equal("jabber:client", xmlnode_get_namespace(child1)); \
+	assert_string_equal("urn:xmpp:ping", xmlnode_get_namespace(child2)); \
+	/*
+	 * This fails (well, actually crashes [the ns is NULL]) unless
+	 * xmlnode_new_child() actually sets the element namespace.
+	assert_string_equal("jabber:client", xmlnode_get_namespace(xmlnode_get_child(child2, "a")));
+	 */ \
+	\
+	assert_string_equal("jabber:client", xmlnode_get_default_namespace(x)); \
+	assert_string_equal("jabber:client", xmlnode_get_default_namespace(ping)); \
+	assert_string_equal("jabber:client", xmlnode_get_default_namespace(child1)); \
+	assert_string_equal("jabber:client", xmlnode_get_default_namespace(child2)); \
+}
+
+START_TEST(test_xmlnode_prefixes)
+{
+	const char *xml_doc =
+		"<iq type='get' xmlns='jabber:client' xmlns:ping='urn:xmpp:ping'>"
+			"<ping:ping>"
+				"<child1>"
+					"<ping:child2></ping:child2>" /* xmlns='jabber:child' */
+				"</child1>"
+			"</ping:ping>"
+		"</iq>";
+	char *str;
+	xmlnode *xml, *reparsed;
+
+	xml = xmlnode_from_str(xml_doc, -1);
+	check_doc_structure(xml);
+
+	/* Check that xmlnode_from_str(xmlnode_to_str(xml, NULL), -1) is idempotent. */
+	str = xmlnode_to_str(xml, NULL);
+	fail_if(str == NULL, "Failed to serialize XMLnode");
+	reparsed = xmlnode_from_str(str, -1);
+	fail_if(reparsed == NULL, "Failed to reparse xml document");
+	check_doc_structure(reparsed);
+
+	g_free(str);
+	xmlnode_free(xml);
+	xmlnode_free(reparsed);
+}
+END_TEST
+
+
+START_TEST(test_strip_prefixes)
+{
+	const char *xml_doc = "<message xmlns='jabber:client' from='user@gmail.com/resource' to='another_user@darkrain42.org' type='chat' id='purple'>"
+		"<cha:active xmlns:cha='http://jabber.org/protocol/chatstates'/>"
+		"<body>xvlc xvlc</body>"
+		"<im:html xmlns:im='http://jabber.org/protocol/xhtml-im'>"
+			"<xht:body xmlns:xht='http://www.w3.org/1999/xhtml'>"
+				"<xht:p>xvlc <xht:span style='font-weight: bold;'>xvlc</xht:span></xht:p>"
+			"</xht:body>"
+		"</im:html>"
+	"</message>";
+	const char *out = "<message xmlns='jabber:client' from='user@gmail.com/resource' to='another_user@darkrain42.org' type='chat' id='purple'>"
+		"<active xmlns:cha='http://jabber.org/protocol/chatstates' xmlns='http://jabber.org/protocol/chatstates'/>"
+		"<body>xvlc xvlc</body>"
+		"<html xmlns:im='http://jabber.org/protocol/xhtml-im' xmlns='http://jabber.org/protocol/xhtml-im'>"
+			"<body xmlns:xht='http://www.w3.org/1999/xhtml' xmlns='http://www.w3.org/1999/xhtml'>"
+				"<p>xvlc <span style='font-weight: bold;'>xvlc</span></p>"
+			"</body>"
+		"</html>"
+	"</message>";
+	char *str;
+	xmlnode *xml;
+
+	xml = xmlnode_from_str(xml_doc, -1);
+	fail_if(xml == NULL, "Failed to parse XML");
+
+	xmlnode_strip_prefixes(xml);
+	str = xmlnode_to_str(xml, NULL);
+	assert_string_equal_free(out, str);
+
+	xmlnode_free(xml);
+}
+END_TEST
+
 Suite *
 xmlnode_suite(void)
 {
@@ -28,6 +123,9 @@
 
 	TCase *tc = tcase_create("xmlnode");
 	tcase_add_test(tc, test_xmlnode_billion_laughs_attack);
+	tcase_add_test(tc, test_xmlnode_prefixes);
+	tcase_add_test(tc, test_strip_prefixes);
+
 	suite_add_tcase(s, tc);
 
 	return s;
--- a/libpurple/theme-loader.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/theme-loader.c	Mon Oct 31 01:25:36 2011 +0000
@@ -24,7 +24,7 @@
 #include "theme-loader.h"
 
 #define PURPLE_THEME_LOADER_GET_PRIVATE(PurpleThemeLoader) \
-	((PurpleThemeLoaderPrivate *) ((PurpleThemeLoader)->priv))
+	(G_TYPE_INSTANCE_GET_PRIVATE((PurpleThemeLoader), PURPLE_TYPE_THEME_LOADER, PurpleThemeLoaderPrivate))
 
 void purple_theme_loader_set_type_string(PurpleThemeLoader *loader, const gchar *type);
 
@@ -86,21 +86,12 @@
 }
 
 static void
-purple_theme_loader_init(GTypeInstance *instance,
-			gpointer klass)
-{
-	PurpleThemeLoader *loader = PURPLE_THEME_LOADER(instance);
-	loader->priv = g_new0(PurpleThemeLoaderPrivate, 1);
-}
-
-static void
 purple_theme_loader_finalize(GObject *obj)
 {
 	PurpleThemeLoader *loader = PURPLE_THEME_LOADER(obj);
 	PurpleThemeLoaderPrivate *priv = PURPLE_THEME_LOADER_GET_PRIVATE(loader);
 
 	g_free(priv->type);
-	g_free(priv);
 
 	parent_class->finalize(obj);
 }
@@ -113,6 +104,8 @@
 
 	parent_class = g_type_class_peek_parent(klass);
 
+	g_type_class_add_private(klass, sizeof(PurpleThemeLoaderPrivate));
+
 	obj_class->get_property = purple_theme_loader_get_property;
 	obj_class->set_property = purple_theme_loader_set_property;
 	obj_class->finalize = purple_theme_loader_finalize;
@@ -139,7 +132,7 @@
 			NULL, /* class_data */
 			sizeof(PurpleThemeLoader),
 			0, /* n_preallocs */
-			purple_theme_loader_init, /* instance_init */
+			NULL, /* instance_init */
 			NULL, /* value table */
 		};
 		type = g_type_register_static(G_TYPE_OBJECT,
--- a/libpurple/theme-loader.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/theme-loader.h	Mon Oct 31 01:25:36 2011 +0000
@@ -50,7 +50,6 @@
 struct _PurpleThemeLoader
 {
 	GObject parent;
-	gpointer priv;
 };
 
 struct _PurpleThemeLoaderClass
--- a/libpurple/theme.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/theme.c	Mon Oct 31 01:25:36 2011 +0000
@@ -25,7 +25,7 @@
 #include "util.h"
 
 #define PURPLE_THEME_GET_PRIVATE(PurpleTheme) \
-	((PurpleThemePrivate *) ((PurpleTheme)->priv))
+	(G_TYPE_INSTANCE_GET_PRIVATE((PurpleTheme), PURPLE_TYPE_THEME, PurpleThemePrivate))
 
 void purple_theme_set_type_string(PurpleTheme *theme, const gchar *type);
 
@@ -129,14 +129,6 @@
 }
 
 static void
-purple_theme_init(GTypeInstance *instance,
-		gpointer klass)
-{
-	PurpleTheme *theme = PURPLE_THEME(instance);
-	theme->priv = g_new0(PurpleThemePrivate, 1);
-}
-
-static void
 purple_theme_finalize(GObject *obj)
 {
 	PurpleTheme *theme = PURPLE_THEME(obj);
@@ -160,6 +152,8 @@
 
 	parent_class = g_type_class_peek_parent(klass);
 
+	g_type_class_add_private(klass, sizeof(PurpleThemePrivate));
+
 	obj_class->get_property = purple_theme_get_property;
 	obj_class->set_property = purple_theme_set_property;
 	obj_class->finalize = purple_theme_finalize;
@@ -222,7 +216,7 @@
 			NULL, /* class_data */
 			sizeof(PurpleTheme),
 			0, /* n_preallocs */
-			purple_theme_init, /* instance_init */
+			NULL, /* instance_init */
 			NULL, /* value table */
 		};
 		type = g_type_register_static (G_TYPE_OBJECT,
--- a/libpurple/theme.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/theme.h	Mon Oct 31 01:25:36 2011 +0000
@@ -49,7 +49,6 @@
 struct _PurpleTheme
 {
 	GObject parent;
-	gpointer priv;
 };
 
 struct _PurpleThemeClass
--- a/libpurple/upnp.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/upnp.c	Mon Oct 31 01:25:36 2011 +0000
@@ -464,7 +464,7 @@
 	purple_timeout_remove(dd->tima);
 	dd->tima = 0;
 
-	purple_util_fetch_url_request_len(descriptionURL, TRUE, NULL, TRUE, httpRequest,
+	purple_util_fetch_url_request(NULL, descriptionURL, TRUE, NULL, TRUE, httpRequest,
 			TRUE, MAX_UPNP_DOWNLOAD, upnp_parse_description_cb, dd);
 
 	g_free(httpRequest);
@@ -730,7 +730,7 @@
 	g_free(pathOfControl);
 	g_free(soapMessage);
 
-	gfud = purple_util_fetch_url_request_len(control_info.control_url, FALSE, NULL, TRUE,
+	gfud = purple_util_fetch_url_request(NULL, control_info.control_url, FALSE, NULL, TRUE,
 				totalSendMessage, TRUE, MAX_UPNP_DOWNLOAD, cb, cb_data);
 
 	g_free(totalSendMessage);
@@ -744,7 +744,7 @@
 {
 	if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED
 			&& control_info.publicip
-			&& strlen(control_info.publicip) > 0)
+			&& *control_info.publicip)
 		return control_info.publicip;
 
 	/* Trigger another UPnP discovery if 5 minutes have elapsed since the
@@ -803,7 +803,7 @@
 {
 	if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED
 			&& control_info.internalip
-			&& strlen(control_info.internalip) > 0)
+			&& *control_info.internalip)
 		return control_info.internalip;
 
 	/* Trigger another UPnP discovery if 5 minutes have elapsed since the
--- a/libpurple/util.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/util.c	Mon Oct 31 01:25:36 2011 +0000
@@ -73,6 +73,14 @@
 	PurpleAccount *account;
 };
 
+struct _PurpleMenuAction
+{
+	char *label;
+	PurpleCallback callback;
+	gpointer data;
+	GList *children;
+};
+
 static char *custom_user_dir = NULL;
 static char *user_dir = NULL;
 
@@ -98,6 +106,62 @@
 	g_free(act);
 }
 
+char * purple_menu_action_get_label(const PurpleMenuAction *act)
+{
+	g_return_val_if_fail(act != NULL, NULL);
+
+	return act->label;
+}
+
+PurpleCallback purple_menu_action_get_callback(const PurpleMenuAction *act)
+{
+	g_return_val_if_fail(act != NULL, NULL);
+
+	return act->callback;
+}
+
+gpointer purple_menu_action_get_data(const PurpleMenuAction *act)
+{
+	g_return_val_if_fail(act != NULL, NULL);
+
+	return act->data;
+}
+
+GList* purple_menu_action_get_children(const PurpleMenuAction *act)
+{
+	g_return_val_if_fail(act != NULL, NULL);
+
+	return act->children;
+}
+
+void purple_menu_action_set_label(PurpleMenuAction *act, char *label)
+{
+	g_return_if_fail(act != NULL);
+
+	act-> label = label;
+}
+
+void purple_menu_action_set_callback(PurpleMenuAction *act, PurpleCallback callback)
+{
+	g_return_if_fail(act != NULL);
+
+	act->callback = callback;
+}
+
+void purple_menu_action_set_data(PurpleMenuAction *act, gpointer data)
+{
+	g_return_if_fail(act != NULL);
+
+	act->data = data;
+}
+
+void purple_menu_action_set_children(PurpleMenuAction *act, GList *children)
+{
+	g_return_if_fail(act != NULL);
+
+	act->children = children;
+}
+
 void
 purple_util_init(void)
 {
@@ -147,7 +211,7 @@
 
 	len = strlen(str);
 
-	g_return_val_if_fail(strlen(str) > 0, 0);
+	g_return_val_if_fail(*str, 0);
 	g_return_val_if_fail(len % 2 == 0,    0);
 
 	data = g_malloc(len / 2);
@@ -612,7 +676,7 @@
 	}
 	else
 	{
-		purple_strlcpy(buf, utf8);
+		g_strlcpy(buf, utf8, sizeof(buf));
 		g_free(utf8);
 	}
 
@@ -1321,7 +1385,7 @@
 				g_string_append_len(dest, p, q - p);
 		}
 
-		purple_notify_user_info_add_pair(user_info, display_name, dest->str);
+		purple_notify_user_info_add_pair_html(user_info, display_name, dest->str);
 		g_string_free(dest, TRUE);
 
 		return TRUE;
@@ -2267,7 +2331,7 @@
 					url_buf = g_string_free(gurl_buf, FALSE);
 
 					/* strip off trailing periods */
-					if (strlen(url_buf) > 0) {
+					if (*url_buf) {
 						for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--)
 							*d = '\0';
 					}
@@ -3267,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;
 
@@ -3282,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++;
 		}
@@ -4103,30 +4167,7 @@
 }
 
 PurpleUtilFetchUrlData *
-purple_util_fetch_url_request(const char *url, gboolean full,
-		const char *user_agent, gboolean http11,
-		const char *request, gboolean include_headers,
-		PurpleUtilFetchUrlCallback callback, void *user_data)
-{
-	return purple_util_fetch_url_request_len_with_account(NULL, url, full,
-					     user_agent, http11,
-					     request, include_headers, -1,
-					     callback, user_data);
-}
-
-PurpleUtilFetchUrlData *
-purple_util_fetch_url_request_len(const char *url, gboolean full,
-		const char *user_agent, gboolean http11,
-		const char *request, gboolean include_headers, gssize max_len,
-		PurpleUtilFetchUrlCallback callback, void *user_data)
-{
-	return purple_util_fetch_url_request_len_with_account(NULL, url, full,
-			user_agent, http11, request, include_headers, max_len, callback,
-			user_data);
-}
-
-PurpleUtilFetchUrlData *
-purple_util_fetch_url_request_len_with_account(PurpleAccount *account,
+purple_util_fetch_url_request(PurpleAccount *account,
 		const char *url, gboolean full,	const char *user_agent, gboolean http11,
 		const char *request, gboolean include_headers, gssize max_len,
 		PurpleUtilFetchUrlCallback callback, void *user_data)
@@ -4413,11 +4454,10 @@
 	return (double_colon && chunks < 8) || (!double_colon && chunks == 8);
 }
 
-/* TODO 3.0.0: Add ipv6 check, too */
 gboolean
 purple_ip_address_is_valid(const char *ip)
 {
-	return purple_ipv4_address_is_valid(ip);
+	return (purple_ipv4_address_is_valid(ip) || purple_ipv6_address_is_valid(ip));
 }
 
 /* Stolen from gnome_uri_list_extract_uris */
@@ -4943,18 +4983,6 @@
 	return buf;
 }
 
-const char *_purple_oscar_convert(const char *act, const char *protocol)
-{
-	if (act && purple_strequal(protocol, "prpl-oscar")) {
-		int i;
-		for (i = 0; act[i] != '\0'; i++)
-			if (!isdigit(act[i]))
-				return "prpl-aim";
-		return "prpl-icq";
-	}
-	return protocol;
-}
-
 void purple_restore_default_signal_handlers(void)
 {
 #ifndef _WIN32
--- a/libpurple/util.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/util.h	Mon Oct 31 01:25:36 2011 +0000
@@ -36,9 +36,20 @@
   * the request.
   */
 typedef struct _PurpleUtilFetchUrlData PurpleUtilFetchUrlData;
-/** @copydoc _PurpleMenuAction */
+
+/**
+ * A generic structure that contains information about an "action."  One
+ * place this is is used is by PRPLs to tell the core the list of available
+ * right-click actions for a buddy list row.
+ */
 typedef struct _PurpleMenuAction PurpleMenuAction;
-/** @copydoc _PurpleKeyValuePair */
+
+/**
+ * A key-value pair.
+ *
+ * This is used by, among other things, purple_gtk_combo* functions to pass in a
+ * list of key-value pairs so it can display a user-friendly value.
+ */
 typedef struct _PurpleKeyValuePair PurpleKeyValuePair;
 
 #include "account.h"
@@ -51,22 +62,8 @@
 extern "C" {
 #endif
 
-struct _PurpleMenuAction
-{
-	char *label;
-	PurpleCallback callback;
-	gpointer data;
-	GList *children;
-};
-
 typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len);
 
-/**
- * A key-value pair.
- *
- * This is used by, among other things, purple_gtk_combo* functions to pass in a
- * list of key-value pairs so it can display a user-friendly value.
- */
 struct _PurpleKeyValuePair
 {
 	gchar *key;
@@ -96,12 +93,79 @@
 void purple_menu_action_free(PurpleMenuAction *act);
 
 /**
+ * Returns the label of the PurpleMenuAction.
+ *
+ * @param act	The PurpleMenuAction.
+ *
+ * @return The label string.
+ */
+char * purple_menu_action_get_label(const PurpleMenuAction *act);
+
+/**
+ * Returns the callback of the PurpleMenuAction.
+ *
+ * @param act	The PurpleMenuAction.
+ *
+ * @return The callback function.
+ */
+PurpleCallback purple_menu_action_get_callback(const PurpleMenuAction *act);
+
+/**
+ * Returns the data stored in the PurpleMenuAction.
+ *
+ * @param act	The PurpleMenuAction.
+ *
+ * @return The data.
+ */
+gpointer purple_menu_action_get_data(const PurpleMenuAction *act);
+
+/**
+ * Returns the children of the PurpleMenuAction.
+ *
+ * @param act	The PurpleMenuAction.
+ *
+ * @return The  GList of children.
+ */
+GList* purple_menu_action_get_children(const PurpleMenuAction *act);
+
+/**
+ * Set the label to the PurpleMenuAction.
+ *
+ * @param act   The menu action.
+ * @param label The label for the menu action.
+ */
+void purple_menu_action_set_label(PurpleMenuAction *act, char *label);
+
+/**
+ * Set the callback that will be used by the PurpleMenuAction.
+ *
+ * @param act        The menu action.
+ * @param callback   The callback.
+ */
+void purple_menu_action_set_callback(PurpleMenuAction *act, PurpleCallback callback);
+
+/**
+ * Set the label to the PurpleMenuAction.
+ *
+ * @param act   The menu action.
+ * @param data  The data used by this PurpleMenuAction
+ */
+void purple_menu_action_set_data(PurpleMenuAction *act, gpointer data);
+
+/**
+ * Set the children of the PurpleMenuAction.
+ *
+ * @param act       The menu action.
+ * @param children  The PurpleMenuAtion children
+ */
+void purple_menu_action_set_children(PurpleMenuAction *act, GList *children);
+
+/**
  * Set the appropriate presence values for the currently playing song.
  *
  * @param title     The title of the song, @c NULL to unset the value.
  * @param artist    The artist of the song, can be @c NULL.
  * @param album     The album of the song, can be @c NULL.
- * @since 2.4.0
  */
 void purple_util_set_current_song(const char *title, const char *artist,
 		const char *album);
@@ -115,7 +179,6 @@
  * @param unused    Currently unused, must be @c NULL.
  *
  * @return   The formatted string. The caller must g_free the returned string.
- * @since 2.4.0
  */
 char * purple_util_format_song_info(const char *title, const char *artist,
 		const char *album, gpointer unused);
@@ -127,15 +190,11 @@
 
 /**
  * Initializes the utility subsystem.
- *
- * @since 2.3.0
  */
 void purple_util_init(void);
 
 /**
  * Uninitializes the util subsystem.
- *
- * @since 2.3.0
  */
 void purple_util_uninit(void);
 
@@ -429,8 +488,6 @@
  * This is exactly the same as g_markup_escape_text(), except that it
  * does not change ' to &apos; because &apos; is not a valid HTML 4 entity,
  * and is displayed literally in IE7.
- *
- * @since 2.6.0
  */
 gchar *purple_markup_escape_text(const gchar *text, gssize length);
 
@@ -531,7 +588,6 @@
  *         this string when finished with it.
  *
  * @see purple_unescape_html()
- * @since 2.7.0
  */
 char *purple_unescape_text(const char *text);
 
@@ -624,8 +680,6 @@
  * @param html  The HTML text.
  *
  * @return  TRUE if the text contains RTL text, FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean purple_markup_is_rtl(const char *html);
 
@@ -826,7 +880,6 @@
  *
  * @return The address family of the socket (AF_INET, AF_INET6, etc) or -1
  *         on error.
- * @since 2.7.0
  */
 int purple_socket_get_family(int fd);
 
@@ -838,7 +891,6 @@
  *
  * @param fd The socket file descriptor
  * @return TRUE if a socket can speak IPv4.
- * @since 2.7.0
  */
 gboolean purple_socket_speaks_ipv4(int fd);
 
@@ -860,8 +912,6 @@
  * @param right A string to compare with left
  *
  * @return @c TRUE if the strings are the same, else @c FALSE.
- *
- * @since 2.6.0
  */
 gboolean purple_strequal(const gchar *left, const gchar *right);
 
@@ -1041,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.
@@ -1117,75 +1167,17 @@
  *                   partial URL.
  * @param user_agent The user agent field to use, or NULL.
  * @param http11     TRUE if HTTP/1.1 should be used to download the file.
- * @param cb         The callback function.
- * @param data       The user data to pass to the callback function.
- */
-#define purple_util_fetch_url(url, full, user_agent, http11, cb, data) \
-	purple_util_fetch_url_request(url, full, user_agent, http11, NULL, \
-		FALSE, cb, data);
-
-/**
- * Fetches the data from a URL, and passes it to a callback function.
- *
- * @param url        The URL.
- * @param full       TRUE if this is the full URL, or FALSE if it's a
- *                   partial URL.
- * @param user_agent The user agent field to use, or NULL.
- * @param http11     TRUE if HTTP/1.1 should be used to download the file.
  * @param max_len    The maximum number of bytes to retrieve (-1 for unlimited)
  * @param cb         The callback function.
  * @param data       The user data to pass to the callback function.
- * @deprecated       In 3.0.0, we'll rename this to "purple_util_fetch_url" and get rid of the old one
  */
-#define purple_util_fetch_url_len(url, full, user_agent, http11, max_len, cb, data) \
-	purple_util_fetch_url_request_len(url, full, user_agent, http11, NULL, \
+#define purple_util_fetch_url(url, full, user_agent, http11, max_len, cb, data) \
+	purple_util_fetch_url_request(NULL, url, full, user_agent, http11, NULL, \
 		FALSE, max_len, cb, data);
 
 /**
  * Fetches the data from a URL, and passes it to a callback function.
  *
- * @param url        The URL.
- * @param full       TRUE if this is the full URL, or FALSE if it's a
- *                   partial URL.
- * @param user_agent The user agent field to use, or NULL.
- * @param http11     TRUE if HTTP/1.1 should be used to download the file.
- * @param request    A HTTP request to send to the server instead of the
- *                   standard GET
- * @param include_headers
- *                   If TRUE, include the HTTP headers in the response.
- * @param callback   The callback function.
- * @param data       The user data to pass to the callback function.
- */
-PurpleUtilFetchUrlData *purple_util_fetch_url_request(const gchar *url,
-		gboolean full, const gchar *user_agent, gboolean http11,
-		const gchar *request, gboolean include_headers,
-		PurpleUtilFetchUrlCallback callback, gpointer data);
-
-/**
- * Fetches the data from a URL, and passes it to a callback function.
- *
- * @param url        The URL.
- * @param full       TRUE if this is the full URL, or FALSE if it's a
- *                   partial URL.
- * @param user_agent The user agent field to use, or NULL.
- * @param http11     TRUE if HTTP/1.1 should be used to download the file.
- * @param request    A HTTP request to send to the server instead of the
- *                   standard GET
- * @param include_headers
- *                   If TRUE, include the HTTP headers in the response.
- * @param max_len    The maximum number of bytes to retrieve (-1 for unlimited)
- * @param callback   The callback function.
- * @param data       The user data to pass to the callback function.
- * @deprecated       In 3.0.0, this will go away.
- */
-PurpleUtilFetchUrlData *purple_util_fetch_url_request_len(const gchar *url,
-		gboolean full, const gchar *user_agent, gboolean http11,
-		const gchar *request, gboolean include_headers, gssize max_len,
-		PurpleUtilFetchUrlCallback callback, gpointer data);
-
-/**
- * Fetches the data from a URL, and passes it to a callback function.
- *
  * @param account    The account for which the request is needed, or NULL.
  * @param url        The URL.
  * @param full       TRUE if this is the full URL, or FALSE if it's a
@@ -1199,9 +1191,8 @@
  * @param max_len    The maximum number of bytes to retrieve (-1 for unlimited)
  * @param callback   The callback function.
  * @param data       The user data to pass to the callback function.
- * @deprecated       In 3.0.0, we'll rename this to "purple_util_fetch_url_request" and get rid of the old one
  */
-PurpleUtilFetchUrlData *purple_util_fetch_url_request_len_with_account(
+PurpleUtilFetchUrlData *purple_util_fetch_url_request(
 		PurpleAccount *account, const gchar *url,
 		gboolean full, const gchar *user_agent, gboolean http11,
 		const gchar *request, gboolean include_headers, gssize max_len,
@@ -1247,14 +1238,15 @@
 gboolean purple_email_is_valid(const char *address);
 
 /**
- * Checks if the given IP address is a syntactically valid IPv4 address.
+ * Checks if the given IP address is a syntactically valid IPv4 or
+ * IPv6 address.
+ * If you specifically want to check for an IPv4 address use
+ * purple_ipv4_address_is_valid(), or for an IPv6 address use
+ * purple_ipv6_address_is_valid().
  *
  * @param ip The IP address to validate.
  *
  * @return True if the IP address is syntactically correct.
- * @deprecated This function will be replaced with one that validates
- *             as either IPv4 or IPv6 in 3.0.0. If you don't want this,
- *             behavior, use one of the more specific functions.
  */
 gboolean purple_ip_address_is_valid(const char *ip);
 
@@ -1264,7 +1256,6 @@
  * @param ip The IP address to validate.
  *
  * @return True if the IP address is syntactically correct.
- * @since 2.6.0
  */
 gboolean purple_ipv4_address_is_valid(const char *ip);
 
@@ -1274,7 +1265,6 @@
  * @param ip The IP address to validate.
  *
  * @return True if the IP address is syntactically correct.
- * @since 2.6.0
  */
 gboolean purple_ipv6_address_is_valid(const char *ip);
 
@@ -1342,7 +1332,6 @@
  * @param str A valid UTF-8 string.
  *
  * @return A newly allocated UTF-8 string without the unprintable characters.
- * @since 2.6.0
  */
 gchar *purple_utf8_strip_unprintables(const gchar *str);
 
@@ -1354,7 +1343,6 @@
  * @param errnum The error code.
  *
  * @return The UTF-8 error message.
- * @since 2.4.0
  */
 G_CONST_RETURN gchar *purple_gai_strerror(gint errnum);
 
@@ -1450,16 +1438,6 @@
 const char *purple_escape_filename(const char *str);
 
 /**
- * This is added temporarily to assist the split of oscar into aim and icq.
- * This should not be used by plugins.
- *
- * @deprecated This function should not be used in new code and should be
- *             removed in 3.0.0.  The aim/icq prpl split happened a long
- *             time ago, and we don't need to keep migrating old data.
- */
-const char *_purple_oscar_convert(const char *act, const char *protocol);
-
-/**
  * Restore default signal handlers for signals which might reasonably have
  * handlers. This should be called by a fork()'d child process, since child processes
  * inherit the handlers of the parent.
@@ -1478,7 +1456,6 @@
  * Returns a type 4 (random) UUID
  *
  * @return A UUID, caller is responsible for freeing it
- * @since 2.7.0
  */
 gchar *purple_uuid_random(void);
 
--- a/libpurple/value.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/value.c	Mon Oct 31 01:25:36 2011 +0000
@@ -29,6 +29,44 @@
 
 #define OUTGOING_FLAG 0x01
 
+/**
+ * A wrapper for a type, subtype, and specific type of value.
+ */
+struct _PurpleValue
+{
+	PurpleType type;
+	unsigned short flags;
+
+	union
+	{
+		char char_data;
+		unsigned char uchar_data;
+		gboolean boolean_data;
+		short short_data;
+		unsigned short ushort_data;
+		int int_data;
+		unsigned int uint_data;
+		long long_data;
+		unsigned long ulong_data;
+		gint64 int64_data;
+		guint64 uint64_data;
+		char *string_data;
+		void *object_data;
+		void *pointer_data;
+		int enum_data;
+		void *boxed_data;
+
+	} data;
+
+	union
+	{
+		unsigned int subtype;
+		char *specific_type;
+
+	} u;
+
+};
+
 PurpleValue *
 purple_value_new(PurpleType type, ...)
 {
--- a/libpurple/value.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/value.h	Mon Oct 31 01:25:36 2011 +0000
@@ -86,40 +86,7 @@
 /**
  * A wrapper for a type, subtype, and specific type of value.
  */
-typedef struct
-{
-	PurpleType type;
-	unsigned short flags;
-
-	union
-	{
-		char char_data;
-		unsigned char uchar_data;
-		gboolean boolean_data;
-		short short_data;
-		unsigned short ushort_data;
-		int int_data;
-		unsigned int uint_data;
-		long long_data;
-		unsigned long ulong_data;
-		gint64 int64_data;
-		guint64 uint64_data;
-		char *string_data;
-		void *object_data;
-		void *pointer_data;
-		int enum_data;
-		void *boxed_data;
-
-	} data;
-
-	union
-	{
-		unsigned int subtype;
-		char *specific_type;
-
-	} u;
-
-} PurpleValue;
+typedef struct _PurpleValue PurpleValue;
 
 #ifdef __cplusplus
 extern "C" {
--- a/libpurple/version.h.in	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/version.h.in	Mon Oct 31 01:25:36 2011 +0000
@@ -56,8 +56,6 @@
  * The major version of the running libpurple.  Contrast with
  * #PURPLE_MAJOR_VERSION, which expands at compile time to the major version of
  * libpurple being compiled against.
- *
- * @since 2.4.0
  */
 extern const guint purple_major_version;
 
@@ -65,8 +63,6 @@
  * The minor version of the running libpurple.  Contrast with
  * #PURPLE_MINOR_VERSION, which expands at compile time to the minor version of
  * libpurple being compiled against.
- *
- * @since 2.4.0
  */
 extern const guint purple_minor_version;
 
@@ -75,8 +71,6 @@
  * The micro version of the running libpurple.  Contrast with
  * #PURPLE_MICRO_VERSION, which expands at compile time to the micro version of
  * libpurple being compiled against.
- *
- * @since 2.4.0
  */
 extern const guint purple_micro_version;
 
--- a/libpurple/whiteboard.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/whiteboard.c	Mon Oct 31 01:25:36 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
  *****************************************************************************/
@@ -90,6 +107,34 @@
 	g_free(wb);
 }
 
+PurpleAccount *purple_whiteboard_get_account(const PurpleWhiteboard *wb)
+{
+	g_return_val_if_fail(wb != NULL, NULL);
+
+	return wb->account;
+}
+
+const char *purple_whiteboard_get_who(const PurpleWhiteboard *wb)
+{
+	g_return_val_if_fail(wb != NULL, NULL);
+
+	return wb->who;	
+}
+
+void purple_whiteboard_set_state(PurpleWhiteboard *wb, int state)
+{
+	g_return_if_fail(wb != NULL);
+
+	wb->state = state;
+}
+
+int purple_whiteboard_get_state(const PurpleWhiteboard *wb)
+{
+	g_return_val_if_fail(wb != NULL, -1);
+
+	return wb->state;
+}
+
 void purple_whiteboard_start(PurpleWhiteboard *wb)
 {
 	/* Create frontend for whiteboard */
@@ -206,3 +251,44 @@
 		whiteboard_ui_ops->set_brush(wb, size, color);
 }
 
+GList *purple_whiteboard_get_draw_list(const PurpleWhiteboard *wb)
+{
+	g_return_val_if_fail(wb != NULL, NULL);
+
+	return wb->draw_list;
+}
+
+void purple_whiteboard_set_draw_list(PurpleWhiteboard *wb, GList* draw_list)
+{
+	g_return_if_fail(wb != NULL);
+
+	wb->draw_list = draw_list;
+}
+
+void purple_whiteboard_set_protocol_data(PurpleWhiteboard *wb, gpointer proto_data)
+{
+	g_return_if_fail(wb != NULL);
+
+	wb->proto_data = proto_data;
+}
+
+gpointer purple_whiteboard_get_protocol_data(const PurpleWhiteboard *wb)
+{
+	g_return_val_if_fail(wb != NULL, NULL);
+
+	return wb->proto_data;
+}
+
+void purple_whiteboard_set_ui_data(PurpleWhiteboard *wb, gpointer ui_data)
+{
+	g_return_if_fail(wb != NULL);
+
+	wb->ui_data = ui_data;
+}
+
+gpointer purple_whiteboard_get_ui_data(const PurpleWhiteboard *wb)
+{
+	g_return_val_if_fail(wb != NULL, NULL);
+
+	return wb->ui_data;
+}
--- a/libpurple/whiteboard.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/whiteboard.h	Mon Oct 31 01:25:36 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
@@ -135,6 +122,41 @@
 void purple_whiteboard_destroy(PurpleWhiteboard *wb);
 
 /**
+ * Returns the whiteboard's account.
+ *
+ * @param wb		The whiteboard.
+ *
+ * @return The whiteboard's account.
+ */
+PurpleAccount *purple_whiteboard_get_account(const PurpleWhiteboard *wb);
+
+/**
+ * Return who you're drawing with.
+ *
+ * @param wb		The whiteboard
+ *
+ * @return Who you're drawing with.
+ */
+const char *purple_whiteboard_get_who(const PurpleWhiteboard *wb);
+
+/**
+ * Set the state of the whiteboard.
+ *
+ * @param wb		The whiteboard.
+ * @param state		The state
+ */
+void purple_whiteboard_set_state(PurpleWhiteboard *wb, int state);
+
+/**
+ * Return the state of the whiteboard.
+ *
+ * @param wb		The whiteboard.
+ *
+ * @return The state of the whiteboard.
+ */
+int purple_whiteboard_get_state(const PurpleWhiteboard *wb);
+
+/**
  * Starts a whiteboard
  *
  * @param wb The whiteboard.
@@ -253,6 +275,59 @@
  */
 void purple_whiteboard_set_brush(PurpleWhiteboard *wb, int size, int color);
 
+/**
+ * Return the drawing list.
+ *
+ * @param wb			The whiteboard.
+ *
+ * @return The drawing list
+ */
+GList *purple_whiteboard_get_draw_list(const PurpleWhiteboard *wb);
+
+/**
+ * Set the drawing list.
+ *
+ * @param wb			The whiteboard
+ * @param draw_list		The drawing list.
+ */
+void purple_whiteboard_set_draw_list(PurpleWhiteboard *wb, GList* draw_list);
+
+/**
+ * Sets the protocol data for a whiteboard.
+ *
+ * @param wb			The whiteboard.
+ * @param proto_data	The protocol data to set for the whiteboard.
+ */
+void purple_whiteboard_set_protocol_data(PurpleWhiteboard *wb, gpointer proto_data);
+
+/**
+ * Gets the protocol data for a whiteboard.
+ *
+ * @param wb			The whiteboard.
+ *
+ * @return The protocol data for the whiteboard.
+ */
+gpointer purple_whiteboard_get_protocol_data(const PurpleWhiteboard *wb);
+
+/**
+ * Set the UI data associated with this whiteboard.
+ *
+ * @param wb			The whiteboard.
+ * @param ui_data		A pointer to associate with this whiteboard.
+ */
+void purple_whiteboard_set_ui_data(PurpleWhiteboard *wb, gpointer ui_data);
+
+/**
+ * Get the UI data associated with this whiteboard.
+ *
+ * @param wb			The whiteboard..
+ *
+ * @return The UI data associated with this whiteboard.  This is a
+ *         convenience field provided to the UIs--it is not
+ *         used by the libpurple core.
+ */
+gpointer purple_whiteboard_get_ui_data(const PurpleWhiteboard *wb);
+
 /*@}*/
 
 #ifdef __cplusplus
--- a/libpurple/win32/libc_interface.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/win32/libc_interface.c	Mon Oct 31 01:25:36 2011 +0000
@@ -467,12 +467,6 @@
 	return res;
 }
 
-/* stdio.h */
-
-int wpurple_rename (const char *oldname, const char *newname) {
-	return g_rename(oldname, newname);
-}
-
 /* time.h */
 
 struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) {
@@ -1047,15 +1041,3 @@
 	purple_debug_warning("wpurple", "could not find a match for Windows timezone \"%s\"\n", tzname);
 	return "";
 }
-
-int wpurple_g_access (const gchar *filename, int mode);
-/**
- * @deprecated - remove for 3.0.0
- */
-int
-wpurple_g_access (const gchar *filename, int mode)
-{
-	return g_access(filename, mode);
-}
-
-
--- a/libpurple/win32/libc_interface.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/win32/libc_interface.h	Mon Oct 31 01:25:36 2011 +0000
@@ -135,7 +135,7 @@
 #define vsnprintf _vsnprintf
 
 #define rename( oldname, newname ) \
-wpurple_rename( oldname, newname )
+g_rename( oldname, newname )
 
 /* sys/stat.h */
 #define fchmod(a,b)
--- a/libpurple/win32/libc_internal.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/win32/libc_internal.h	Mon Oct 31 01:25:36 2011 +0000
@@ -141,9 +141,6 @@
 int wpurple_gethostname(char *name, size_t size);
 
 
-/* stdio.h */
-int wpurple_rename(const char *oldname, const char *newname);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
--- a/libpurple/xmlnode.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/xmlnode.c	Mon Oct 31 01:25:36 2011 +0000
@@ -78,6 +78,19 @@
 	node = new_node(name, XMLNODE_TYPE_TAG);
 
 	xmlnode_insert_child(parent, node);
+#if 0
+	/* This would give xmlnodes more appropriate namespacing
+	 * when creating them.  Otherwise, unless an explicit namespace
+	 * is set, xmlnode_get_namespace() will return NULL, when
+	 * there may be a default namespace.
+	 *
+	 * I'm unconvinced that it's useful, and concerned it may break things.
+	 *
+	 * _insert_child would need the same thing, probably (assuming
+	 * xmlns->node == NULL)
+	 */
+	xmlnode_set_namespace(node, xmlnode_get_default_namespace(node))
+#endif
 
 	return node;
 }
@@ -191,18 +204,6 @@
 }
 
 void
-xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value)
-{
-	xmlnode_set_attrib_full(node, attr, xmlns, NULL, value);
-}
-
-void
-xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value)
-{
-	xmlnode_set_attrib_full(node, attr, NULL, prefix, value);
-}
-
-void
 xmlnode_set_attrib_full(xmlnode *node, const char *attr, const char *xmlns, const char *prefix, const char *value)
 {
 	xmlnode *attrib_node;
@@ -261,19 +262,53 @@
 
 void xmlnode_set_namespace(xmlnode *node, const char *xmlns)
 {
+	char *tmp;
 	g_return_if_fail(node != NULL);
 
-	g_free(node->xmlns);
+	tmp = node->xmlns;
 	node->xmlns = g_strdup(xmlns);
+
+	if (node->namespace_map) {
+		g_hash_table_insert(node->namespace_map,
+			g_strdup(""), g_strdup(xmlns));
+	}
+
+	g_free(tmp);
 }
 
-const char *xmlnode_get_namespace(xmlnode *node)
+const char *xmlnode_get_namespace(const xmlnode *node)
 {
 	g_return_val_if_fail(node != NULL, NULL);
 
 	return node->xmlns;
 }
 
+const char *xmlnode_get_default_namespace(const xmlnode *node)
+{
+	const xmlnode *current_node;
+	const char *ns = NULL;
+
+	g_return_val_if_fail(node != NULL, NULL);
+
+	current_node = node;
+	while (current_node) {
+		/* If this node does *not* have a prefix, node->xmlns is the default
+		 * namespace.  Otherwise, it's the prefix namespace.
+		 */
+		if (!current_node->prefix && current_node->xmlns) {
+			return current_node->xmlns;
+		} else if (current_node->namespace_map) {
+			ns = g_hash_table_lookup(current_node->namespace_map, "");
+			if (ns && *ns)
+				return ns;
+		}
+
+		current_node = current_node->parent;
+	}
+
+	return ns;
+}
+
 void xmlnode_set_prefix(xmlnode *node, const char *prefix)
 {
 	g_return_if_fail(node != NULL);
@@ -288,6 +323,53 @@
 	return node->prefix;
 }
 
+const char *xmlnode_get_prefix_namespace(const xmlnode *node, const char *prefix)
+{
+	const xmlnode *current_node;
+
+	g_return_val_if_fail(node != NULL, NULL);
+	g_return_val_if_fail(prefix != NULL, xmlnode_get_default_namespace(node));
+
+	current_node = node;
+	while (current_node) {
+		if (current_node->prefix && g_str_equal(prefix, current_node->prefix) &&
+				current_node->xmlns) {
+			return current_node->xmlns;
+		} else if (current_node->namespace_map) {
+			const char *ns = g_hash_table_lookup(current_node->namespace_map, prefix);
+			if (ns && *ns) {
+				return ns;
+			}
+		}
+
+		current_node = current_node->parent;
+	}
+
+	return NULL;
+}
+
+void xmlnode_strip_prefixes(xmlnode *node)
+{
+	xmlnode *child;
+	const char *prefix;
+
+	g_return_if_fail(node != NULL);
+
+	for (child = node->child; child; child = child->next) {
+		if (child->type == XMLNODE_TYPE_TAG)
+			xmlnode_strip_prefixes(child);
+	}
+
+	prefix = xmlnode_get_prefix(node);
+	if (prefix) {
+		const char *ns = xmlnode_get_prefix_namespace(node, prefix);
+		xmlnode_set_namespace(node, ns);
+		xmlnode_set_prefix(node, NULL);
+	} else {
+		xmlnode_set_namespace(node, xmlnode_get_default_namespace(node));
+	}
+}
+
 xmlnode *xmlnode_get_parent(const xmlnode *child)
 {
 	g_return_val_if_fail(child != NULL, NULL);
@@ -455,12 +537,22 @@
 	if (node->namespace_map) {
 		g_hash_table_foreach(node->namespace_map,
 			(GHFunc)xmlnode_to_str_foreach_append_ns, text);
-	} else if (node->xmlns) {
-		if(!node->parent || !purple_strequal(node->xmlns, node->parent->xmlns))
+	} else {
+		/* Figure out if this node has a different default namespace from parent */
+		const char *xmlns = NULL;
+		const char *parent_xmlns = NULL;
+		if (!prefix)
+			xmlns = node->xmlns;
+
+		if (!xmlns)
+			xmlns = xmlnode_get_default_namespace(node);
+		if (node->parent)
+			parent_xmlns = xmlnode_get_default_namespace(node->parent);
+		if (!purple_strequal(xmlns, parent_xmlns))
 		{
-			char *xmlns = g_markup_escape_text(node->xmlns, -1);
-			g_string_append_printf(text, " xmlns='%s'", xmlns);
-			g_free(xmlns);
+			char *escaped_xmlns = g_markup_escape_text(xmlns, -1);
+			g_string_append_printf(text, " xmlns='%s'", escaped_xmlns);
+			g_free(escaped_xmlns);
 		}
 	}
 	for(c = node->child; c; c = c->next)
--- a/libpurple/xmlnode.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/libpurple/xmlnode.h	Mon Oct 31 01:25:36 2011 +0000
@@ -35,7 +35,7 @@
 /**
  * The valid types for an xmlnode
  */
-typedef enum _XMLNodeType
+typedef enum
 {
 	XMLNODE_TYPE_TAG,		/**< Just a tag */
 	XMLNODE_TYPE_ATTRIB,		/**< Has attributes */
@@ -157,42 +157,14 @@
  */
 void xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value);
 
-#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_XMLNODE_C_)
-/**
- * Sets a prefixed attribute for a node
- *
- * @param node   The node to set an attribute for.
- * @param attr   The name of the attribute to set
- * @param prefix The prefix of the attribute to ste
- * @param value  The value of the attribute
- *
- * @deprecated Use xmlnode_set_attrib_full instead.
- */
-void xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value);
-
-/**
- * Sets a namespaced attribute for a node
- *
- * @param node  The node to set an attribute for.
- * @param attr  The name of the attribute to set
- * @param xmlns The namespace of the attribute to ste
- * @param value The value of the attribute
- *
- * @deprecated Use xmlnode_set_attrib_full instead.
- */
-void xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value);
-#endif /* PURPLE_DISABLE_DEPRECATED */
-
 /**
  * Sets a namespaced attribute for a node
  *
  * @param node   The node to set an attribute for.
  * @param attr   The name of the attribute to set
- * @param xmlns  The namespace of the attribute to ste
- * @param prefix The prefix of the attribute to ste
+ * @param xmlns  The namespace of the attribute to set
+ * @param prefix The prefix of the attribute to set
  * @param value  The value of the attribute
- *
- * @since 2.6.0
  */
 void xmlnode_set_attrib_full(xmlnode *node, const char *attr, const char *xmlns,
 	const char *prefix, const char *value);
@@ -249,7 +221,37 @@
  * @param node The node to get the namepsace from
  * @return The namespace of this node
  */
-const char *xmlnode_get_namespace(xmlnode *node);
+const char *xmlnode_get_namespace(const xmlnode *node);
+
+/**
+ * Returns the current default namespace.  The default
+ * namespace is the current namespace which applies to child
+ * elements which are unprefixed and which do not contain their
+ * own namespace.
+ *
+ * For example, given:
+ * \verbatim
+ * <iq type='get' xmlns='jabber:client' xmlns:ns1='http://example.org/ns1'>
+ *     <ns1:element><child1/></ns1:element>
+ * </iq>
+ * \endverbatim
+ *
+ * The default namespace of all nodes (including 'child1') is "jabber:client",
+ * though the namespace for 'element' is "http://example.org/ns1".
+ *
+ * @param node The node for which to return the default namespace
+ * @return The default namespace of this node
+ */
+const char *xmlnode_get_default_namespace(const xmlnode *node);
+
+/**
+ * Returns the defined namespace for a prefix.
+ *
+ * @param node The node from which to start the search.
+ * @param prefix The prefix for which to return the associated namespace.
+ * @return The namespace for this prefix.
+ */
+const char *xmlnode_get_prefix_namespace(const xmlnode *node, const char *prefix);
 
 /**
  * Sets the prefix of a node
@@ -268,13 +270,24 @@
 const char *xmlnode_get_prefix(const xmlnode *node);
 
 /**
+ * Remove all element prefixes from an xmlnode tree.  The prefix's
+ * namespace is transformed into the default namespace for an element.
+ *
+ * Note that this will not necessarily remove all prefixes in use
+ * (prefixed attributes may still exist), and that this usage may
+ * break some applications (SOAP / XPath apparently often rely on
+ * the prefixes having the same name.
+ *
+ * @param node The node from which to strip prefixes
+ */
+void xmlnode_strip_prefixes(xmlnode *node);
+
+/**
  * Gets the parent node.
  *
  * @param child The child node.
  *
  * @return The parent or NULL.
- *
- * @since 2.6.0
  */
 xmlnode *xmlnode_get_parent(const xmlnode *child);
 
@@ -343,8 +356,6 @@
  * 			the category for debugging.
  *
  * @return The new node or NULL if an error occurred.
- *
- * @since 2.6.0
  */
 xmlnode *xmlnode_from_file(const char *dir, const char *filename,
 			   const char *description, const char *process);
@@ -354,3 +365,4 @@
 #endif
 
 #endif /* _PURPLE_XMLNODE_H_ */
+
--- a/pidgin/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/Makefile.am	Mon Oct 31 01:25:36 2011 +0000
@@ -3,8 +3,8 @@
 		getopt.h \
 		getopt1.c \
 		Makefile.mingw \
-		pidgin.pc.in \
-		pidgin-uninstalled.pc.in \
+		pidgin-3.pc.in \
+		pidgin-3-uninstalled.pc.in \
 		win32/MinimizeToTray.h \
 		win32/MinimizeToTray.c \
 		win32/pidgin_dll_rc.rc.in \
@@ -32,9 +32,9 @@
 if ENABLE_GTK
 
 pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = pidgin.pc
+pkgconfig_DATA = pidgin-3.pc
 
-SUBDIRS = pixmaps plugins
+SUBDIRS = pixmaps plugins themes
 
 bin_PROGRAMS = pidgin
 
@@ -48,11 +48,12 @@
 	gtkcertmgr.c \
 	gtkconn.c \
 	gtkconv.c \
+	gtkconv-theme.c \
+	gtkconv-theme-loader.c \
 	gtkdebug.c \
 	gtkdialogs.c \
 	gtkdnd-hints.c \
 	gtkdocklet.c \
-	gtkdocklet-gtk.c \
 	gtkeventloop.c \
 	gtkft.c \
 	gtkicon-theme.c \
@@ -84,9 +85,11 @@
 	gtkstatusbox.c \
 	gtkthemes.c \
 	gtkutils.c \
+	gtkwebview.c \
 	gtkwhiteboard.c \
 	minidialog.c \
-	pidgintooltip.c
+	pidgintooltip.c \
+	smileyparser.c
 
 pidgin_headers = \
 	gtkaccount.h \
@@ -98,6 +101,8 @@
 	gtkconn.h \
 	gtkconv.h \
 	gtkconvwin.h \
+	gtkconv-theme.h \
+	gtkconv-theme-loader.h \
 	gtkdebug.h \
 	gtkdialogs.h \
 	gtkdnd-hints.h \
@@ -107,7 +112,6 @@
 	gtkicon-theme.h \
 	gtkicon-theme-loader.h \
 	gtkidle.h \
-	gtkgaim-compat.h \
 	gtkimhtml.h \
 	gtkimhtmltoolbar.h \
 	gtklog.h \
@@ -135,10 +139,12 @@
 	pidginstock.h \
 	gtkthemes.h \
 	gtkutils.h \
+	gtkwebview.h \
 	gtkwhiteboard.h \
 	minidialog.h \
 	pidgintooltip.h \
-	pidgin.h
+	pidgin.h \
+	smileyparser.h
 
 pidginincludedir=$(includedir)/pidgin
 pidgininclude_HEADERS = \
@@ -157,6 +163,7 @@
 	$(INTLLIBS) \
 	$(GTKSPELL_LIBS) \
 	$(LIBXML_LIBS) \
+	$(WEBKIT_LIBS) \
 	$(GTK_LIBS) \
 	$(top_builddir)/libpurple/libpurple.la
 
@@ -180,5 +187,7 @@
 	$(DBUS_CFLAGS) \
 	$(GTKSPELL_CFLAGS) \
 	$(LIBXML_CFLAGS) \
+	$(WEBKIT_CFLAGS) \
 	$(INTGG_CFLAGS)
 endif  # ENABLE_GTK
+
--- a/pidgin/Makefile.mingw	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/Makefile.mingw	Mon Oct 31 01:25:36 2011 +0000
@@ -58,6 +58,8 @@
 			gtkcertmgr.c \
 			gtkconn.c \
 			gtkconv.c \
+			gtkconv-theme.c \
+			gtkconv-theme-loader.c \
 			gtkdebug.c \
 			gtkdialogs.c \
 			gtkdnd-hints.c \
@@ -91,12 +93,12 @@
 			gtkstatusbox.c \
 			gtkthemes.c \
 			gtkutils.c \
+			gtkwebview.c \
 			gtkwhiteboard.c \
 			minidialog.c \
 			pidginstock.c \
 			pidgintooltip.c \
-			win32/MinimizeToTray.c \
-			win32/gtkdocklet-win32.c \
+			smileyparser.c \
 			win32/gtkwin32dep.c \
 			win32/untar.c \
 			win32/wspell.c
--- a/pidgin/gtkblist-theme.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkblist-theme.c	Mon Oct 31 01:25:36 2011 +0000
@@ -24,7 +24,7 @@
 #include "gtkblist-theme.h"
 
 #define PIDGIN_BLIST_THEME_GET_PRIVATE(Gobject) \
-	((PidginBlistThemePrivate *) ((PIDGIN_BLIST_THEME(Gobject))->priv))
+	(G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_BLIST_THEME, PidginBlistThemePrivate))
 
 /******************************************************************************
  * Structs
@@ -189,13 +189,6 @@
  *****************************************************************************/
 
 static void
-pidgin_blist_theme_init(GTypeInstance *instance,
-		gpointer klass)
-{
-	(PIDGIN_BLIST_THEME(instance))->priv = g_new0(PidginBlistThemePrivate, 1);
-}
-
-static void
 pidgin_blist_theme_get_property(GObject *obj, guint param_id, GValue *value,
 		GParamSpec *psec)
 {
@@ -349,8 +342,6 @@
 	pidgin_theme_font_free(priv->message_nick_said);
 	pidgin_theme_font_free(priv->status);
 
-	g_free(priv);
-
 	parent_class->finalize (obj);
 }
 
@@ -362,6 +353,8 @@
 
 	parent_class = g_type_class_peek_parent (klass);
 
+	g_type_class_add_private(klass, sizeof(PidginBlistThemePrivate));
+
 	obj_class->get_property = pidgin_blist_theme_get_property;
 	obj_class->set_property = pidgin_blist_theme_set_property;
 	obj_class->finalize = pidgin_blist_theme_finalize;
@@ -484,7 +477,7 @@
 			NULL, /* class_data */
 			sizeof(PidginBlistTheme),
 			0, /* n_preallocs */
-			pidgin_blist_theme_init, /* instance_init */
+			NULL, /* instance_init */
 			NULL, /* value table */
 		};
 		type = g_type_register_static (PURPLE_TYPE_THEME,
@@ -507,7 +500,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->bgcolor;
 }
@@ -519,7 +512,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), 1.0);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->opacity;
 }
@@ -531,7 +524,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->layout;
 }
@@ -543,7 +536,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->expanded_color;
 }
@@ -555,7 +548,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->expanded;
 }
@@ -567,7 +560,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->collapsed_color;
 }
@@ -579,7 +572,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->collapsed;
 }
@@ -591,7 +584,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->contact_color;
 }
@@ -603,7 +596,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->contact;
 }
@@ -615,7 +608,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->online;
 }
@@ -627,7 +620,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->away;
 }
@@ -639,7 +632,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->offline;
 }
@@ -651,7 +644,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->idle;
 }
@@ -663,7 +656,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->message;
 }
@@ -675,7 +668,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->message_nick_said;
 }
@@ -687,7 +680,7 @@
 
 	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	return priv->status;
 }
@@ -700,7 +693,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	if (priv->bgcolor)
 		gdk_color_free(priv->bgcolor);
@@ -714,7 +707,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme) || opacity < 0.0 || opacity > 1.0);
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	priv->opacity = opacity;
 }
@@ -726,7 +719,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	g_free(priv->layout);
 	priv->layout = g_memdup(layout, sizeof(PidginBlistLayout));
@@ -739,7 +732,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	if (priv->expanded_color)
 		gdk_color_free(priv->expanded_color);
@@ -753,7 +746,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->expanded);
 	priv->expanded = copy_font_and_color(pair);
@@ -766,7 +759,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	if (priv->collapsed_color)
 		gdk_color_free(priv->collapsed_color);
@@ -780,7 +773,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->collapsed);
 	priv->collapsed = copy_font_and_color(pair);
@@ -793,7 +786,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	if (priv->contact_color)
 		gdk_color_free(priv->contact_color);
@@ -807,7 +800,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->contact);
 	priv->contact = copy_font_and_color(pair);
@@ -820,7 +813,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->online);
 	priv->online = copy_font_and_color(pair);
@@ -833,7 +826,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->away);
 	priv->away = copy_font_and_color(pair);
@@ -846,7 +839,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->offline);
 	priv->offline = copy_font_and_color(pair);
@@ -859,7 +852,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->idle);
 	priv->idle = copy_font_and_color(pair);
@@ -872,7 +865,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->message);
 	priv->message = copy_font_and_color(pair);
@@ -885,7 +878,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->message_nick_said);
 	priv->message_nick_said = copy_font_and_color(pair);
@@ -898,7 +891,7 @@
 
 	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
 
-	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme);
 
 	pidgin_theme_font_free(priv->status);
 	priv->status = copy_font_and_color(pair);
--- a/pidgin/gtkblist-theme.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkblist-theme.h	Mon Oct 31 01:25:36 2011 +0000
@@ -51,7 +51,6 @@
 struct _PidginBlistTheme
 {
 	PurpleTheme parent;
-	gpointer priv;
 };
 
 struct _PidginBlistThemeClass
--- a/pidgin/gtkblist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkblist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -916,7 +916,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);
@@ -940,7 +940,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);
 }
@@ -1030,6 +1030,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;
@@ -1038,17 +1039,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)
 	{
@@ -1411,7 +1413,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;
@@ -1519,7 +1521,7 @@
 
 	if (prpl_info && prpl_info->send_file) {
 		if (!prpl_info->can_receive_file ||
-			prpl_info->can_receive_file(buddy->account->gc, 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,
@@ -1547,7 +1549,7 @@
 				NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
 	}
 
-	pidgin_append_blist_node_proto_menu(menu, buddy->account->gc, 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)
@@ -1600,7 +1602,7 @@
 			return FALSE;
 		}
 		if(buddy)
-			pidgin_retrieve_user_info(buddy->account->gc, 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:
@@ -1753,7 +1755,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, c->account->gc, node);
+	pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(c->account), node);
 	pidgin_append_blist_node_extended_menu(menu, node);
 
 	pidgin_separator(menu);
@@ -1838,13 +1840,13 @@
 
 				if(buddy == b)
 					continue;
-				if(!buddy->account->gc)
+				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),
@@ -1962,12 +1964,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(b->account->gc, b->name);
+			pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(b)), purple_buddy_get_name(b));
 		handled = TRUE;
 	}
 
@@ -2292,7 +2294,7 @@
 			buddy = (PurpleBuddy *)node;
 		}
 
-		gc = purple_account_get_connection(buddy->account);
+		gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
 		if (gc == NULL)
 		{
@@ -2301,7 +2303,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);
@@ -2311,13 +2313,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");
@@ -2600,7 +2602,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);
@@ -2673,8 +2675,8 @@
 		account = purple_buddy_get_account(buddy);
 	}
 
-	if(account && account->gc) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl);
+	if(account && purple_account_get_connection(account)) {
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
 	}
 
 #if 0
@@ -2700,7 +2702,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);
 		}
@@ -2870,7 +2872,7 @@
 	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;
 	}
@@ -3203,8 +3205,8 @@
 
 	gtknode = ((PurpleBlistNode*)buddy)->ui_data;
 
-	return (purple_account_is_connected(buddy->account) &&
-			(purple_presence_is_online(buddy->presence) ||
+	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")));
@@ -3382,7 +3384,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);
@@ -3398,7 +3400,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);
 				}
 			}
@@ -3433,9 +3435,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
@@ -3493,7 +3495,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");
@@ -3528,8 +3530,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();
@@ -3539,7 +3541,7 @@
 	g = purple_request_field_group_new(NULL);
 	f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
 
-	purple_request_field_list_add(f, _("None"), "");
+	purple_request_field_list_add_icon(f, _("None"), NULL, "");
 	if (current_mood == NULL)
 		purple_request_field_list_add_selected(f, _("None"));
 
@@ -3568,7 +3570,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);
@@ -3681,7 +3683,7 @@
 		connections = purple_connections_get_all();
 		if (connections && connections->next)
 		{
-			tmp = g_markup_escape_text(chat->account->username, -1);
+			tmp = g_markup_escape_text(purple_account_get_username(chat->account), -1);
 			g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
 			g_free(tmp);
 		}
@@ -3713,7 +3715,7 @@
 		}
 
 		if (prpl_info && prpl_info->chat_info != NULL)
-			cur = prpl_info->chat_info(chat->account->gc);
+			cur = prpl_info->chat_info(purple_account_get_connection(chat->account));
 		else
 			cur = NULL;
 
@@ -3764,7 +3766,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);
@@ -3774,22 +3776,19 @@
 		connections = purple_connections_get_all();
 		if (full && connections && connections->next)
 		{
-			tmp = g_markup_escape_text(purple_account_get_username(
-									   purple_buddy_get_account(b)), -1);
-			purple_notify_user_info_add_pair(user_info, _("Account"), tmp);
-			g_free(tmp);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Account"),
+					purple_account_get_username(purple_buddy_get_account(b)));
 		}
 
 		/* 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)
 		{
-			tmp = g_markup_escape_text(b->alias, -1);
-			purple_notify_user_info_add_pair(user_info, _("Buddy Alias"), tmp);
-			g_free(tmp);
+			purple_notify_user_info_add_pair_plaintext(user_info,
+					_("Buddy Alias"), purple_buddy_get_local_buddy_alias(b));
 		}
 
 		/* Nickname/Server Alias */
@@ -3797,11 +3796,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))
 		{
-			tmp = g_markup_escape_text(b->server_alias, -1);
-			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
-			g_free(tmp);
+			purple_notify_user_info_add_pair_plaintext(user_info,
+					_("Nickname"), purple_buddy_get_server_alias(b));
 		}
 
 		/* Logged In */
@@ -3817,7 +3815,7 @@
 				tmp = g_strdup(purple_date_format_long(localtime(&signon)));
 			} else
 				tmp = purple_str_seconds_to_string(time(NULL) - signon);
-			purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Logged In"), tmp);
 			g_free(tmp);
 		}
 
@@ -3828,7 +3826,7 @@
 			if (idle_secs > 0)
 			{
 				tmp = purple_str_seconds_to_string(time(NULL) - idle_secs);
-				purple_notify_user_info_add_pair(user_info, _("Idle"), tmp);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp);
 				g_free(tmp);
 			}
 		}
@@ -3863,7 +3861,7 @@
 			if (lastseen > 0)
 			{
 				tmp = purple_str_seconds_to_string(time(NULL) - lastseen);
-				purple_notify_user_info_add_pair(user_info, _("Last Seen"), tmp);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Last Seen"), tmp);
 				g_free(tmp);
 			}
 		}
@@ -3873,10 +3871,10 @@
 		/* FIXME: Why is this status special-cased by the core? --rlaager
 		 * FIXME: Alternatively, why not have the core do all of them? --rlaager */
 		if (!PURPLE_BUDDY_IS_ONLINE(b)) {
-			purple_notify_user_info_add_pair(user_info, _("Status"), _("Offline"));
-		}
-
-		if (purple_account_is_connected(b->account) &&
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Offline"));
+		}
+
+		if (purple_account_is_connected(purple_buddy_get_account(b)) &&
 				prpl_info && prpl_info->tooltip_text)
 		{
 			/* Additional text from the PRPL */
@@ -3884,12 +3882,12 @@
 		}
 
 		/* These are Easter Eggs.  Patches to remove them will be rejected. */
-		if (!g_ascii_strcasecmp(b->name, "robflynn"))
-			purple_notify_user_info_add_pair(user_info, _("Description"), _("Spooky"));
-		if (!g_ascii_strcasecmp(b->name, "seanegn"))
-			purple_notify_user_info_add_pair(user_info, _("Status"), _("Awesome"));
-		if (!g_ascii_strcasecmp(b->name, "chipx86"))
-			purple_notify_user_info_add_pair(user_info, _("Status"), _("Rockin'"));
+		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(purple_buddy_get_name(b), "seanegn"))
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Awesome"));
+		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");
 		g_string_append(str, tmp);
@@ -3904,24 +3902,21 @@
 		user_info = purple_notify_user_info_new();
 
 		count = purple_blist_get_group_online_count(group);
-
 		if (count != 0) {
 			/* Online buddies in group */
-			tmp = g_strdup_printf("%d", count);
-			purple_notify_user_info_add_pair(user_info,
-			                                 _("Online Buddies"),
-			                                 tmp);
-			g_free(tmp);
+			char tmp2[12];
+			sprintf(tmp2, "%d", count);
+			purple_notify_user_info_add_pair_plaintext(user_info,
+					_("Online Buddies"), tmp2);
 		}
 
 		count = purple_blist_get_group_size(group, FALSE);
 		if (count != 0) {
 			/* Total buddies (from online accounts) in group */
-			tmp = g_strdup_printf("%d", count);
-			purple_notify_user_info_add_pair(user_info,
-			                                 _("Total Buddies"),
-			                                 tmp);
-			g_free(tmp);
+			char tmp2[12];
+			sprintf(tmp2, "%d", count);
+			purple_notify_user_info_add_pair_html(user_info,
+					_("Total Buddies"), tmp2);
 		}
 
 		tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n");
@@ -3994,7 +3989,7 @@
 		if (((struct _pidgin_blist_node*)(node->parent->ui_data))->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;
@@ -4002,7 +3997,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);
 	}
@@ -4038,7 +4033,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;
 
@@ -4102,7 +4097,7 @@
 		PurplePlugin *prpl;
 
 		if(buddy)
-			account = buddy->account;
+			account = purple_buddy_get_account(buddy);
 		else
 			account = chat->account;
 
@@ -4237,12 +4232,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 && b->account->gc) {
+		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;
 
@@ -4597,6 +4592,7 @@
 conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type,
                         PidginBuddyList *gtkblist)
 {
+	PurpleAccount *account = purple_conversation_get_account(conv);
 	GList *convs = NULL;
 	GList *ims, *chats;
 	GList *l = NULL;
@@ -4604,8 +4600,8 @@
 	if (type != PURPLE_CONV_UPDATE_UNSEEN)
 		return;
 
-	if(conv->account != NULL && conv->name != NULL) {
-		PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name);
+	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);
 	}
@@ -4714,10 +4710,12 @@
 static void
 conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist)
 {
-	switch (conv->type) {
+	PurpleAccount *account = purple_conversation_get_account(conv);
+
+	switch (purple_conversation_get_type(conv)) {
 		case PURPLE_CONV_TYPE_IM:
 			{
-				GSList *buddies = purple_find_buddies(conv->account, conv->name);
+				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;
@@ -4738,7 +4736,7 @@
 			break;
 		case PURPLE_CONV_TYPE_CHAT:
 			{
-				PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name);
+				PurpleChat *chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
 				struct _pidgin_blist_node *ui;
 				if (!chat)
 					break;
@@ -4770,8 +4768,6 @@
 	PidginBuddyList *gtkblist;
 
 	gtkblist = g_new0(PidginBuddyList, 1);
-	gtkblist->connection_errors = g_hash_table_new_full(g_direct_hash,
-												g_direct_equal, NULL, g_free);
 	gtkblist->priv = g_new0(PidginBuddyListPrivate, 1);
 
 	blist->ui_data = gtkblist;
@@ -5085,7 +5081,6 @@
 generic_error_destroy_cb(GtkObject *dialog,
                          PurpleAccount *account)
 {
-	g_hash_table_remove(gtkblist->connection_errors, account);
 	/* If the error dialog is being destroyed in response to the
 	 * account-error-changed signal, we don't want to clear the current
 	 * error.
@@ -5356,12 +5351,6 @@
 	if (old == NULL && new == NULL)
 		return;
 
-	/* For backwards compatibility: */
-	if (new)
-		pidgin_blist_update_account_error_state(account, new->description);
-	else
-		pidgin_blist_update_account_error_state(account, NULL);
-
 	if (new != NULL)
 		pidgin_blist_select_notebook_page(gtkblist);
 
@@ -5427,18 +5416,6 @@
 	}
 }
 
-void
-pidgin_blist_update_account_error_state(PurpleAccount *account, const char *text)
-{
-	/* connection_errors isn't actually used anywhere; it's just kept in
-	 * sync with reality in case a plugin uses it.
-	 */
-	if (text == NULL)
-		g_hash_table_remove(gtkblist->connection_errors, account);
-	else
-		g_hash_table_insert(gtkblist->connection_errors, account, g_strdup(text));
-}
-
 static gboolean
 paint_headline_hbox  (GtkWidget      *widget,
 		      GdkEventExpose *event,
@@ -6318,7 +6295,7 @@
 		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;
 			}
@@ -6550,7 +6527,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);
@@ -6881,7 +6858,6 @@
 	if (gtkblist->drag_timeout)
 		g_source_remove(gtkblist->drag_timeout);
 
-	g_hash_table_destroy(gtkblist->connection_errors);
 	gtkblist->refresh_timer = 0;
 	gtkblist->timeout = 0;
 	gtkblist->drag_timeout = 0;
@@ -7037,7 +7013,7 @@
 			purple_blist_add_buddy(b, NULL, g, NULL);
 		}
 
-		purple_account_add_buddy_with_invite(account, b, invite);
+		purple_account_add_buddy(account, b, invite);
 
 		/* Offer to merge people with the same alias. */
 		if (whoalias != NULL && g != NULL)
@@ -7229,11 +7205,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;
 		}
@@ -7241,8 +7219,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;
 			}
@@ -7849,7 +7828,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)) {
@@ -7885,7 +7864,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 {
@@ -8107,14 +8086,14 @@
 		pidgin_separator(submenu);
 
 		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;
 		prpl_info = plugin ? PURPLE_PLUGIN_PROTOCOL_INFO(plugin) : NULL;
 
 		if (prpl_info &&
 		    (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) ||
 			 PURPLE_PLUGIN_HAS_ACTIONS(plugin))) {
 			if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) &&
-			    gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) {
+			    (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) {
 
 				if (purple_account_get_status(account, "mood")) {
 					menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood..."));
--- a/pidgin/gtkblist.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkblist.h	Mon Oct 31 01:25:36 2011 +0000
@@ -86,15 +86,6 @@
 	GtkWidget *menutray;            /**< The menu tray widget. */
 	GtkWidget *menutrayicon;        /**< The menu tray icon. */
 
-	/** Caches connection error messages; keys are #PurpleAccount and
-	 *  values are non-@c NULL <tt>const char *</tt>s containing localised
-	 *  error messages.  (If an account does not have an error, it will not
-	 *  appear in the table.)
-	 *  @deprecated in favour of purple_account_get_current_error(), which also
-	 *              gives you the #PurpleConnectionError value.
-	 */
-	GHashTable *connection_errors;
-
 	guint refresh_timer;            /**< The timer for refreshing every 30 seconds */
 
 	guint      timeout;              /**< The timeout for the tooltip. */
@@ -259,8 +250,6 @@
  * Sets the current theme for Pidgin to use
  *
  * @param theme	the new theme to use
- *
- * @since 2.6.0
  */
 void pidgin_blist_set_theme(PidginBlistTheme *theme);
 
@@ -268,8 +257,6 @@
  * Gets Pidgin's current buddy list theme
  *
  * @returns	the current theme
- *
- * @since 2.6.0
  */
 PidginBlistTheme *pidgin_blist_get_theme(void);
 
@@ -370,20 +357,6 @@
 void pidgin_append_blist_node_extended_menu(GtkWidget *menu, PurpleBlistNode *node);
 
 /**
- * Was used by the connection API to tell the blist if an account has a
- * connection error or no longer has a connection error, but the blist now does
- * this itself with the @ref account-error-changed signal.
- *
- * @param account The account that either has a connection error
- *        or no longer has a connection error.
- * @param message The connection error message, or NULL if this
- *        account is no longer in an error state.
- * @deprecated There was no good reason for code other than gtkconn to call
- *             this.
- */
-void pidgin_blist_update_account_error_state(PurpleAccount *account, const char *message);
-
-/**
  * Sets a headline notification
  *
  * This is currently used for mail notification, but could theoretically be used for anything.
@@ -405,8 +378,6 @@
  * @param selected  Whether this buddy is selected. If TRUE, the markup will not change the color.
  * @param aliased  TRUE to return the appropriate alias of this buddy, FALSE to return its username and status information
  * @return The markup for this buddy
- *
- * @since 2.1.0
  */
 gchar *pidgin_blist_get_name_markup(PurpleBuddy *buddy, gboolean selected, gboolean aliased);
 
@@ -418,15 +389,11 @@
  *
  * @param node The buddy list node to show a tooltip for
  * @param widget The widget to draw the tooltip on
- *
- * @since 2.1.0
  */
 void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget);
 
 /**
  * Destroys the current (if any) Buddy List tooltip
- *
- * @since 2.1.0
  */
 void pidgin_blist_tooltip_destroy(void);
 
--- a/pidgin/gtkcertmgr.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkcertmgr.c	Mon Oct 31 01:25:36 2011 +0000
@@ -333,6 +333,12 @@
 }
 
 static void
+tls_peers_mgmt_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
+{
+	tls_peers_mgmt_info_cb(NULL, NULL);
+}
+
+static void
 tls_peers_mgmt_delete_confirm_cb(gchar *id, gint choice)
 {
 	if (1 == choice) {
@@ -452,6 +458,9 @@
 	g_signal_connect(G_OBJECT(select), "changed",
 			 G_CALLBACK(tls_peers_mgmt_select_chg_cb), NULL);
 
+	g_signal_connect(G_OBJECT(listview), "row-activated",
+			 G_CALLBACK(tls_peers_mgmt_activated_cb), NULL);
+
 	gtk_box_pack_start(GTK_BOX(mgmt_widget), 
 			pidgin_make_scrollable(GTK_WIDGET(listview), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1),
 			TRUE, TRUE, /* Take up lots of space */
@@ -471,9 +480,8 @@
 	gtk_widget_show(bbox);
 
 	/* Import button */
-	/* TODO: This is the wrong stock button */
 	tpm_dat->importbutton = importbutton =
-		gtk_button_new_from_stock(GTK_STOCK_ADD);
+		gtk_button_new_from_stock(GTK_STOCK_OPEN);
 	gtk_box_pack_start(GTK_BOX(bbox), importbutton, FALSE, FALSE, 0);
 	gtk_widget_show(importbutton);
 	g_signal_connect(G_OBJECT(importbutton), "clicked",
@@ -481,9 +489,8 @@
 
 
 	/* Export button */
-	/* TODO: This is the wrong stock button */
 	tpm_dat->exportbutton = exportbutton =
-		gtk_button_new_from_stock(GTK_STOCK_SAVE);
+		gtk_button_new_from_stock(GTK_STOCK_SAVE_AS);
 	gtk_box_pack_start(GTK_BOX(bbox), exportbutton, FALSE, FALSE, 0);
 	gtk_widget_show(exportbutton);
 	g_signal_connect(G_OBJECT(exportbutton), "clicked",
--- a/pidgin/gtkconn.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkconn.c	Mon Oct 31 01:25:36 2011 +0000
@@ -136,9 +136,9 @@
 }
 
 static void
-pidgin_connection_report_disconnect_reason (PurpleConnection *gc,
-                                            PurpleConnectionError reason,
-                                            const char *text)
+pidgin_connection_report_disconnect(PurpleConnection *gc,
+                                    PurpleConnectionError reason,
+                                    const char *text)
 {
 	PurpleAccount *account = NULL;
 	PidginAutoRecon *info;
@@ -215,10 +215,9 @@
 	pidgin_connection_connected,
 	pidgin_connection_disconnected,
 	pidgin_connection_notice,
-	NULL, /* report_disconnect */
 	pidgin_connection_network_connected,
 	pidgin_connection_network_disconnected,
-	pidgin_connection_report_disconnect_reason,
+	pidgin_connection_report_disconnect,
 	NULL,
 	NULL,
 	NULL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkconv-theme-loader.c	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,280 @@
+/*
+ * PidginConvThemeLoader for 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 "pidgin.h"
+#include "gtkconv-theme-loader.h"
+#include "gtkconv-theme.h"
+
+#include "xmlnode.h"
+#include "debug.h"
+
+/*****************************************************************************
+ * Conversation Theme Builder
+ *****************************************************************************/
+
+static GHashTable *
+read_info_plist(xmlnode *plist)
+{
+	GHashTable *info;
+	xmlnode *key, *value;
+	gboolean fail = FALSE;
+
+	info = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+	for (key = xmlnode_get_child(plist, "dict/key");
+	     key;
+	     key = xmlnode_get_next_twin(key)) {
+		char *keyname;
+		GValue *val;
+
+		;
+		for (value = key->next; value && value->type != XMLNODE_TYPE_TAG; value = value->next)
+			;
+		if (!value) {
+			fail = TRUE;
+			break;
+		}
+
+		val = g_new0(GValue, 1);
+		if (g_str_equal(value->name, "string")) {
+			g_value_init(val, G_TYPE_STRING);
+			g_value_take_string(val, xmlnode_get_data_unescaped(value));
+
+		} else if (g_str_equal(value->name, "true")) {
+			g_value_init(val, G_TYPE_BOOLEAN);
+			g_value_set_boolean(val, TRUE);
+
+		} else if (g_str_equal(value->name, "false")) {
+			g_value_init(val, G_TYPE_BOOLEAN);
+			g_value_set_boolean(val, FALSE);
+
+		} else if (g_str_equal(value->name, "real")) {
+			char *temp = xmlnode_get_data_unescaped(value);
+			g_value_init(val, G_TYPE_FLOAT);
+			g_value_set_float(val, atof(temp));
+			g_free(temp);
+
+		} else if (g_str_equal(value->name, "integer")) {
+			char *temp = xmlnode_get_data_unescaped(value);
+			g_value_init(val, G_TYPE_INT);
+			g_value_set_int(val, atoi(temp));
+			g_free(temp);
+
+		} else {
+			/* NOTE: We don't support array, data, date, or dict as values,
+			   since they don't seem to be needed for styles. */
+			g_free(val);
+			fail = TRUE;
+			break;
+		}
+
+		keyname = xmlnode_get_data_unescaped(key);
+		g_hash_table_insert(info, keyname, val);
+	}
+
+	if (fail) {
+		g_hash_table_destroy(info);
+		info = NULL;
+	}
+
+	return info;
+}
+
+static PurpleTheme *
+pidgin_conv_loader_build(const gchar *dir)
+{
+	PidginConvTheme *theme = NULL;
+	char *contents;
+	xmlnode *plist;
+	GHashTable *info;
+	GValue *val;
+	int MessageViewVersion;
+	const char *CFBundleName;
+	const char *CFBundleIdentifier;
+	GDir *variants;
+	char *variant_dir;
+
+	g_return_val_if_fail(dir != NULL, NULL);
+
+	/* Load Info.plist for theme information */
+	contents = g_build_filename(dir, "Contents", NULL);
+	plist = xmlnode_from_file(contents, "Info.plist", "Info.plist", "gtkconv-theme-loader");
+	g_free(contents);
+	if (plist == NULL) {
+		purple_debug_error("gtkconv-theme-loader",
+		                   "Failed to load Contents/Info.plist in %s\n", dir);
+		return NULL;
+	}
+
+	info = read_info_plist(plist);
+	xmlnode_free(plist);
+	if (info == NULL) {
+		purple_debug_error("gtkconv-theme-loader",
+		                   "Failed to load Contents/Info.plist in %s\n", dir);
+		return NULL;
+	}
+
+	/* Check for required keys: CFBundleName */
+	val = g_hash_table_lookup(info, "CFBundleName");
+	if (!val || !G_VALUE_HOLDS_STRING(val)) {
+		purple_debug_error("gtkconv-theme-loader",
+		                   "%s/Contents/Info.plist missing required string key CFBundleName.\n",
+		                   dir);
+		g_hash_table_destroy(info);
+		return NULL;
+	}
+	CFBundleName = g_value_get_string(val);
+
+	/* Check for required keys: CFBundleIdentifier */
+	val = g_hash_table_lookup(info, "CFBundleIdentifier");
+	if (!val || !G_VALUE_HOLDS_STRING(val)) {
+		purple_debug_error("gtkconv-theme-loader",
+		                   "%s/Contents/Info.plist missing required string key CFBundleIdentifier.\n",
+		                   dir);
+		g_hash_table_destroy(info);
+		return NULL;
+	}
+	CFBundleIdentifier = g_value_get_string(val);
+
+	/* Check for required keys: MessageViewVersion */
+	val = g_hash_table_lookup(info, "MessageViewVersion");
+	if (!val || !G_VALUE_HOLDS_INT(val)) {
+		purple_debug_error("gtkconv-theme-loader",
+		                   "%s/Contents/Info.plist missing required integer key MessageViewVersion.\n",
+		                   dir);
+		g_hash_table_destroy(info);
+		return NULL;
+	}
+
+	MessageViewVersion = g_value_get_int(val);
+	if (MessageViewVersion < 3) {
+		purple_debug_error("gtkconv-theme-loader",
+		                   "%s is a legacy style (version %d) and will not be loaded.\n",
+		                   CFBundleName, MessageViewVersion);
+		g_hash_table_destroy(info);
+		return NULL;
+	}
+
+	theme = g_object_new(PIDGIN_TYPE_CONV_THEME,
+	                     "type", "conversation",
+	                     "name", CFBundleName,
+	                     "directory", dir,
+	                     "info", info, NULL);
+
+	/* Read list of variants */
+	variant_dir = g_build_filename(dir, "Contents", "Resources", "Variants", NULL);
+	variants = g_dir_open(variant_dir, 0, NULL);
+	g_free(variant_dir);
+
+	if (variants) {
+		char *prefname;
+		const char *default_variant = NULL;
+		const char *file;
+
+		/* Make sure prefs exist */
+		prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s",
+		                           CFBundleIdentifier);
+		purple_prefs_add_none(prefname);
+		g_free(prefname);
+
+		/* Try user-set variant */
+		prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s/variant",
+		                           CFBundleIdentifier);
+		if (purple_prefs_exists(prefname))
+			default_variant = purple_prefs_get_string(prefname);
+		g_free(prefname);
+
+		if (default_variant && *default_variant) {
+			pidgin_conversation_theme_set_variant(theme, default_variant);
+
+		} else {
+			/* Try theme default */
+			val = g_hash_table_lookup(info, "DefaultVariant");
+			if (val && G_VALUE_HOLDS_STRING(val)) {
+				default_variant = g_value_get_string(val);
+				if (default_variant && *default_variant)
+					pidgin_conversation_theme_set_variant(theme, default_variant);
+				else
+					default_variant = NULL;
+			} else
+				default_variant = NULL;
+		}
+
+		while ((file = g_dir_read_name(variants)) != NULL) {
+			const char *end = g_strrstr(file, ".css");
+			char *name;
+
+			if ((end == NULL) || (*(end + 4) != '\0'))
+				continue;
+
+			name = g_strndup(file, end - file);
+			pidgin_conversation_theme_add_variant(theme, name);
+
+			/* Set variant with first found */
+			if (!default_variant) {
+				pidgin_conversation_theme_set_variant(theme, name);
+				default_variant = name;
+			}
+		}
+
+		g_dir_close(variants);
+	}
+
+	return PURPLE_THEME(theme);
+}
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+
+static void
+pidgin_conv_theme_loader_class_init(PidginConvThemeLoaderClass *klass)
+{
+	PurpleThemeLoaderClass *loader_klass = PURPLE_THEME_LOADER_CLASS(klass);
+
+	loader_klass->purple_theme_loader_build = pidgin_conv_loader_build;
+}
+
+
+GType
+pidgin_conversation_theme_loader_get_type(void)
+{
+	static GType type = 0;
+	if (type == 0) {
+		static const GTypeInfo info = {
+			sizeof(PidginConvThemeLoaderClass),
+			NULL, /* base_init */
+			NULL, /* base_finalize */
+			(GClassInitFunc)pidgin_conv_theme_loader_class_init, /* class_init */
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (PidginConvThemeLoader),
+			0, /* n_preallocs */
+			NULL, /* instance_init */
+			NULL, /* value table */
+		};
+		type = g_type_register_static(PURPLE_TYPE_THEME_LOADER,
+				"PidginConvThemeLoader", &info, 0);
+	}
+	return type;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkconv-theme-loader.h	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,72 @@
+/**
+ * @file gtkconv-theme-loader.h  Pidgin Conversation Theme Loader Class API
+ */
+
+/* purple
+ *
+ * Purple 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
+ */
+
+#ifndef PIDGIN_CONV_THEME_LOADER_H
+#define PIDGIN_CONV_THEME_LOADER_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "theme-loader.h"
+
+/**
+ * A pidgin conversation theme loader. Extends PurpleThemeLoader (theme-loader.h)
+ * This is a class designed to build conversation themes
+ *
+ * PidginConvThemeLoader is a GObject.
+ */
+typedef struct _PidginConvThemeLoader       PidginConvThemeLoader;
+typedef struct _PidginConvThemeLoaderClass  PidginConvThemeLoaderClass;
+
+#define PIDGIN_TYPE_CONV_THEME_LOADER            (pidgin_conversation_theme_loader_get_type ())
+#define PIDGIN_CONV_THEME_LOADER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIDGIN_TYPE_CONV_THEME_LOADER, PidginConvThemeLoader))
+#define PIDGIN_CONV_THEME_LOADER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PIDGIN_TYPE_CONV_THEME_LOADER, PidginConvThemeLoaderClass))
+#define PIDGIN_IS_CONV_THEME_LOADER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIDGIN_TYPE_CONV_THEME_LOADER))
+#define PIDGIN_IS_CONV_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIDGIN_TYPE_CONV_THEME_LOADER))
+#define PIDGIN_CONV_THEME_LOADER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PIDGIN_TYPE_CONV_THEME_LOADER, PidginConvThemeLoaderClass))
+
+struct _PidginConvThemeLoader
+{
+	PurpleThemeLoader parent;
+};
+
+struct _PidginConvThemeLoaderClass
+{
+	PurpleThemeLoaderClass parent_class;
+};
+
+/**************************************************************************/
+/** @name Pidgin Conversation Theme-Loader API                            */
+/**************************************************************************/
+G_BEGIN_DECLS
+
+/**
+ * GObject foo.
+ * @internal.
+ */
+GType pidgin_conversation_theme_loader_get_type(void);
+
+G_END_DECLS
+#endif /* PIDGIN_CONV_THEME_LOADER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkconv-theme.c	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,746 @@
+/*
+ * Conversation Themes for 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 "gtkconv-theme.h"
+
+#include "conversation.h"
+#include "debug.h"
+#include "prefs.h"
+#include "xmlnode.h"
+
+#include "pidgin.h"
+#include "gtkconv.h"
+#include "gtkwebview.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define PIDGIN_CONV_THEME_GET_PRIVATE(Gobject) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_CONV_THEME, PidginConvThemePrivate))
+
+/******************************************************************************
+ * Structs
+ *****************************************************************************/
+
+typedef struct {
+	/* current config options */
+	char     *variant; /* allowed to be NULL if there are no variants */
+	GList    *variants;
+
+	/* Info.plist keys/values */
+	GHashTable *info;
+
+	/* caches */
+	char    *template_html;
+	char    *header_html;
+	char    *footer_html;
+	char    *topic_html;
+	char    *status_html;
+	char    *content_html;
+	char    *incoming_content_html;
+	char    *outgoing_content_html;
+	char    *incoming_next_content_html;
+	char    *outgoing_next_content_html;
+	char    *incoming_context_html;
+	char    *outgoing_context_html;
+	char    *incoming_next_context_html;
+	char    *outgoing_next_context_html;
+	char    *basestyle_css;
+} PidginConvThemePrivate;
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+
+enum {
+	PROP_ZERO = 0,
+	PROP_INFO,
+	PROP_VARIANT,
+	PROP_LAST
+};
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+
+static GObjectClass *parent_class = NULL;
+#if GLIB_CHECK_VERSION(2,26,0)
+static GParamSpec *properties[PROP_LAST];
+#endif
+
+/******************************************************************************
+ * Helper Functions
+ *****************************************************************************/
+
+static const GValue *
+get_key(PidginConvThemePrivate *priv, const char *key, gboolean specific)
+{
+	GValue *val = NULL;
+
+	/* Try variant-specific key */
+	if (specific && priv->variant) {
+		char *name = g_strdup_printf("%s:%s", key, priv->variant);
+		val = g_hash_table_lookup(priv->info, name);
+		g_free(name);
+	}
+
+	/* Try generic key */
+	if (!val) {
+		val = g_hash_table_lookup(priv->info, key);
+	}
+
+	return val;
+}
+
+static const char *
+get_template_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	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);
+	}
+
+	if (!g_file_get_contents(file, &priv->template_html, NULL, NULL)) {
+		purple_debug_error("webkit", "Could not locate a Template.html (%s)\n", file);
+		priv->template_html = g_strdup("");
+	}
+	g_free(file);
+
+	return priv->template_html;
+}
+
+static const char *
+get_basestyle_css(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->basestyle_css)
+		return priv->basestyle_css;
+
+	file = g_build_filename(dir, "Contents", "Resources", "main.css", NULL);
+	if (!g_file_get_contents(file, &priv->basestyle_css, NULL, NULL))
+		priv->basestyle_css = g_strdup("");
+	g_free(file);
+
+	return priv->basestyle_css;
+}
+
+static const char *
+get_header_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->header_html)
+		return priv->header_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Header.html", NULL);
+	if (!g_file_get_contents(file, &priv->header_html, NULL, NULL))
+		priv->header_html = g_strdup("");
+	g_free(file);
+
+	return priv->header_html;
+}
+
+static const char *
+get_footer_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->footer_html)
+		return priv->footer_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Footer.html", NULL);
+	if (!g_file_get_contents(file, &priv->footer_html, NULL, NULL))
+		priv->footer_html = g_strdup("");
+	g_free(file);
+
+	return priv->footer_html;
+}
+
+static const char *
+get_topic_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->topic_html)
+		return priv->topic_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Topic.html", NULL);
+	if (!g_file_get_contents(file, &priv->topic_html, NULL, NULL)) {
+		purple_debug_info("webkit", "%s could not find Resources/Topic.html\n", dir);
+		priv->topic_html = g_strdup("");
+	}
+	g_free(file);
+
+	return priv->topic_html;
+}
+
+static const char *
+get_content_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->content_html)
+		return priv->content_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Content.html", NULL);
+	if (!g_file_get_contents(file, &priv->content_html, NULL, NULL)) {
+		purple_debug_info("webkit", "%s did not have a Content.html\n", dir);
+		priv->content_html = g_strdup("");
+	}
+	g_free(file);
+
+	return priv->content_html;
+}
+
+static const char *
+get_status_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->status_html)
+		return priv->status_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Status.html", NULL);
+	if (!g_file_get_contents(file, &priv->status_html, NULL, NULL)) {
+		purple_debug_info("webkit", "%s could not find Resources/Status.html\n", dir);
+		priv->status_html = g_strdup(get_content_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->status_html;
+}
+
+static const char *
+get_incoming_content_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->incoming_content_html)
+		return priv->incoming_content_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Incoming", "Content.html", NULL);
+	if (!g_file_get_contents(file, &priv->incoming_content_html, NULL, NULL)) {
+		purple_debug_info("webkit", "%s did not have a Incoming/Content.html\n", dir);
+		priv->incoming_content_html = g_strdup(get_content_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->incoming_content_html;
+}
+
+static const char *
+get_incoming_next_content_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->incoming_next_content_html)
+		return priv->incoming_next_content_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Incoming", "NextContent.html", NULL);
+	if (!g_file_get_contents(file, &priv->incoming_next_content_html, NULL, NULL)) {
+		priv->incoming_next_content_html = g_strdup(get_incoming_content_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->incoming_next_content_html;
+}
+
+static const char *
+get_incoming_context_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->incoming_context_html)
+		return priv->incoming_context_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Incoming", "Context.html", NULL);
+	if (!g_file_get_contents(file, &priv->incoming_context_html, NULL, NULL)) {
+		purple_debug_info("webkit", "%s did not have a Incoming/Context.html\n", dir);
+		priv->incoming_context_html = g_strdup(get_incoming_content_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->incoming_context_html;
+}
+
+static const char *
+get_incoming_next_context_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->incoming_next_context_html)
+		return priv->incoming_next_context_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Incoming", "NextContext.html", NULL);
+	if (!g_file_get_contents(file, &priv->incoming_next_context_html, NULL, NULL)) {
+		priv->incoming_next_context_html = g_strdup(get_incoming_context_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->incoming_next_context_html;
+}
+
+static const char *
+get_outgoing_content_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->outgoing_content_html)
+		return priv->outgoing_content_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "Content.html", NULL);
+	if (!g_file_get_contents(file, &priv->outgoing_content_html, NULL, NULL)) {
+		priv->outgoing_content_html = g_strdup(get_incoming_content_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->outgoing_content_html;
+}
+
+static const char *
+get_outgoing_next_content_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->outgoing_next_content_html)
+		return priv->outgoing_next_content_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "NextContent.html", NULL);
+	if (!g_file_get_contents(file, &priv->outgoing_next_content_html, NULL, NULL)) {
+		priv->outgoing_next_content_html = g_strdup(get_outgoing_content_html(priv, dir));
+	}
+
+	return priv->outgoing_next_content_html;
+}
+
+static const char *
+get_outgoing_context_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->outgoing_context_html)
+		return priv->outgoing_context_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "Context.html", NULL);
+	if (!g_file_get_contents(file, &priv->outgoing_context_html, NULL, NULL)) {
+		priv->outgoing_context_html = g_strdup(get_incoming_context_html(priv, dir));
+	}
+	g_free(file);
+
+	return priv->outgoing_context_html;
+}
+
+static const char *
+get_outgoing_next_context_html(PidginConvThemePrivate *priv, const char *dir)
+{
+	char *file;
+
+	if (priv->outgoing_next_context_html)
+		return priv->outgoing_next_context_html;
+
+	file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "NextContext.html", NULL);
+	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));
+	}
+
+	return priv->outgoing_next_context_html;
+}
+
+static void
+_set_variant(PidginConvTheme *theme, const char *variant)
+{
+	PidginConvThemePrivate *priv;
+	const GValue *val;
+	char *prefname;
+
+	g_return_if_fail(theme != NULL);
+	g_return_if_fail(variant != NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	g_free(priv->variant);
+	priv->variant = g_strdup(variant);
+
+	val = get_key(priv, "CFBundleIdentifier", FALSE);
+	prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s/variant",
+	                           g_value_get_string(val));
+	purple_prefs_set_string(prefname, variant);
+	g_free(prefname);
+}
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+
+static void
+pidgin_conv_theme_get_property(GObject *obj, guint param_id, GValue *value,
+		GParamSpec *psec)
+{
+	PidginConvTheme *theme = PIDGIN_CONV_THEME(obj);
+
+	switch (param_id) {
+		case PROP_INFO:
+			g_value_set_boxed(value, (gpointer)pidgin_conversation_theme_get_info(theme));
+			break;
+
+		case PROP_VARIANT:
+			g_value_set_string(value, pidgin_conversation_theme_get_variant(theme));
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec);
+			break;
+	}
+}
+
+static void
+pidgin_conv_theme_set_property(GObject *obj, guint param_id, const GValue *value,
+		GParamSpec *psec)
+{
+	PidginConvTheme *theme = PIDGIN_CONV_THEME(obj);
+
+	switch (param_id) {
+		case PROP_INFO:
+			pidgin_conversation_theme_set_info(theme, g_value_get_boxed(value));
+			break;
+
+		case PROP_VARIANT:
+			_set_variant(theme, g_value_get_string(value));
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec);
+			break;
+	}
+}
+
+static void
+pidgin_conv_theme_init(GTypeInstance *instance,
+		gpointer klass)
+{
+	PidginConvThemePrivate *priv;
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(instance);
+}
+
+static void
+pidgin_conv_theme_finalize(GObject *obj)
+{
+	PidginConvThemePrivate *priv;
+	GList *list;
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(obj);
+
+	g_free(priv->template_html);
+	g_free(priv->header_html);
+	g_free(priv->footer_html);
+	g_free(priv->topic_html);
+	g_free(priv->status_html);
+	g_free(priv->content_html);
+	g_free(priv->incoming_content_html);
+	g_free(priv->outgoing_content_html);
+	g_free(priv->incoming_next_content_html);
+	g_free(priv->outgoing_next_content_html);
+	g_free(priv->incoming_context_html);
+	g_free(priv->outgoing_context_html);
+	g_free(priv->incoming_next_context_html);
+	g_free(priv->outgoing_next_context_html);
+	g_free(priv->basestyle_css);
+
+	if (priv->info)
+		g_hash_table_destroy(priv->info);
+
+	list = priv->variants;
+	while (list) {
+		g_free(list->data);
+		list = g_list_delete_link(list, list);
+	}
+	g_free(priv->variant);
+
+	parent_class->finalize(obj);
+}
+
+static void
+pidgin_conv_theme_class_init(PidginConvThemeClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	GParamSpec *pspec;
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	g_type_class_add_private(klass, sizeof(PidginConvThemePrivate));
+
+	obj_class->get_property = pidgin_conv_theme_get_property;
+	obj_class->set_property = pidgin_conv_theme_set_property;
+	obj_class->finalize = pidgin_conv_theme_finalize;
+
+	/* INFO */
+	pspec = g_param_spec_boxed("info", "Info",
+			"The information about this theme",
+			G_TYPE_HASH_TABLE,
+			G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+	g_object_class_install_property(obj_class, PROP_INFO, pspec);
+#if GLIB_CHECK_VERSION(2,26,0)
+	properties[PROP_INFO] = pspec;
+#endif
+
+	/* VARIANT */
+	pspec = g_param_spec_string("variant", "Variant",
+			"The current variant for this theme",
+			NULL, G_PARAM_READWRITE);
+	g_object_class_install_property(obj_class, PROP_VARIANT, pspec);
+#if GLIB_CHECK_VERSION(2,26,0)
+	properties[PROP_VARIANT] = pspec;
+#endif
+}
+
+GType
+pidgin_conversation_theme_get_type(void)
+{
+	static GType type = 0;
+	if (type == 0) {
+		static const GTypeInfo info = {
+			sizeof(PidginConvThemeClass),
+			NULL, /* base_init */
+			NULL, /* base_finalize */
+			(GClassInitFunc)pidgin_conv_theme_class_init, /* class_init */
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof(PidginConvTheme),
+			0, /* n_preallocs */
+			pidgin_conv_theme_init, /* instance_init */
+			NULL, /* value table */
+		};
+		type = g_type_register_static(PURPLE_TYPE_THEME,
+				"PidginConvTheme", &info, 0);
+	}
+	return type;
+}
+
+/*****************************************************************************
+ * Public API functions
+ *****************************************************************************/
+
+const GHashTable *
+pidgin_conversation_theme_get_info(const PidginConvTheme *theme)
+{
+	PidginConvThemePrivate *priv;
+
+	g_return_val_if_fail(theme != NULL, NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+	return priv->info;
+}
+
+void
+pidgin_conversation_theme_set_info(PidginConvTheme *theme, GHashTable *info)
+{
+	PidginConvThemePrivate *priv;
+
+	g_return_if_fail(theme != NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	if (priv->info)
+		g_hash_table_destroy(priv->info);
+
+	priv->info = info;
+}
+
+const GValue *
+pidgin_conversation_theme_lookup(PidginConvTheme *theme, const char *key, gboolean specific)
+{
+	PidginConvThemePrivate *priv;
+
+	g_return_val_if_fail(theme != NULL, NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	return get_key(priv, key, specific);
+}
+
+const char *
+pidgin_conversation_theme_get_template(PidginConvTheme *theme, PidginConvThemeTemplateType type)
+{
+	PidginConvThemePrivate *priv;
+	const char *dir;
+	const char *html;
+
+	g_return_val_if_fail(theme != NULL, NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+	dir = purple_theme_get_dir(PURPLE_THEME(theme));
+
+	switch (type) {
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN:
+			html = get_template_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER:
+			html = get_header_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER:
+			html = get_footer_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_TOPIC:
+			html = get_topic_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS:
+			html = get_status_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_CONTENT:
+			html = get_content_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT:
+			html = get_incoming_content_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT:
+			html = get_incoming_next_content_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTEXT:
+			html = get_incoming_context_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTEXT:
+			html = get_incoming_next_context_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT:
+			html = get_outgoing_content_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT:
+			html = get_outgoing_next_content_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTEXT:
+			html = get_outgoing_context_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTEXT:
+			html = get_outgoing_next_context_html(priv, dir);
+			break;
+		case PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS:
+			html = get_basestyle_css(priv, dir);
+			break;
+		default:
+			purple_debug_error("gtkconv-theme",
+			                   "Requested invalid template type (%d) for theme %s.\n",
+			                   type, purple_theme_get_name(PURPLE_THEME(theme)));
+			html = NULL;
+	}
+
+	return html;
+}
+
+void
+pidgin_conversation_theme_add_variant(PidginConvTheme *theme, char *variant)
+{
+	PidginConvThemePrivate *priv;
+
+	g_return_if_fail(theme != NULL);
+	g_return_if_fail(variant != NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	priv->variants = g_list_prepend(priv->variants, variant);
+}
+
+const char *
+pidgin_conversation_theme_get_variant(PidginConvTheme *theme)
+{
+	PidginConvThemePrivate *priv;
+
+	g_return_val_if_fail(theme != NULL, NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	return priv->variant;
+}
+
+void
+pidgin_conversation_theme_set_variant(PidginConvTheme *theme, const char *variant)
+{
+	_set_variant(theme, variant);
+#if GLIB_CHECK_VERSION(2,26,0)
+	g_object_notify_by_pspec(G_OBJECT(theme), properties[PROP_VARIANT]);
+#else
+	g_object_notify(G_OBJECT(theme), "variant");
+#endif
+}
+
+const GList *
+pidgin_conversation_theme_get_variants(PidginConvTheme *theme)
+{
+	PidginConvThemePrivate *priv;
+
+	g_return_val_if_fail(theme != NULL, NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	return priv->variants;
+}
+
+char *
+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;
+}
+
+char *
+pidgin_conversation_theme_get_css_path(PidginConvTheme *theme)
+{
+	PidginConvThemePrivate *priv;
+	const char *dir;
+
+	g_return_val_if_fail(theme != NULL, NULL);
+
+	priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
+
+	dir = purple_theme_get_dir(PURPLE_THEME(theme));
+	if (!priv->variant) {
+		return g_build_filename(dir, "Contents", "Resources", "main.css", NULL);
+	} else {
+		char *file = g_strdup_printf("%s.css", priv->variant);
+		char *ret = g_build_filename(dir, "Contents", "Resources", "Variants",  file, NULL);
+		g_free(file);
+		return ret;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkconv-theme.h	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,196 @@
+/**
+ * @file gtkconv-theme.h  Pidgin Conversation Theme  Class API
+ */
+
+/* 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
+ */
+
+#ifndef PIDGIN_CONV_THEME_H
+#define PIDGIN_CONV_THEME_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "conversation.h"
+#include "theme.h"
+
+/**
+ * extends PurpleTheme (theme.h)
+ * A pidgin icon theme.
+ * This object represents a Pidgin icon theme.
+ *
+ * PidginConvTheme is a PurpleTheme Object.
+ */
+typedef struct _PidginConvTheme        PidginConvTheme;
+typedef struct _PidginConvThemeClass   PidginConvThemeClass;
+
+#define PIDGIN_TYPE_CONV_THEME            (pidgin_conversation_theme_get_type ())
+#define PIDGIN_CONV_THEME(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIDGIN_TYPE_CONV_THEME, PidginConvTheme))
+#define PIDGIN_CONV_THEME_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PIDGIN_TYPE_CONV_THEME, PidginConvThemeClass))
+#define PIDGIN_IS_CONV_THEME(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIDGIN_TYPE_CONV_THEME))
+#define PIDGIN_IS_CONV_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIDGIN_TYPE_CONV_THEME))
+#define PIDGIN_CONV_THEME_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PIDGIN_TYPE_CONV_THEME, PidginConvThemeClass))
+
+struct _PidginConvTheme
+{
+	PurpleTheme parent;
+};
+
+struct _PidginConvThemeClass
+{
+	PurpleThemeClass parent_class;
+};
+
+typedef enum {
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_TOPIC,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_CONTENT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTEXT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTEXT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTEXT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTEXT,
+	PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS
+
+} PidginConvThemeTemplateType;
+
+/**************************************************************************/
+/** @name Pidgin Conversation Theme API                                   */
+/**************************************************************************/
+G_BEGIN_DECLS
+
+/**
+ * GObject foo.
+ * @internal.
+ */
+GType pidgin_conversation_theme_get_type(void);
+
+/**
+ * Get the Info.plist hash table from a conversation theme.
+ *
+ * @param theme The conversation theme
+ *
+ * @return The hash table. Keys are strings as outlined for message styles,
+ *         values are GValue*s. This is an internal structure. Take a ref if
+ *         necessary, but don't destroy it yourself.
+ */
+const GHashTable *pidgin_conversation_theme_get_info(const PidginConvTheme *theme);
+
+/**
+ * Set the Info.plist hash table for a conversation theme.
+ *
+ * @param theme The conversation theme
+ * @param info  The new hash table. The theme will take ownership of this hash
+ *              table. Do not use it yourself afterwards with holding a ref.
+ *              For key and value specifications, @see pidgin_conversation_theme_get_info.
+ *
+ */
+void pidgin_conversation_theme_set_info(PidginConvTheme *theme, GHashTable *info);
+
+/**
+ * Lookup a key in a theme
+ *
+ * @param theme    The conversation theme
+ * @param key      The key to find
+ * @param specific Whether to search variant-specific keys
+ *
+ * @return The key information. If @a specific is @c TRUE, then keys are first
+ *         searched by variant, then by general ones. Otherwise, only general
+ *         key values are returned.
+ */
+const GValue *pidgin_conversation_theme_lookup(PidginConvTheme *theme, const char *key, gboolean specific);
+
+/**
+ * Get the template data from a conversation theme.
+ *
+ * @param theme The conversation theme
+ * @param type  The type of template data
+ *
+ * @return The template data requested. Fallback is made as required by styles.
+ *         Subsequent calls to this function will return cached values.
+ */
+const char *pidgin_conversation_theme_get_template(PidginConvTheme *theme, PidginConvThemeTemplateType type);
+
+/**
+ * Add an available variant name to a conversation theme.
+ *
+ * @param theme   The conversation theme
+ * @param variant The name of the variant
+ *
+ * @Note The conversation theme will take ownership of the variant name string.
+ *       This function should normally only be called by the theme loader.
+ */
+void pidgin_conversation_theme_add_variant(PidginConvTheme *theme, char *variant);
+
+/**
+ * Get the currently set variant name for a conversation theme.
+ *
+ * @param theme The conversation theme
+ *
+ * @return The current variant name.
+ */
+const char *pidgin_conversation_theme_get_variant(PidginConvTheme *theme);
+
+/**
+ * Set the variant name for a conversation theme.
+ *
+ * @param theme   The conversation theme
+ * @param variant The name of the variant
+ *
+ */
+void pidgin_conversation_theme_set_variant(PidginConvTheme *theme, const char *variant);
+
+/**
+ * Get a list of available variants for a conversation theme.
+ *
+ * @param theme The conversation theme
+ *
+ * @return The list of variants. This GList and the string data are owned by
+ *         the theme and should not be freed by the caller.
+ */
+const GList *pidgin_conversation_theme_get_variants(PidginConvTheme *theme);
+
+/**
+ * Get the path to the template HTML file.
+ *
+ * @param theme The conversation theme
+ *
+ * @return The path to the HTML file.
+ */
+char *pidgin_conversation_theme_get_template_path(PidginConvTheme *theme);
+
+/**
+ * Get the path to the current variant CSS file.
+ *
+ * @param theme The conversation theme
+ *
+ * @return The path to the CSS file.
+ */
+char *pidgin_conversation_theme_get_css_path(PidginConvTheme *theme);
+
+G_END_DECLS
+#endif /* PIDGIN_CONV_THEME_H */
+
--- a/pidgin/gtkconv.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkconv.c	Mon Oct 31 01:25:36 2011 +0000
@@ -52,6 +52,8 @@
 #include "notify.h"
 #include "prpl.h"
 #include "request.h"
+#include "theme-loader.h"
+#include "theme-manager.h"
 #include "util.h"
 #include "version.h"
 
@@ -59,6 +61,8 @@
 #include "gtkblist.h"
 #include "gtkconv.h"
 #include "gtkconvwin.h"
+#include "gtkconv-theme.h"
+#include "gtkconv-theme-loader.h"
 #include "gtkdialogs.h"
 #include "gtkimhtml.h"
 #include "gtkimhtmltoolbar.h"
@@ -69,11 +73,46 @@
 #include "gtkprivacy.h"
 #include "gtkthemes.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 #include "pidginstock.h"
 #include "pidgintooltip.h"
+#include "smileyparser.h"
 
 #include "gtknickcolors.h"
 
+/**
+ * A GTK+ Instant Message pane.
+ */
+struct _PidginImPane
+{
+	GtkWidget *block;
+	GtkWidget *send_file;
+	GtkWidget *sep1;
+	GtkWidget *sep2;
+	GtkWidget *check;
+	GtkWidget *progress;
+	guint32 typing_timer;
+
+	/* Buddy icon stuff */
+	GtkWidget *icon_container;
+	GtkWidget *icon;
+	gboolean show_icon;
+	gboolean animate;
+	GdkPixbufAnimation *anim;
+	GdkPixbufAnimationIter *iter;
+	guint32 icon_timer;
+};
+
+/**
+ * GTK+ Chat panes.
+ */
+struct _PidginChatPane
+{
+	GtkWidget *count;
+	GtkWidget *list;
+	GtkWidget *topic_text;
+};
+
 #define CLOSE_CONV_TIMEOUT_SECS  (10 * 60)
 
 #define AUTO_RESPONSE "&lt;AUTO-REPLY&gt; : "
@@ -176,7 +215,7 @@
 static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name)
 {
 	static GdkColor col;
-	GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml);
+	GtkStyle *style = gtk_widget_get_style(gtkconv->webview);
 	float scale;
 
 	col = nick_colors[g_str_hash(name) % nbr_nick_colors];
@@ -196,15 +235,16 @@
 static PurpleBlistNode *
 get_conversation_blist_node(PurpleConversation *conv)
 {
+	PurpleAccount *account = purple_conversation_get_account(conv);
 	PurpleBlistNode *node = NULL;
 
 	switch (purple_conversation_get_type(conv)) {
 		case PURPLE_CONV_TYPE_IM:
-			node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name));
+			node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv)));
 			node = node ? node->parent : NULL;
 			break;
 		case PURPLE_CONV_TYPE_CHAT:
-			node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name));
+			node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv)));
 			break;
 		default:
 			break;
@@ -276,7 +316,7 @@
 default_formatize(PidginConversation *c)
 {
 	PurpleConversation *conv = c->active_conv;
-	gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features);
+	gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), purple_conversation_get_features(conv));
 }
 
 static void
@@ -356,8 +396,32 @@
 		}
 
 		tmp = g_string_free(str, FALSE);
+	} else if (!g_ascii_strcasecmp(args[0], "unsafe")) {
+		if (purple_debug_is_unsafe()) {
+			purple_debug_set_unsafe(FALSE);
+			purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."),
+			                          PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
+		} else {
+			purple_debug_set_unsafe(TRUE);
+			purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."),
+			                          PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
+		}
+
+		return PURPLE_CMD_RET_OK;
+	} else if (!g_ascii_strcasecmp(args[0], "verbose")) {
+		if (purple_debug_is_verbose()) {
+			purple_debug_set_verbose(FALSE);
+			purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."),
+			                          PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
+		} else {
+			purple_debug_set_verbose(TRUE);
+			purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."),
+			                          PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL));
+		}
+
+		return PURPLE_CMD_RET_OK;
 	} else {
-		purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"),
+		purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"),
 		                        PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL));
 		return PURPLE_CMD_RET_OK;
 	}
@@ -379,8 +443,9 @@
 	PidginConversation *gtkconv = NULL;
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
-	if (gtkconv)
-		gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml));
+
+	if (PIDGIN_CONVERSATION(conv))
+		webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(gtkconv->webview), "", "");
 }
 
 static PurpleCmdRet
@@ -498,8 +563,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;
@@ -578,7 +643,7 @@
 
 	gtk_widget_grab_focus(gtkconv->entry);
 
-	if (strlen(clean) == 0) {
+	if (!*clean) {
 		g_free(buf);
 		g_free(clean);
 		return;
@@ -591,7 +656,7 @@
 		flags |= PURPLE_MESSAGE_IMAGES;
 
 	gc = purple_account_get_connection(account);
-	if (gc && (conv->features & PURPLE_CONNECTION_NO_NEWLINES)) {
+	if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) {
 		char **bufs;
 		int i;
 
@@ -657,7 +722,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)));
 	}
 }
@@ -669,7 +734,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) {
@@ -757,7 +822,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);
 	}
@@ -792,7 +857,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 "
@@ -988,6 +1053,8 @@
 static void
 savelog_writefile_cb(void *user_data, const char *filename)
 {
+	/* TODO WEBKIT: I don't know how to support this using webkit yet. */
+#if 0
 	PurpleConversation *conv = (PurpleConversation *)user_data;
 	FILE *fp;
 	const char *name;
@@ -1014,6 +1081,7 @@
 
 	fprintf(fp, "\n</body>\n</html>\n");
 	fclose(fp);
+#endif /* if 0 */
 }
 
 /*
@@ -1025,7 +1093,8 @@
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
-	PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name);
+	PurpleAccount *account = purple_conversation_get_account(conv);
+	PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
 	const char *name;
 	gchar *buf;
 	gchar *c;
@@ -1033,7 +1102,7 @@
 	if (buddy != NULL)
 		name = purple_buddy_get_contact_alias(buddy);
 	else
-		name = purple_normalize(conv->account, conv->name);
+		name = purple_normalize(account, purple_conversation_get_name(conv));
 
 	buf = g_strdup_printf("%s.html", name);
 	for (c = buf ; *c ; c++)
@@ -1147,7 +1216,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);
 	}
 
 }
@@ -1159,8 +1228,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);
 	}
 }
 
@@ -1356,16 +1430,14 @@
 
 		purple_conversation_write(conv, NULL,
 								_("Logging started. Future messages in this conversation will be logged."),
-								conv->logs ? (PURPLE_MESSAGE_SYSTEM) :
-								             (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
+								PURPLE_MESSAGE_SYSTEM,
 								time(NULL));
 	}
 	else
 	{
 		purple_conversation_write(conv, NULL,
 								_("Logging stopped. Future messages in this conversation will not be logged."),
-								conv->logs ? (PURPLE_MESSAGE_SYSTEM) :
-								             (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG),
+								PURPLE_MESSAGE_SYSTEM,
 								time(NULL));
 
 		/* Disable the logging second, so that the above message can be logged. */
@@ -1373,7 +1445,7 @@
 	}
 
 	/* Save the setting IFF it's different than the pref. */
-	switch (conv->type)
+	switch (purple_conversation_get_type(conv))
 	{
 		case PURPLE_CONV_TYPE_IM:
 			if (logging == purple_prefs_get_bool("/purple/logging/log_ims"))
@@ -1445,7 +1517,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,
@@ -1496,12 +1568,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,
@@ -1522,32 +1594,6 @@
 }
 
 static void
-menu_chat_get_away_cb(GtkWidget *w, PidginConversation *gtkconv)
-{
-	PurpleConversation *conv = gtkconv->active_conv;
-	PurplePluginProtocolInfo *prpl_info = NULL;
-	PurpleConnection *gc;
-	char *who;
-
-	gc  = purple_conversation_get_gc(conv);
-	who = g_object_get_data(G_OBJECT(w), "user_data");
-
-	if (gc != NULL) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
-		/*
-		 * May want to expand this to work similarly to menu_info_cb?
-		 */
-
-		if (prpl_info->get_cb_away != NULL)
-		{
-			prpl_info->get_cb_away(gc,
-				purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who);
-		}
-	}
-}
-
-static void
 menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv)
 {
 	PurpleConversation *conv = gtkconv->active_conv;
@@ -1570,7 +1616,7 @@
 static GtkTextMark *
 get_mark_for_user(PidginConversation *gtkconv, const char *who)
 {
-	GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml));
+	GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview));
 	char *tmp = g_strconcat("user:", who, NULL);
 	GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp);
 
@@ -1581,6 +1627,8 @@
 static void
 menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv)
 {
+/* TODO WEBKIT: This doesn't work yet, of course... */
+#if 0
 	GtkTextMark *mark;
 	const char *who;
 
@@ -1591,6 +1639,7 @@
 		gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
 	else
 		g_return_if_reached();
+#endif /* if 0 */
 }
 
 static GtkWidget *
@@ -1599,12 +1648,13 @@
 	static GtkWidget *menu = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
+	PurpleAccount *account = purple_conversation_get_account(conv);
 	gboolean is_me = FALSE;
 	GtkWidget *button;
 	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,
@@ -1613,7 +1663,7 @@
 	if (menu)
 		gtk_widget_destroy(menu);
 
-	if (!strcmp(chat->nick, purple_normalize(conv->account, who)))
+	if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who)))
 		is_me = TRUE;
 
 	menu = gtk_menu_new();
@@ -1678,18 +1728,8 @@
 			g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
 	}
 
-	if (prpl_info && prpl_info->get_cb_away) {
-		button = pidgin_new_item_from_stock(menu, _("Get Away Message"), PIDGIN_STOCK_AWAY,
-					G_CALLBACK(menu_chat_get_away_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
-
-		if (gc == NULL)
-			gtk_widget_set_sensitive(button, FALSE);
-		else
-			g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
-	}
-
 	if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
-		if ((buddy = purple_find_buddy(conv->account, who)) != NULL)
+		if ((buddy = purple_find_buddy(account, who)) != NULL)
 			button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE,
 						G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
 		else
@@ -1710,8 +1750,8 @@
 
 	if (buddy != NULL)
 	{
-		if (purple_account_is_connected(conv->account))
-			pidgin_append_blist_node_proto_menu(menu, conv->account->gc,
+		if (purple_account_is_connected(account))
+			pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account),
 												  (PurpleBlistNode *)buddy);
 		pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
 		gtk_widget_show_all(menu);
@@ -1737,7 +1777,7 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	gtkchat = gtkconv->u.chat;
 	account = purple_conversation_get_account(conv);
-	gc      = account->gc;
+	gc      = purple_account_get_connection(account);
 
 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
 
@@ -1773,7 +1813,7 @@
 
 	gtkchat = gtkconv->u.chat;
 	account = purple_conversation_get_account(conv);
-	gc      = account->gc;
+	gc      = purple_account_get_connection(account);
 
 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
 
@@ -1805,10 +1845,13 @@
 		chat_do_im(gtkconv, who);
 	} else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) {
 		/* Move to user's anchor */
+/* TODO WEBKIT: This isn't implemented yet. */
+#if 0
 		GtkTextMark *mark = get_mark_for_user(gtkconv, who);
 
 		if(mark != NULL)
 			gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
+#endif /* if 0 */
 	} else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
 		GtkWidget *menu = create_chat_menu (conv, who, gc);
 		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
@@ -1885,8 +1928,8 @@
 		GtkWidget *from;
 		GtkWidget *to;
 	} transitions[] = {
-		{gtkconv->entry, gtkconv->imhtml},
-		{gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry},
+		{gtkconv->entry, gtkconv->webview},
+		{gtkconv->webview, chat ? gtkconv->u.chat->list : gtkconv->entry},
 		{chat ? gtkconv->u.chat->list : NULL, gtkconv->entry},
 		{NULL, NULL}
 	}, *ptr;
@@ -2142,14 +2185,20 @@
 			break;
 
 		case GDK_Page_Up:
- 		case GDK_KP_Page_Up:
+		case GDK_KP_Page_Up:
+/* TODO WEBKIT: Write this. */
+#if 0
 			gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml));
+#endif /* if 0 */
 			return TRUE;
 			break;
 
 		case GDK_Page_Down:
- 		case GDK_KP_Page_Down:
+		case GDK_KP_Page_Down:
+/* TODO WEBKIT: Write this. */
+#if 0
 			gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml));
+#endif /* if 0 */
 			return TRUE;
 			break;
 
@@ -2236,6 +2285,7 @@
 	PurpleConversation *old_conv;
 	GtkIMHtml *entry;
 	const char *protocol_name;
+	PurpleConnectionFlags features;
 
 	g_return_if_fail(conv != NULL);
 
@@ -2257,14 +2307,15 @@
 		gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging)));
 
 	entry = GTK_IMHTML(gtkconv->entry);
-	protocol_name = purple_account_get_protocol_name(conv->account);
+	protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv));
 	gtk_imhtml_set_protocol_name(entry, protocol_name);
-	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name);
-
-	if (!(conv->features & PURPLE_CONNECTION_HTML))
+	/* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */
+
+	features = purple_conversation_get_features(conv);
+	if (!(features & PURPLE_CONNECTION_HTML))
 		gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry));
-	else if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO &&
-	         !(old_conv->features & PURPLE_CONNECTION_FORMATTING_WBFO))
+	else if (features & PURPLE_CONNECTION_FORMATTING_WBFO &&
+	         !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO))
 	{
 		/* The old conversation allowed formatting on parts of the
 		 * buffer, but the new one only allows it on the whole
@@ -2304,12 +2355,12 @@
 
 		gtk_imhtml_toggle_fontface(entry, fontface);
 
-		if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE))
+		if (!(features & PURPLE_CONNECTION_NO_FONTSIZE))
 			gtk_imhtml_font_set_size(entry, fontsize);
 
 		gtk_imhtml_toggle_forecolor(entry, forecolor);
 
-		if (!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR))
+		if (!(features & PURPLE_CONNECTION_NO_BGCOLOR))
 		{
 			gtk_imhtml_toggle_backcolor(entry, backcolor);
 			gtk_imhtml_toggle_background(entry, background);
@@ -2327,7 +2378,7 @@
 		 * here, we didn't call gtk_imhtml_clear_formatting() (because we want to
 		 * preserve the formatting exactly as it is), so we have to do this now. */
 		gtk_imhtml_set_whole_buffer_formatting_only(entry,
-			(conv->features & PURPLE_CONNECTION_FORMATTING_WBFO));
+			(features & PURPLE_CONNECTION_FORMATTING_WBFO));
 	}
 
 	purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv);
@@ -2392,7 +2443,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);
 	}
@@ -2557,7 +2608,7 @@
 	status = infopane_status = pidgin_conv_get_icon_stock(conv);
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		PurpleBuddy *b = purple_find_buddy(conv->account, conv->name);
+		PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
 		if (b)
 			emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
 	}
@@ -2578,7 +2629,7 @@
 		g_object_unref(emblem);
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) {
-		emblem = pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL);
+		emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL);
 	} else {
 		emblem = NULL;
 	}
@@ -2634,7 +2685,7 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	account = purple_conversation_get_account(conv);
 
-	if (!(account && account->gc)) {
+	if (!(account && purple_account_get_connection(account))) {
 		gtkconv->u.im->icon_timer = 0;
 		return FALSE;
 	}
@@ -2841,11 +2892,11 @@
 
 	ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv)));
 
-	buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext);
+	buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext);
 
 	purple_request_file(gtkconv, _("Save Icon"), buf, TRUE,
 					 G_CALLBACK(saveicon_writefile_cb), NULL,
-					conv->account, NULL, conv,
+					purple_conversation_get_account(conv), NULL, conv,
 					gtkconv);
 
 	g_free(buf);
@@ -3185,21 +3236,23 @@
 {
 	GList *list;
 	PurpleConversation *conv;
+	PurpleAccount *account;
 	PurpleBlistNode *node = NULL;
 	PurpleChat *chat = NULL;
 	PurpleBuddy *buddy = NULL;
 	gboolean ret;
 
 	conv = gtkconv->active_conv;
+	account = purple_conversation_get_account(conv);
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
-		chat = purple_blist_find_chat(conv->account, conv->name);
-
-		if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
-			chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat");
-		}
-
-		if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
+		chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
+
+		if ((chat == NULL) && (gtkconv->webview != NULL)) {
+			chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
+		}
+
+		if ((chat == NULL) && (gtkconv->webview != NULL)) {
 			GHashTable *components;
 			PurpleAccount *account = purple_conversation_get_account(conv);
 			PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
@@ -3214,30 +3267,30 @@
 				g_hash_table_replace(components, g_strdup("channel"),
 						g_strdup(purple_conversation_get_name(conv)));
 			}
-			chat = purple_chat_new(conv->account, NULL, components);
+			chat = purple_chat_new(account, NULL, components);
 			purple_blist_node_set_flags((PurpleBlistNode *)chat,
 					PURPLE_BLIST_NODE_FLAG_NO_SAVE);
-			g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat",
+			g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat",
 					chat, (GDestroyNotify)purple_blist_remove_chat);
 		}
 	} else {
-		if (!purple_account_is_connected(conv->account))
+		if (!purple_account_is_connected(account))
 			return FALSE;
 
-		buddy = purple_find_buddy(conv->account, conv->name);
+		buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
 
 		/* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle
 		 * removing "isolated" buddy nodes well */
 		if (purple_version_check(2, 0, 2) == NULL) {
-			if ((buddy == NULL) && (gtkconv->imhtml != NULL)) {
-				buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy");
+			if ((buddy == NULL) && (gtkconv->webview != NULL)) {
+				buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
 			}
 
-			if ((buddy == NULL) && (gtkconv->imhtml != NULL)) {
-				buddy = purple_buddy_new(conv->account, conv->name, NULL);
+			if ((buddy == NULL) && (gtkconv->webview != NULL)) {
+				buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL);
 				purple_blist_node_set_flags((PurpleBlistNode *)buddy,
 						PURPLE_BLIST_NODE_FLAG_NO_SAVE);
-				g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy",
+				g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy",
 						buddy, (GDestroyNotify)purple_buddy_destroy);
 			}
 		}
@@ -3256,8 +3309,8 @@
 			/* XXX: */
 		}
 	} else if (node) {
-		if (purple_account_is_connected(conv->account))
-			pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node);
+		if (purple_account_is_connected(account))
+			pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), node);
 		pidgin_append_blist_node_extended_menu(menu, node);
 	}
 
@@ -3327,6 +3380,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;
@@ -3414,6 +3521,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. */
@@ -3486,9 +3594,10 @@
 		gtk_item_factory_get_widget(win->menu.item_factory,
 		                            N_("/Conversation/Send File..."));
 
-	g_object_set_data(G_OBJECT(win->window), "get_attention",
+	win->menu.get_attention =
 		gtk_item_factory_get_widget(win->menu.item_factory,
-			                    N_("/Conversation/Get Attention")));
+			                    N_("/Conversation/Get Attention"));
+
 	win->menu.add_pounce =
 		gtk_item_factory_get_widget(win->menu.item_factory,
 		                            N_("/Conversation/Add Buddy Pounce..."));
@@ -3597,7 +3706,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);
@@ -3648,6 +3757,8 @@
 static void
 update_typing_message(PidginConversation *gtkconv, const char *message)
 {
+	/* TODO WEBKIT: this is not handled at all */
+#if 0
 	GtkTextBuffer *buffer;
 	GtkTextMark *stmark, *enmark;
 
@@ -3680,6 +3791,7 @@
 		gtk_text_buffer_get_end_iter(buffer, &iter);
 		gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE);
 	}
+#endif /* if 0 */
 }
 
 static void
@@ -3736,7 +3848,7 @@
 	if (win->menu.send_to == NULL)
 		return FALSE;
 
-	if (!(b = purple_find_buddy(account, conv->name)))
+	if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv))))
 		return FALSE;
 
 
@@ -3896,8 +4008,8 @@
 
 	gtk_widget_show(menu);
 
-	if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM) {
-		buds = purple_find_buddies(gtkconv->active_conv->account, gtkconv->active_conv->name);
+	if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM) {
+		buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
 
 		if (buds == NULL)
 		{
@@ -3921,7 +4033,8 @@
 						continue;
 
 					account = purple_buddy_get_account(buddy);
-					if (purple_account_is_connected(account) || account == gtkconv->active_conv->account)
+					/* TODO WEBKIT: (I'm not actually sure if this is webkit-related --Mark Doliner) */
+					if (purple_account_is_connected(account) /*|| account == purple_conversation_get_account(gtkconv->active_conv)*/)
 					{
 						/* Use the PurplePresence to get unique buddies. */
 						PurplePresence *presence = purple_buddy_get_presence(buddy);
@@ -3980,10 +4093,11 @@
 static void
 deleting_chat_buddy_cb(PurpleConvChatBuddy *cb)
 {
-	if (cb->ui_data) {
-		GtkTreeRowReference *ref = cb->ui_data;
+	GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
+
+	if (ref) {
 		gtk_tree_row_reference_free(ref);
-		cb->ui_data = NULL;
+		purple_conv_chat_cb_set_ui_data(cb, NULL);
 	}
 }
 
@@ -4002,20 +4116,21 @@
 	GtkTreeIter iter;
 	gboolean is_me = FALSE;
 	gboolean is_buddy;
-	gchar *tmp, *alias_key, *name, *alias;
+	const gchar *name, *alias;
+	gchar *tmp, *alias_key;
 	PurpleConvChatBuddyFlags flags;
 	GdkColor *color = NULL;
 
-	alias = cb->alias;
-	name  = cb->name;
-	flags = cb->flags;
+	alias = purple_conv_chat_cb_get_alias(cb);
+	name  = purple_conv_chat_cb_get_name(cb);
+	flags = purple_conv_chat_cb_get_flags(cb);
 
 	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));
@@ -4023,20 +4138,23 @@
 
 	stock = get_chat_buddy_status_icon(chat, name, flags);
 
-	if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name)))
+	if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name)))
 		is_me = TRUE;
 
-	is_buddy = cb->buddy;
+	is_buddy = purple_conv_chat_cb_is_buddy(cb);
 
 	tmp = g_utf8_casefold(alias, -1);
 	alias_key = g_utf8_collate_key(tmp, -1);
 	g_free(tmp);
 
 	if (is_me) {
+#if 0
+		/* TODO WEBKIT: No tags in webkit stuff, yet. */
 		GtkTextTag *tag = gtk_text_tag_table_lookup(
-				gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer),
+				gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer),
 				"send-name");
 		g_object_get(tag, "foreground-gdk", &color, NULL);
+#endif /* if 0 */
 	} else {
 		GtkTextTag *tag;
 		if ((tag = get_buddy_tag(conv, name, 0, FALSE)))
@@ -4064,13 +4182,13 @@
 			CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
 			-1);
 
-	if (cb->ui_data) {
-		GtkTreeRowReference *ref = cb->ui_data;
+	if (purple_conv_chat_cb_get_ui_data(cb)) {
+		GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
 		gtk_tree_row_reference_free(ref);
 	}
 
 	newpath = gtk_tree_model_get_path(tm, &iter);
-	cb->ui_data = gtk_tree_row_reference_new(tm, newpath);
+	purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath));
 	gtk_tree_path_free(newpath);
 
 	if (is_me && color)
@@ -4100,7 +4218,7 @@
  */
 static void
 tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial,
-				  GList **matches, char *name)
+				  GList **matches, const char *name)
 {
 	memcpy(nick_partial, name, entered_bytes);
 	if (purple_utf8_strcasecmp(nick_partial, entered))
@@ -4222,7 +4340,7 @@
 		/* Users */
 		for (; l != NULL; l = l->next) {
 			tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
-									  &matches, ((PurpleConvChatBuddy *)l->data)->name);
+									  &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data));
 		}
 
 
@@ -4320,9 +4438,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)
@@ -4397,6 +4515,7 @@
 {
 	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
 	PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
+	PurpleAccount *account = purple_conversation_get_account(conv);
 	GtkTreeModel *model;
 	char *normalized_name;
 	GtkTreeIter iter;
@@ -4411,23 +4530,23 @@
 	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
 		return;
 
-	normalized_name = g_strdup(purple_normalize(conv->account, buddy->name));
+	normalized_name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy)));
 
 	do {
 		char *name;
 
 		gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
 
-		if (!strcmp(normalized_name, purple_normalize(conv->account, name))) {
+		if (!strcmp(normalized_name, purple_normalize(account, name))) {
 			const char *alias = name;
 			char *tmp;
 			char *alias_key = NULL;
 			PurpleBuddy *buddy2;
 
-			if (strcmp(chat->nick, purple_normalize(conv->account, name))) {
+			if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) {
 				/* This user is not me, so look into updating the alias. */
 
-				if ((buddy2 = purple_find_buddy(conv->account, name)) != NULL) {
+				if ((buddy2 = purple_find_buddy(account, name)) != NULL) {
 					alias = purple_buddy_get_contact_alias(buddy2);
 				}
 
@@ -4462,10 +4581,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;
@@ -4514,14 +4633,14 @@
 	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
 		return;
 
-	normalized_name = g_strdup(purple_normalize(conv->account, buddy->name));
+	normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_buddy_get_name(buddy)));
 
 	do {
 		char *name;
 
 		gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1);
 
-		if (!strcmp(normalized_name, purple_normalize(conv->account, name))) {
+		if (!strcmp(normalized_name, purple_normalize(purple_conversation_get_account(conv), name))) {
 			gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 			                   CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1);
 			g_free(name);
@@ -4600,7 +4719,7 @@
 	GdkRectangle oneline;
 	int height, diff;
 	int pad_top, pad_inside, pad_bottom;
-	int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height);
+	int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height);
 	int max_height = total_height / 2;
 	int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines");
 	int min_height;
@@ -4672,8 +4791,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;
@@ -4714,7 +4833,7 @@
 	PurpleAccount *account = purple_conversation_get_account(conv);
 	char *who = NULL;
 
-	if (account->gc == NULL)
+	if (purple_account_get_connection(account) == NULL)
 		return FALSE;
 
 	if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
@@ -4722,8 +4841,8 @@
 
 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl);
-	node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who));
+	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);
 
@@ -4824,7 +4943,7 @@
 
 	gtkchat->list = list;
 
-	gtk_box_pack_start(GTK_BOX(lbox), 
+	gtk_box_pack_start(GTK_BOX(lbox),
 		pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1),
 		TRUE, TRUE, 0);
 }
@@ -4838,15 +4957,15 @@
 
 	conv = gtkconv->active_conv;
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
-		node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name));
+		node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
 		if (!node)
-			node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat");
+			node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
 	} else {
-		node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name));
+		node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)));
 #if 0
 		/* Using the transient blist nodes to show the tooltip doesn't quite work yet. */
 		if (!node)
-			node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy");
+			node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy");
 #endif
 	}
 
@@ -4861,7 +4980,7 @@
 {
 	gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
 
-	gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml));
+	webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview));
 	gtk_widget_hide_all(gtkconv->quickfind.container);
 
 	gtk_widget_grab_focus(gtkconv->entry);
@@ -4874,7 +4993,7 @@
 	switch (event->keyval) {
 		case GDK_Return:
 		case GDK_KP_Enter:
-			if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) {
+			if (webkit_web_view_search_text(WEBKIT_WEB_VIEW(gtkconv->webview), gtk_entry_get_text(GTK_ENTRY(entry)), FALSE, TRUE, TRUE)) {
 				gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
 			} else {
 				GdkColor col;
@@ -4924,16 +5043,181 @@
 
 /* }}} */
 
+static char *
+replace_header_tokens(PurpleConversation *conv, const char *text)
+{
+	PurpleAccount *account = purple_conversation_get_account(conv);
+	GString *str;
+	const char *cur = text;
+	const char *prev = cur;
+
+	if (text == NULL || *text == '\0')
+		return NULL;
+
+	str = g_string_new(NULL);
+	while ((cur = strchr(cur, '%'))) {
+		const char *replace = NULL;
+		const char *fin = NULL;
+
+		if (g_str_has_prefix(cur, "%chatName%")) {
+			replace = purple_conversation_get_name(conv);
+
+		} else if (g_str_has_prefix(cur, "%sourceName%")) {
+			replace = purple_account_get_alias(account);
+			if (replace == NULL)
+				replace = purple_account_get_username(account);
+
+		} else if (g_str_has_prefix(cur, "%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 (g_str_has_prefix(cur, "%incomingIconPath%")) {
+			PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
+			if (icon)
+				replace = purple_buddy_icon_get_full_path(icon);
+
+		} else if (g_str_has_prefix(cur, "%outgoingIconPath%")) {
+			replace = purple_account_get_buddy_icon_path(account);
+
+		} else if (g_str_has_prefix(cur, "%timeOpened")) {
+			const char *tmp = cur + strlen("%timeOpened");
+			char *format = NULL;
+			if (*tmp == '{') {
+				const char *end;
+				tmp++;
+				end = strstr(tmp, "}%");
+				if (!end) /* Invalid string */
+					continue;
+				format = g_strndup(tmp, end - tmp);
+				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);
+		if (replace)
+			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(PidginConvTheme *theme, const char *header, const char *footer)
+{
+	GString *str;
+	const char *text;
+	char **ms;
+	char *path;
+
+	text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN);
+	if (text == NULL)
+		return NULL;
+
+	ms = g_strsplit(text, "%@", 6);
+	if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) {
+		g_strfreev(ms);
+		return NULL;
+	}
+
+	str = g_string_new(NULL);
+
+	g_string_append(str, ms[0]);
+	g_string_append(str, "file://");
+	path = pidgin_conversation_theme_get_template_path(theme);
+	g_string_append(str, path);
+	g_free(path);
+
+	g_string_append(str, ms[1]);
+
+	text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS);
+	g_string_append(str, text);
+
+	g_string_append(str, ms[2]);
+
+	g_string_append(str, "file://");
+	path = pidgin_conversation_theme_get_css_path(theme);
+	g_string_append(str, path);
+	g_free(path);
+
+	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);
+
+	return g_string_free(str, FALSE);
+}
+
+static void
+set_theme_webkit_settings(WebKitWebView *webview, PidginConvTheme *theme)
+{
+	WebKitWebSettings *settings;
+	const GValue *val;
+
+	g_object_get(G_OBJECT(webview), "settings", &settings, NULL);
+
+	val = pidgin_conversation_theme_lookup(theme, "DefaultFontFamily", TRUE);
+	if (val && G_VALUE_HOLDS_STRING(val))
+		g_object_set(G_OBJECT(settings), "default-font-family", g_value_get_string(val), NULL);
+
+	val = pidgin_conversation_theme_lookup(theme, "DefaultFontSize", TRUE);
+	if (val && G_VALUE_HOLDS_INT(val))
+		g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(g_value_get_int(val)), NULL);
+
+	val = pidgin_conversation_theme_lookup(theme, "DefaultBackgroundIsTransparent", TRUE);
+	if (val && G_VALUE_HOLDS_BOOLEAN(val))
+		/* this does not work :( */
+		webkit_web_view_set_transparent(webview, g_value_get_boolean(val));
+}
+
+static void
+conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data)
+{
+	PidginConversation *gtkconv = user_data;
+	const char *path;
+	char *js;
+
+	path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject));
+	js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path);
+	gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js);
+	g_free(js);
+}
+
 static GtkWidget *
 setup_common_pane(PidginConversation *gtkconv)
 {
-	GtkWidget *vbox, *frame, *imhtml_sw, *event_box;
+	GtkWidget *vbox, *frame, *webview_sw, *event_box;
 	GtkCellRenderer *rend;
 	GtkTreePath *path;
 	PurpleConversation *conv = gtkconv->active_conv;
 	PurpleBuddy *buddy;
-	gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT);
+	gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT);
 	int buddyicon_size = 0;
+	char *header, *footer;
+	char *template;
 
 	/* Setup the top part of the pane */
 	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
@@ -5023,9 +5307,41 @@
 	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL);
 	g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL);
 
-	/* Setup the gtkimhtml widget */
-	frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
-	gtk_widget_set_size_request(gtkconv->imhtml, -1, 0);
+	/* Setup the webkit widget */
+	frame = pidgin_create_webview(FALSE, &gtkconv->webview, NULL, &webview_sw);
+	gtk_widget_set_size_request(gtkconv->webview, -1, 0);
+
+	header = replace_header_tokens(conv,
+		pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER));
+	footer = replace_header_tokens(conv,
+		pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER));
+	template = replace_template_tokens(gtkconv->theme, header, footer);
+	g_free(header);
+	g_free(footer);
+
+	if (template != NULL) {
+		char *basedir;
+		char *baseuri;
+
+		purple_debug_info("webkit", "template: %s\n", template);
+
+		set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme);
+
+		basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme);
+		baseuri = g_strdup_printf("file://%s", basedir);
+		webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, "text/html", "UTF-8", baseuri);
+
+		if (chat)
+			gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), "document.getElementById('Chat').className = 'groupchat'");
+
+		g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant",
+		                 G_CALLBACK(conv_variant_changed_cb), gtkconv);
+
+		g_free(basedir);
+		g_free(baseuri);
+		g_free(template);
+	}
+
 	if (chat) {
 		GtkWidget *hpaned;
 
@@ -5043,19 +5359,16 @@
 	} else {
 		gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 	}
-	gtk_widget_show(frame);
-
-	gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
-	gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
-	g_object_set_data(G_OBJECT(gtkconv->imhtml), "gtkconv", gtkconv);
-
-	g_object_set(G_OBJECT(imhtml_sw), "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
-
-	g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event",
+	gtk_widget_show_all(frame);
+
+	gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview");
+	g_object_set_data(G_OBJECT(gtkconv->webview), "gtkconv", gtkconv);
+
+	g_signal_connect_after(G_OBJECT(gtkconv->webview), "button_press_event",
 	                       G_CALLBACK(entry_stop_rclick_cb), NULL);
-	g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event",
+	g_signal_connect(G_OBJECT(gtkconv->webview), "key_press_event",
 	                 G_CALLBACK(refocus_entry_cb), gtkconv);
-	g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
+	g_signal_connect(G_OBJECT(gtkconv->webview), "key_release_event",
 	                 G_CALLBACK(refocus_entry_cb), gtkconv);
 
 	pidgin_conv_setup_quickfind(gtkconv, vbox);
@@ -5071,7 +5384,7 @@
 
 	gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
 	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
-			purple_account_get_protocol_name(conv->account));
+			purple_account_get_protocol_name(purple_conversation_get_account(conv)));
 
 	g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
 	                 G_CALLBACK(entry_popup_menu_cb), gtkconv);
@@ -5118,7 +5431,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))
 	{
@@ -5238,7 +5551,7 @@
 static PidginConversation *
 pidgin_conv_find_gtkconv(PurpleConversation * conv)
 {
-	PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name);
+	PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
 	PurpleContact *c;
 	PurpleBlistNode *cn, *bn;
 
@@ -5252,9 +5565,9 @@
 	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->ui_data)
-				return conv->ui_data;
+		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);
 		}
 	}
 
@@ -5296,6 +5609,8 @@
 
 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv)
 {
+/* TODO WEBKIT */
+#if 0
 	static PangoFontDescription *font_desc = NULL;
 	static GdkColor *color = NULL;
 	static gboolean enable = TRUE;
@@ -5326,6 +5641,7 @@
 	}
 
 	g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv);
+#endif /* if 0 */
 }
 
 /**************************************************************************
@@ -5335,6 +5651,7 @@
 private_gtkconv_new(PurpleConversation *conv, gboolean hidden)
 {
 	PidginConversation *gtkconv;
+	PurpleTheme *theme;
 	PurpleConversationType conv_type = purple_conversation_get_type(conv);
 	GtkWidget *pane = NULL;
 	GtkWidget *tab_cont;
@@ -5342,7 +5659,7 @@
 	PurpleValue *value;
 
 	if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
-		conv->ui_data = gtkconv;
+		purple_conversation_set_ui_data(conv, gtkconv);
 		if (!g_list_find(gtkconv->convs, conv))
 			gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
 		pidgin_conv_switch_active_conversation(conv);
@@ -5350,7 +5667,7 @@
 	}
 
 	gtkconv = g_new0(PidginConversation, 1);
-	conv->ui_data = gtkconv;
+	purple_conversation_set_ui_data(conv, gtkconv);
 	gtkconv->active_conv = conv;
 	gtkconv->convs = g_list_prepend(gtkconv->convs, conv);
 	gtkconv->send_history = g_list_append(NULL, NULL);
@@ -5359,6 +5676,11 @@
 	gtkconv->tooltips = gtk_tooltips_new();
 	gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
 	gtkconv->unseen_count = 0;
+	theme = purple_theme_manager_find_theme(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme"), "conversation");
+	if (!theme)
+		theme = purple_theme_manager_find_theme("Default", "conversation");
+	gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme));
+	gtkconv->last_flags = 0;
 
 	if (conv_type == PURPLE_CONV_TYPE_IM) {
 		gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
@@ -5367,9 +5689,6 @@
 	}
 	pane = setup_common_pane(gtkconv);
 
-	gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml),
-			gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE);
-
 	if (pane == NULL) {
 		if (conv_type == PURPLE_CONV_TYPE_CHAT)
 			g_free(gtkconv->u.chat);
@@ -5377,7 +5696,7 @@
 			g_free(gtkconv->u.im);
 
 		g_free(gtkconv);
-		conv->ui_data = NULL;
+		purple_conversation_set_ui_data(conv, NULL);
 		return;
 	}
 
@@ -5392,7 +5711,7 @@
 	                  GTK_DEST_DEFAULT_DROP,
 	                  te, sizeof(te) / sizeof(GtkTargetEntry),
 	                  GDK_ACTION_COPY);
-	gtk_drag_dest_set(gtkconv->imhtml, 0,
+	gtk_drag_dest_set(gtkconv->webview, 0,
 	                  te, sizeof(te) / sizeof(GtkTargetEntry),
 	                  GDK_ACTION_COPY);
 
@@ -5404,12 +5723,12 @@
 	                 G_CALLBACK(ignore_middle_click), NULL);
 	g_signal_connect(G_OBJECT(pane), "drag_data_received",
 	                 G_CALLBACK(conv_dnd_recv), gtkconv);
-	g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received",
+	g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received",
 	                 G_CALLBACK(conv_dnd_recv), gtkconv);
 	g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received",
 	                 G_CALLBACK(conv_dnd_recv), gtkconv);
 
-	g_signal_connect(gtkconv->imhtml, "style-set", G_CALLBACK(set_typing_font), gtkconv);
+	g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv);
 
 	/* Setup the container for the tab. */
 	gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
@@ -5439,10 +5758,6 @@
 	else
 		gtk_widget_hide(gtkconv->infopane_hbox);
 
-	gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
-		purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
-	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml),
-								 purple_account_get_protocol_name(conv->account));
 
 	g_signal_connect_swapped(G_OBJECT(pane), "focus",
 	                         G_CALLBACK(gtk_widget_grab_focus),
@@ -5455,10 +5770,10 @@
 
 	if (nick_colors == NULL) {
 		nbr_nick_colors = NUM_NICK_COLORS;
-		nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]);
-	}
-
-	if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
+		nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]);
+	}
+
+	if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
 		pidgin_themes_smiley_themeize_custom(gtkconv->entry);
 }
 
@@ -5569,6 +5884,10 @@
 		g_source_remove(gtkconv->attach.timer);
 	}
 
+	g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify",
+	                    conv_variant_changed_cb, gtkconv, NULL);
+	g_object_unref(gtkconv->theme);
+
 	g_free(gtkconv);
 }
 
@@ -5596,6 +5915,7 @@
 	purple_conversation_write(conv, who, message, flags, mtime);
 }
 
+#if 0
 static const char *
 get_text_tag_color(GtkTextTag *tag)
 {
@@ -5659,7 +5979,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);
@@ -5676,10 +5996,13 @@
 
 	return FALSE;
 }
+#endif
 
 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag,
 		gboolean create)
 {
+/* TODO WEBKIT */
+#if 0
 	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
 	GtkTextTag *buddytag;
 	gchar *str;
@@ -5713,8 +6036,11 @@
 	g_free(str);
 
 	return buddytag;
-}
-
+#endif /* if 0 */
+	return NULL;
+}
+
+#if 0
 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime)
 {
 	struct tm *tm = localtime(&mtime);
@@ -5760,6 +6086,105 @@
 	*str = ret;
 #endif
 }
+#endif
+
+static char *
+replace_message_tokens(
+	const char *text,
+	PurpleConversation *conv,
+	const char *name,
+	const char *alias,
+	const char *message,
+	PurpleMessageFlags flags,
+	time_t mtime)
+{
+	GString *str;
+	const char *cur = text;
+	const char *prev = cur;
+
+	if (text == NULL)
+		return g_strdup("");
+
+	str = g_string_new(NULL);
+	while ((cur = strchr(cur, '%'))) {
+		const char *replace = NULL;
+		const char *fin = NULL;
+
+		if (g_str_has_prefix(cur, "%message%")) {
+			replace = message;
+
+		} else if (g_str_has_prefix(cur, "%messageClasses%")) {
+			replace = flags & PURPLE_MESSAGE_SEND ? "outgoing" :
+				  flags & PURPLE_MESSAGE_RECV ? "incoming" : "event";
+
+		} else if (g_str_has_prefix(cur, "%time")) {
+			const char *tmp = cur + strlen("%time");
+			char *format = NULL;
+			if (*tmp == '{') {
+				char *end;
+				tmp++;
+				end = strstr(tmp, "}%");
+				if (!end) /* Invalid string */
+					continue;
+				format = g_strndup(tmp, end - tmp);
+				fin = end + 1;
+			}
+			replace = purple_utf8_strftime(format ? format : "%X", NULL);
+			g_free(format);
+
+		} 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)) {
+					replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
+				} else {
+					PurpleStoredImage *img = purple_buddy_icons_find_account_icon(purple_conversation_get_account(conv));
+					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));
+				if (icon)
+					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 (g_str_has_prefix(cur, "%senderScreenName%")) {
+			replace = name;
+
+		} else if (g_str_has_prefix(cur, "%sender%")) {
+			replace = alias;
+
+		} else if (g_str_has_prefix(cur, "%service%")) {
+			replace = purple_account_get_protocol_name(purple_conversation_get_account(conv));
+
+		} else {
+			cur++;
+			continue;
+		}
+
+		/* Here we have a replacement to make */
+		g_string_append_len(str, prev, cur - prev);
+		if (replace)
+			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 void
 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias,
@@ -5769,23 +6194,31 @@
 	PidginConversation *gtkconv;
 	PurpleConnection *gc;
 	PurpleAccount *account;
+#if 0
 	int gtk_font_options = 0;
 	int gtk_font_options_all = 0;
-	int max_scrollback_lines;
-	int line_count;
 	char buf2[BUF_LONG];
 	gboolean show_date;
 	char *mdate;
 	char *str;
 	char *with_font_tag;
 	char *sml_attrib = NULL;
+#endif
 	size_t length;
 	PurpleConversationType type;
 	char *displaying;
 	gboolean plugin_return;
-	char *bracket;
-	int tag_count = 0;
+#if 0
 	gboolean is_rtl_message = FALSE;
+#endif
+
+	const char *message_html;
+	char *msg;
+	char *escape;
+	char *script;
+	char *smileyed;
+	PurpleMessageFlags old_flags;
+	const char *func = "appendMessage";
 
 	g_return_if_fail(conv != NULL);
 	gtkconv = PIDGIN_CONVERSATION(conv);
@@ -5842,56 +6275,39 @@
 	}
 	length = strlen(displaying) + 1;
 
-	/* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes.
-	 * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually
-	 * needs that much formatting, anyway.
-	 */
-	for (bracket = strchr(displaying, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<'))
-		tag_count++;
-
-	if (tag_count > 100) {
-		char *tmp = displaying;
-		displaying = purple_markup_strip_html(tmp);
-		g_free(tmp);
-	}
-
-	line_count = gtk_text_buffer_get_line_count(
-			gtk_text_view_get_buffer(GTK_TEXT_VIEW(
-				gtkconv->imhtml)));
-
-	max_scrollback_lines = purple_prefs_get_int(
-		PIDGIN_PREFS_ROOT "/conversations/scrollback_lines");
-	/* If we're sitting at more than 100 lines more than the
-	   max scrollback, trim down to max scrollback */
-	if (max_scrollback_lines > 0
-			&& line_count > (max_scrollback_lines + 100)) {
-		GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(
-			GTK_TEXT_VIEW(gtkconv->imhtml));
-		GtkTextIter start, end;
-
-		gtk_text_buffer_get_start_iter(text_buffer, &start);
-		gtk_text_buffer_get_iter_at_line(text_buffer, &end,
-			(line_count - max_scrollback_lines));
-		gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end);
-	}
-
-	if (type == PURPLE_CONV_TYPE_CHAT)
-	{
-		/* Create anchor for user */
-		GtkTextIter iter;
-		char *tmp = g_strconcat("user:", name, NULL);
-
-		gtk_text_buffer_get_end_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), &iter);
-		gtk_text_buffer_create_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)),
-								tmp, &iter, TRUE);
-		g_free(tmp);
-	}
-
-	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling"))
-		gtk_font_options_all |= GTK_IMHTML_USE_SMOOTHSCROLLING;
-
-	if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml))))
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
+	old_flags = gtkconv->last_flags;
+	if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) {
+		message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT);
+		func = "appendNextMessage";
+	} else if (flags & PURPLE_MESSAGE_SEND) {
+		message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT);
+	} else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) {
+		message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT);
+		func = "appendNextMessage";
+	} else if (flags & PURPLE_MESSAGE_RECV) {
+		message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
+	} else {
+		message_html = pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS);
+	}
+	gtkconv->last_flags = flags;
+
+	smileyed = smiley_parse_markup(message, purple_account_get_protocol_id(account));
+	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(gtkconv->webview), script);
+
+	g_free(script);
+	g_free(smileyed);
+	g_free(msg);
+	g_free(escape);
+
+#if 0
+	/* if the buffer is not empty add a <br> */
+	if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview)))
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<br />");
 
 	/* First message in a conversation. */
 	if (gtkconv->newday == 0)
@@ -5934,40 +6350,40 @@
 		gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING;
 
 	/* this is gonna crash one day, I can feel it. */
-	if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(conv->account)))->options &
+	if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(purple_conversation_get_account(conv))))->options &
 	    OPT_PROTO_USE_POINTSIZE) {
 		gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
 	}
 
-	if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
+	if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
 	{
 		/* We want to see our own smileys. Need to revert it after send*/
-		pidgin_themes_smiley_themeize_custom(gtkconv->imhtml);
+		pidgin_themes_smiley_themeize_custom(gtkconv->webview);
 	}
 
 	/* TODO: These colors should not be hardcoded so log.c can use them */
 	if (flags & PURPLE_MESSAGE_RAW) {
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), message);
 	} else if (flags & PURPLE_MESSAGE_SYSTEM) {
 		g_snprintf(buf2, sizeof(buf2),
-			   "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT>",
+			   "<font %s><font size=\"2\"><span class='timestamp'>%s</span></font><b>%s</b></font>",
 			   sml_attrib ? sml_attrib : "", mdate, displaying);
 
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
 
 	} else if (flags & PURPLE_MESSAGE_ERROR) {
 		g_snprintf(buf2, sizeof(buf2),
-			   "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT></FONT>",
+			   "<font color=\"#ff0000\"><font %s><font size=\"2\"><span class='timestamp'>%s</span> </font><b>%s</b></font></font>",
 			   sml_attrib ? sml_attrib : "", mdate, displaying);
 
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
 
 	} else if (flags & PURPLE_MESSAGE_NO_LOG) {
 		g_snprintf(buf2, BUF_LONG,
-			   "<B><FONT %s COLOR=\"#777777\">%s</FONT></B>",
+			   "<b><font %s color=\"#777777\">%s</font></b>",
 			   sml_attrib ? sml_attrib : "", displaying);
 
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
 	} else {
 		char *new_message = g_memdup(displaying, length);
 		char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup(""));
@@ -5977,11 +6393,6 @@
 		int tag_end_offset = 0;
 		const char *tagname = NULL;
 
-		GtkTextIter start, end;
-		GtkTextMark *mark;
-		GtkTextTag *tag;
-		GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer;
-
 		/* Enforce direction on alias */
 		if (is_rtl_message)
 			str_embed_direction_chars(&alias_escaped);
@@ -6042,55 +6453,41 @@
 
 		g_free(alias_escaped);
 
+		/* TODO WEBKIT */
+#if 0
 		if (tagname)
 			tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname);
 		else
 			tag = get_buddy_tag(conv, name, flags, TRUE);
 
 		if (GTK_IMHTML(gtkconv->imhtml)->show_comments) {
+		{
 			/* The color for the timestamp has to be set in the font-tags, unfortunately.
 			 * Applying the nick-tag to timestamps would work, but that can make it
 			 * bold. I thought applying the "comment" tag again, which has "weight" set
 			 * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So
 			 * this will have to do. I don't terribly like it.  -- sadrul */
-			const char *color = get_text_tag_color(tag);
+			/* const char *color = get_text_tag_color(tag); */
 			g_snprintf(buf2, BUF_LONG, "<FONT %s%s%s SIZE=\"2\"><!--%s --></FONT>",
 					color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate);
-			gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
-		}
-
-		gtk_text_buffer_get_end_iter(buffer, &end);
-		mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE);
-
-		g_snprintf(buf2, BUF_LONG, "<FONT %s>%s</FONT> ", sml_attrib ? sml_attrib : "", str);
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL);
-
-		gtk_text_buffer_get_end_iter(buffer, &end);
-		gtk_text_buffer_get_iter_at_mark(buffer, &start, mark);
-		gtk_text_buffer_apply_tag(buffer, tag, &start, &end);
-		gtk_text_buffer_delete_mark(buffer, mark);
+			gtk_webview_append_html (GTK_WEBVIEW(gtkconv->webview), buf2);
+		}
+#endif /* if 0 */
+		g_snprintf(buf2, BUF_LONG, "<font %s>%s</font> ", sml_attrib ? sml_attrib : "", str);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2);
 
 		g_free(str);
 
-		if(gc){
+		if (gc) {
 			char *pre = g_strdup_printf("<font %s>", sml_attrib ? sml_attrib : "");
 			char *post = "</font>";
-			int pre_len = strlen(pre);
-			int post_len = strlen(post);
-
-			with_font_tag = g_malloc(length + pre_len + post_len + 1);
-
-			strcpy(with_font_tag, pre);
-			memcpy(with_font_tag + pre_len, new_message, length);
-			strcpy(with_font_tag + pre_len + length, post);
-
-			length += pre_len + post_len;
+			with_font_tag = g_strdup_printf("%s%s%s", pre, new_message, post);
 			g_free(pre);
 		} else
 			with_font_tag = g_memdup(new_message, length);
 
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml),
-							 with_font_tag, gtk_font_options | gtk_font_options_all);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview),
+							 with_font_tag);
 
 		g_free(with_font_tag);
 		g_free(new_message);
@@ -6099,6 +6496,8 @@
 	g_free(mdate);
 	g_free(sml_attrib);
 
+#endif
+
 	/* Tab highlighting stuff */
 	if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv))
 	{
@@ -6117,11 +6516,13 @@
 		gtkconv_set_unseen(gtkconv, unseen);
 	}
 
-	if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
+#if 0
+	if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY))
 	{
 		/* Restore the smiley-data */
-		pidgin_themes_smiley_themeize(gtkconv->imhtml);
-	}
+		pidgin_themes_smiley_themeize(gtkconv->webview);
+	}
+#endif
 
 	purple_signal_emit(pidgin_conversations_get_handle(),
 		(type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"),
@@ -6132,7 +6533,7 @@
 
 static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter)
 {
-	GtkTreeRowReference *ref = cb->ui_data;
+	GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb);
 	GtkTreePath *path;
 	GtkTreeModel *model;
 
@@ -6218,11 +6619,11 @@
 
 	old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
 	if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
-		GtkTreeRowReference *ref = old_cbuddy->ui_data;
+		GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy);
 
 		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
 		gtk_tree_row_reference_free(ref);
-		old_cbuddy->ui_data = NULL;
+		purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL);
 	}
 
 	if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
@@ -6316,10 +6717,10 @@
 
 	cbuddy = purple_conv_chat_cb_find(chat, user);
 	if (get_iter_from_chatbuddy(cbuddy, &iter)) {
-		GtkTreeRowReference *ref = cbuddy->ui_data;
+		GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy);
 		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
 		gtk_tree_row_reference_free(ref);
-		cbuddy->ui_data = NULL;
+		purple_conv_chat_cb_set_ui_data(cbuddy, NULL);
 	}
 
 	if (cbuddy)
@@ -6366,6 +6767,13 @@
 }
 
 static gboolean
+add_custom_smiley_for_webview(GtkWebView *webview, const char *sml, const char *smile)
+{
+	/* TODO WEBKIT: Smileys need to be added to webkit stuff */
+	return TRUE;
+}
+
+static gboolean
 pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote)
 {
 	PidginConversation *gtkconv;
@@ -6382,7 +6790,7 @@
 
 	/* If possible add this smiley to the current theme.
 	 * The addition is only temporary: custom smilies aren't saved to disk. */
-	conv_sml = purple_account_get_protocol_name(conv->account);
+	conv_sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
 	for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) {
@@ -6392,7 +6800,7 @@
 		}
 	}
 
-	if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->imhtml), sml, smile))
+	if (!add_custom_smiley_for_webview(GTK_WEBVIEW(gtkconv->webview), sml, smile))
 		return FALSE;
 
 	if (!remote)	/* If it's a local custom smiley, then add it for the entry */
@@ -6406,12 +6814,14 @@
 pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile,
                                       const guchar *data, gsize size)
 {
+/* TODO WEBKIT */
+#if 0
 	PidginConversation *gtkconv;
 	GtkIMHtmlSmiley *smiley;
 	const char *sml;
 	GError *error = NULL;
 
-	sml = purple_account_get_protocol_name(conv->account);
+	sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
 
@@ -6427,7 +6837,7 @@
 
 	if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) {
 		purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() "
-				"failed with size=%zu: %s\n", size,
+				"failed with size=%" G_GSIZE_FORMAT ": %s\n", size,
 				error ? error->message : "(no error message)");
 		if (error)
 			g_error_free(error);
@@ -6440,11 +6850,14 @@
 		g_object_unref(G_OBJECT(smiley->loader));
 		smiley->loader = gdk_pixbuf_loader_new();
 	}
+#endif /* if 0 */
 }
 
 static void
 pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile)
 {
+/* TODO WEBKIT */
+#if 0
 	PidginConversation *gtkconv;
 	GtkIMHtmlSmiley *smiley;
 	const char *sml;
@@ -6453,7 +6866,7 @@
 	g_return_if_fail(conv  != NULL);
 	g_return_if_fail(smile != NULL);
 
-	sml = purple_account_get_protocol_name(conv->account);
+	sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
 
@@ -6481,6 +6894,7 @@
 		g_object_unref(G_OBJECT(smiley->loader));
 		smiley->loader = gdk_pixbuf_loader_new();
 	}
+#endif /* if 0 */
 }
 
 static void
@@ -6508,11 +6922,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);
@@ -6531,7 +6945,7 @@
 		/* Deal with menu items */
 		gtk_widget_show(win->menu.view_log);
 		gtk_widget_show(win->menu.send_file);
-		gtk_widget_show(g_object_get_data(G_OBJECT(win->window), "get_attention"));
+		gtk_widget_show(win->menu.get_attention);
 		gtk_widget_show(win->menu.add_pounce);
 		gtk_widget_show(win->menu.get_info);
 		gtk_widget_hide(win->menu.invite);
@@ -6560,7 +6974,7 @@
 		/* Deal with menu items */
 		gtk_widget_show(win->menu.view_log);
 		gtk_widget_hide(win->menu.send_file);
-		gtk_widget_hide(g_object_get_data(G_OBJECT(win->window), "get_attention"));
+		gtk_widget_hide(win->menu.get_attention);
 		gtk_widget_hide(win->menu.add_pounce);
 		gtk_widget_hide(win->menu.get_info);
 		gtk_widget_show(win->menu.invite);
@@ -6590,31 +7004,35 @@
 		((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) ||
 		 !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) ))
 	{
+		PurpleConnectionFlags features = purple_conversation_get_features(conv);
 		/* Account is online */
 		/* Deal with the toolbar */
-		if (conv->features & PURPLE_CONNECTION_HTML)
+		if (features & PURPLE_CONNECTION_HTML)
 		{
 			buttons = GTK_IMHTML_ALL; /* Everything on */
-			if (conv->features & PURPLE_CONNECTION_NO_BGCOLOR)
+			if (features & PURPLE_CONNECTION_NO_BGCOLOR)
 				buttons &= ~GTK_IMHTML_BACKCOLOR;
-			if (conv->features & PURPLE_CONNECTION_NO_FONTSIZE)
+			if (features & PURPLE_CONNECTION_NO_FONTSIZE)
 			{
 				buttons &= ~GTK_IMHTML_GROW;
 				buttons &= ~GTK_IMHTML_SHRINK;
 			}
-			if (conv->features & PURPLE_CONNECTION_NO_URLDESC)
+			if (features & PURPLE_CONNECTION_NO_URLDESC)
 				buttons &= ~GTK_IMHTML_LINKDESC;
 		} else {
 			buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE;
 		}
 
-		if (!(prpl_info->options & OPT_PROTO_IM_IMAGE))
-			conv->features |= PURPLE_CONNECTION_NO_IMAGES;
-
-		if(conv->features & PURPLE_CONNECTION_NO_IMAGES)
+		if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)
+		 && !(features & PURPLE_CONNECTION_NO_IMAGES)) {
+			features |= PURPLE_CONNECTION_NO_IMAGES;
+			purple_conversation_set_features(conv, features);
+		}
+
+		if (features & PURPLE_CONNECTION_NO_IMAGES)
 			buttons &= ~GTK_IMHTML_IMAGE;
 
-		if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
+		if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
 			buttons |= GTK_IMHTML_CUSTOM_SMILEY;
 		else
 			buttons &= ~GTK_IMHTML_CUSTOM_SMILEY;
@@ -6628,17 +7046,17 @@
 		gtk_widget_set_sensitive(win->menu.add_pounce, TRUE);
 		gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
 		gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
-		gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML));
-		gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES));
+		gtk_widget_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML));
+		gtk_widget_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 		{
-			gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL));
+			gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL));
 			gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL));
 			gtk_widget_set_sensitive(win->menu.send_file,
 									 (prpl_info->send_file != NULL && (!prpl_info->can_receive_file ||
 									  prpl_info->can_receive_file(gc, purple_conversation_get_name(conv)))));
-			gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL));
+			gtk_widget_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL));
 			gtk_widget_set_sensitive(win->menu.alias,
 									 (account != NULL) &&
 									 (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL));
@@ -6659,8 +7077,7 @@
 		/* Then deal with menu items */
 		gtk_widget_set_sensitive(win->menu.view_log, TRUE);
 		gtk_widget_set_sensitive(win->menu.send_file, FALSE);
-		gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window),
-			"get_attention"), FALSE);
+		gtk_widget_set_sensitive(win->menu.get_attention, FALSE);
 		gtk_widget_set_sensitive(win->menu.add_pounce, TRUE);
 		gtk_widget_set_sensitive(win->menu.get_info, FALSE);
 		gtk_widget_set_sensitive(win->menu.invite, FALSE);
@@ -6680,7 +7097,7 @@
 		if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) &&
 				(gtkconv->u.im->anim))
 		{
-			PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name);
+			PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
 			window_icon =
 				gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim);
 
@@ -6753,8 +7170,10 @@
 		}
 	}
 
+#if 0
 	if (fields & PIDGIN_CONV_SMILEY_THEME)
-		pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml);
+		pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview);
+#endif
 
 	if ((fields & PIDGIN_CONV_COLORIZE_TITLE) ||
 			(fields & PIDGIN_CONV_SET_TITLE) ||
@@ -6781,7 +7200,7 @@
 			title = g_strdup(purple_conversation_get_title(conv));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-			buddy = purple_find_buddy(account, conv->name);
+			buddy = purple_find_buddy(account, purple_conversation_get_name(conv));
 			if (buddy) {
 				markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE);
 			} else {
@@ -6826,7 +7245,7 @@
 			style = "tab-label-attention";
 		} else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT)	{
 			atk_object_set_description(accessibility_obj, _("Unread Messages"));
-			if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT)
+			if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT)
 				style = "tab-label-unreadchat";
 			else
 				style = "tab-label-attention";
@@ -7038,7 +7457,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));
@@ -7332,8 +7751,11 @@
 		        GTK_CHECK_MENU_ITEM(win->menu.show_timestamps),
 		        (gboolean)GPOINTER_TO_INT(value));
 
+/* TODO WEBKIT: Use WebKit version of this. */
+#if 0
 		gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
 			(gboolean)GPOINTER_TO_INT(value));
+#endif /* if 0 */
 	}
 }
 
@@ -7501,7 +7923,7 @@
 
 		conv = gtkconv->active_conv;
 
-		if (conv->type == PURPLE_CONV_TYPE_CHAT ||
+		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT ||
 				gtkconv->unseen_count == 0 ||
 				(when_away && !purple_status_is_available(
 							purple_account_get_active_status(
@@ -7541,7 +7963,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);
 	}
@@ -7566,14 +7988,16 @@
 							PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE);
 
 		if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
-				conv->type == PURPLE_CONV_TYPE_CHAT &&
-				conv->account == gc->account &&
+				purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT &&
+				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(conv->account, conv->name);
+			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, conv->name);
+				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;
 			}
@@ -7642,7 +8066,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);
 }
@@ -7652,7 +8076,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);
 }
@@ -7717,7 +8141,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. */
@@ -7728,16 +8152,22 @@
 	int count = 0;
 	int timer = gtkconv->attach.timer;
 	time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time"));
-	gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM);
+	gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM);
 
 	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) {
-			gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0);
+		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 {
@@ -7760,16 +8190,22 @@
 			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);
-		}
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0);
+			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);
 	}
 
@@ -7845,16 +8281,16 @@
 				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(),
 				"conversation-displayed", gtkconv);
 	}
 
-	if (conv->type == PURPLE_CONV_TYPE_CHAT) {
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC);
-		pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE);
+		pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE);
 	}
 
 	return TRUE;
@@ -7876,6 +8312,7 @@
 
 	/* Conversations */
 	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations");
+	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/themes");
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE);
@@ -8159,6 +8596,8 @@
 	purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle,
 			PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL);
 
+	purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_CONV_THEME_LOADER, "type", "conversation", NULL));
+
 	{
 		/* Set default tab colors */
 		GString *str = g_string_new(NULL);
@@ -9047,13 +9486,13 @@
 		return FALSE;
 	}
 
-	if (!purple_account_is_connected(gtkconv->active_conv->account)) {
+	if (!purple_account_is_connected(purple_conversation_get_account(gtkconv->active_conv))) {
 		/* Do not allow aliasing someone on a disconnected account. */
 		return FALSE;
 	}
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
-		PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name);
+		PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv));
 		if (!buddy)
 			/* This buddy isn't in your buddy list, so we can't alias him */
 			return FALSE;
@@ -9063,9 +9502,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/gtkconv.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkconv.h	Mon Oct 31 01:25:36 2011 +0000
@@ -51,12 +51,12 @@
 	CHAT_USERS_FLAGS_COLUMN,
 	CHAT_USERS_COLOR_COLUMN,
 	CHAT_USERS_WEIGHT_COLUMN,
-	CHAT_USERS_ICON_STOCK_COLUMN,   /** @since 2.6.0 */
+	CHAT_USERS_ICON_STOCK_COLUMN,
 	CHAT_USERS_COLUMNS
 };
 
 #define PIDGIN_CONVERSATION(conv) \
-	((PidginConversation *)(conv)->ui_data)
+	((PidginConversation *)purple_conversation_get_ui_data(conv))
 
 #define PIDGIN_IS_PIDGIN_CONVERSATION(conv) \
 	(purple_conversation_get_ui_ops(conv) == \
@@ -65,6 +65,7 @@
 #include "pidgin.h"
 #include "conversation.h"
 #include "gtkconvwin.h"
+#include "gtkconv-theme.h"
 
 /**************************************************************************
  * @name Structures
@@ -77,39 +78,6 @@
  */
 
 /**
- * A GTK+ Instant Message pane.
- */
-struct _PidginImPane
-{
-	GtkWidget *block;
-	GtkWidget *send_file;
-	GtkWidget *sep1;
-	GtkWidget *sep2;
-	GtkWidget *check;
-	GtkWidget *progress;
-	guint32 typing_timer;
-
-	/* Buddy icon stuff */
-	GtkWidget *icon_container;
-	GtkWidget *icon;
-	gboolean show_icon;
-	gboolean animate;
-	GdkPixbufAnimation *anim;
-	GdkPixbufAnimationIter *iter;
-	guint32 icon_timer;
-};
-
-/**
- * GTK+ Chat panes.
- */
-struct _PidginChatPane
-{
-	GtkWidget *count;
-	GtkWidget *list;
-	GtkWidget *topic_text;
-};
-
-/**
  * A GTK+ conversation pane.
  */
 struct _PidginConversation
@@ -128,12 +96,14 @@
 	GtkWidget *tabby;
 	GtkWidget *menu_tabby;
 
-	GtkWidget *imhtml;
+	PidginConvTheme *theme;
+	PurpleMessageFlags last_flags;
+	GtkWidget *webview;
 	GtkTextBuffer *entry_buffer;
 	GtkWidget *entry;
 	gboolean auto_resize;   /* this is set to TRUE if the conversation
-		 	 	 * is being resized by a non-user-initiated
-		 		 * event, such as the buddy icon appearing
+				 * is being resized by a non-user-initiated
+				 * event, such as the buddy icon appearing
 				 */
 	gboolean entry_growing; /* True if the size of the entry was set
 				 * automatically by typing too much to fit
@@ -144,12 +114,6 @@
 	GtkWidget *tab_label;
 	GtkWidget *menu_icon;
 	GtkWidget *menu_label;
-#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKCONV_C_)
-	/** @deprecated */
-	GtkSizeGroup *sg;
-#else
-	gpointer depr1;
-#endif
 
 	GtkWidget *lower_hbox;
 
@@ -180,8 +144,6 @@
 
 	/**
 	 * Quick Find.
-	 *
-	 * @since 2.7.0
 	 */
 	struct {
 		GtkWidget *entry;
@@ -269,8 +231,6 @@
  * @param conv  The conversation.
  *
  * @return  Wheter Pidgin UI was successfully attached.
- *
- * @since 2.2.0
  */
 gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv);
 
--- a/pidgin/gtkconvwin.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkconvwin.h	Mon Oct 31 01:25:36 2011 +0000
@@ -51,6 +51,7 @@
 		GtkWidget *view_log;
 
 		GtkWidget *send_file;
+		GtkWidget *get_attention;
 		GtkWidget *add_pounce;
 		GtkWidget *get_info;
 		GtkWidget *invite;
--- a/pidgin/gtkdialogs.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkdialogs.c	Mon Oct 31 01:25:36 2011 +0000
@@ -39,10 +39,9 @@
 
 #include "gtkblist.h"
 #include "gtkdialogs.h"
-#include "gtkimhtml.h"
-#include "gtkimhtmltoolbar.h"
 #include "gtklog.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 #include "pidginstock.h"
 
 static GList *dialogwindows = NULL;
@@ -151,7 +150,7 @@
 	{N_("Assamese"),            "as", "Amitakhya Phukan", "aphukan@fedoraproject.org"},
 	{N_("Belarusian Latin"),    "be@latin", "Ihar Hrachyshka", "ihar.hrachyshka@gmail.com"},
 	{N_("Bulgarian"),           "bg", "Vladimira Girginova", "missing@here.is"},
-	{N_("Bulgarian"),           "bg", "Vladimir (Kaladan) Petkov", "vpetkov@i-space.org"},
+	{N_("Bulgarian"),           "bg", "Vladimir (Kaladan) Petkov", "kaladan@gmail.com"},
 	{N_("Bengali"),             "bn", "Israt Jahan", "israt@ankur.org.bd"},
 	{N_("Bengali"),             "bn", "Jamil Ahmed", "jamil@bengalinux.org"},
 	{N_("Bengali"),             "bn", "Samia Nimatullah", "mailsamia2001@yahoo.com"},
@@ -222,7 +221,6 @@
 	{N_("Oriya"),               "or", "Manoj Kumar Giri", "giri.manojkr@gmail.com"},
 	{N_("Punjabi"),             "pa", "Amanpreet Singh Alam", "aalam@users.sf.net"},
 	{N_("Polish"),              "pl", "Piotr Drąg", "piotrdrag@gmail.com"},
-	{N_("Polish"),              "pl", "Piotr Makowski", "pmakowski@aviary.pl"},
 	{N_("Portuguese"),          "pt", "Duarte Henriques", "duarte_henriques@myrealbox.com"},
 	{N_("Portuguese-Brazil"),   "pt_BR", "Rodrigo Luiz Marques Flores", "rodrigomarquesflores@gmail.com"},
 	{N_("Pashto"),              "ps", "Kashif Masood", "masudmails@yahoo.com"},
@@ -304,6 +302,7 @@
 	{N_("Polish"),              "pl", "Emil Nowak", "emil5@go2.pl"},
 	{N_("Polish"),              "pl", "Paweł Godlewski", "pawel@bajk.pl"},
 	{N_("Polish"),              "pl", "Krzysztof Foltman", "krzysztof@foltman.com"},
+	{N_("Polish"),              "pl", "Piotr Makowski", NULL},
 	{N_("Polish"),              "pl", "Przemysław Sułek", NULL},
 	{N_("Portuguese-Brazil"),   "pt_BR", "Maurício de Lemos Rodrigues Collares Neto", "mauricioc@gmail.com"},
 	{N_("Russian"),             "ru", "Dmitry Beloglazov", "dmaa@users.sf.net"},
@@ -422,9 +421,8 @@
 static GtkWidget *
 pidgin_build_help_dialog(const char *title, const char *role, GString *string)
 {
-	GtkWidget *win, *vbox, *frame, *logo, *imhtml, *button;
+	GtkWidget *win, *vbox, *frame, *logo, *webview, *button;
 	GdkPixbuf *pixbuf;
-	GtkTextIter iter;
 	AtkObject *obj;
 	char *filename, *tmp;
 
@@ -451,13 +449,15 @@
 	g_free(tmp);
 	gtk_box_pack_start(GTK_BOX(vbox), logo, FALSE, FALSE, 0);
 
-	frame = pidgin_create_imhtml(FALSE, &imhtml, NULL, NULL);
+	frame = pidgin_create_webview(FALSE, &webview, NULL, NULL);
+	/* TODO WEBKIT: Compile now and fix it later when we have a proper replacement for this function
 	gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml), GTK_IMHTML_ALL ^ GTK_IMHTML_SMILEY);
+	*/
 	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 
-	gtk_imhtml_append_text(GTK_IMHTML(imhtml), string->str, GTK_IMHTML_NO_SCROLL);
-	gtk_text_buffer_get_start_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml)), &iter);
-	gtk_text_buffer_place_cursor(gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml)), &iter);
+	gtk_webview_append_html(GTK_WEBVIEW(webview), string->str);
+	/* TODO WEBKIT: This doesn't seem to stay at the top. */
+	webkit_web_view_move_cursor(WEBKIT_WEB_VIEW(webview), GTK_MOVEMENT_BUFFER_ENDS, -1);
 
 	button = pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CLOSE,
 	                G_CALLBACK(destroy_win), win);
@@ -1114,26 +1114,6 @@
 }
 
 static void
-pidgin_dialogs_alias_contact_cb(PurpleContact *contact, const char *new_alias)
-{
-	purple_blist_alias_contact(contact, new_alias);
-}
-
-void
-pidgin_dialogs_alias_contact(PurpleContact *contact)
-{
-	g_return_if_fail(contact != NULL);
-
-	purple_request_input(NULL, _("Alias Contact"), NULL,
-					   _("Enter an alias for this contact."),
-					   contact->alias, FALSE, FALSE, NULL,
-					   _("Alias"), G_CALLBACK(pidgin_dialogs_alias_contact_cb),
-					   _("Cancel"), NULL,
-					   NULL, purple_contact_get_alias(contact), NULL,
-					   contact);
-}
-
-static void
 pidgin_dialogs_alias_buddy_cb(PurpleBuddy *buddy, const char *new_alias)
 {
 	purple_blist_alias_buddy(buddy, new_alias);
@@ -1147,10 +1127,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,
@@ -1189,8 +1169,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);
 }
@@ -1216,7 +1196,7 @@
 						"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);
+					purple_buddy_get_name(buddy), contact->totalsize - 1);
 
 		purple_request_action(contact, NULL, _("Remove Contact"), text, 0,
 				NULL, purple_contact_get_alias(contact), NULL,
@@ -1284,8 +1264,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 {
@@ -1333,10 +1313,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);
@@ -1352,7 +1332,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,
--- a/pidgin/gtkdialogs.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkdialogs.h	Mon Oct 31 01:25:36 2011 +0000
@@ -42,14 +42,6 @@
 void pidgin_dialogs_info(void);
 void pidgin_dialogs_log(void);
 
-#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKDIALOGS_C_)
-/**
- * @deprecated This function is no longer used and will be removed in
- *             Pidgin 3.0.0 unless there is sufficient demand to keep it.
- */
-void pidgin_dialogs_alias_contact(PurpleContact *);
-#endif
-
 void pidgin_dialogs_alias_buddy(PurpleBuddy *);
 void pidgin_dialogs_alias_chat(PurpleChat *);
 void pidgin_dialogs_remove_buddy(PurpleBuddy *);
@@ -58,15 +50,7 @@
 void pidgin_dialogs_remove_contact(PurpleContact *);
 void pidgin_dialogs_merge_groups(PurpleGroup *, const char *);
 
-/* Everything after this should probably be moved elsewhere */
-
-#ifndef PIDGIN_DISABLE_DEPRECATED
-/* This PIDGIN_DISABLE_DEPRECATED doesn't need to be deactivated by
- * _PIDGIN_GTKDIALOGS_C_, because it shouldn't be using this macro. */
-#define PIDGIN_DIALOG(x)	x = gtk_window_new(GTK_WINDOW_TOPLEVEL); \
-			gtk_window_set_type_hint(GTK_WINDOW(x), GDK_WINDOW_TYPE_HINT_DIALOG)
-#endif
-
+/* This macro should probably be moved elsewhere */
 #define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED)
 
 #endif /* _PIDGINDIALOGS_H_ */
--- a/pidgin/gtkdocklet-gtk.c	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * System tray icon (aka docklet) plugin for Purple
- *
- * Copyright (C) 2007 Anders Hasselqvist
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include "internal.h"
-#include "pidgin.h"
-#include "debug.h"
-#include "prefs.h"
-#include "pidginstock.h"
-#include "gtkdocklet.h"
-
-#define SHORT_EMBED_TIMEOUT 5
-#define LONG_EMBED_TIMEOUT 15
-
-/* globals */
-static GtkStatusIcon *docklet = NULL;
-static guint embed_timeout = 0;
-
-/* protos */
-static void docklet_gtk_status_create(gboolean);
-
-static gboolean
-docklet_gtk_recreate_cb(gpointer data)
-{
-	docklet_gtk_status_create(TRUE);
-
-	return FALSE;
-}
-
-static gboolean
-docklet_gtk_embed_timeout_cb(gpointer data)
-{
-#if !GTK_CHECK_VERSION(2,12,0)
-	if (gtk_status_icon_is_embedded(docklet)) {
-		/* Older GTK+ (<2.12) don't implement the embedded signal, but the
-		   information is still accessable through the above function. */
-		purple_debug_info("docklet", "embedded\n");
-
-		pidgin_docklet_embedded();
-		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
-	}
-	else
-#endif
-	{
-		/* The docklet was not embedded within the timeout.
-		 * Remove it as a visibility manager, but leave the plugin
-		 * loaded so that it can embed automatically if/when a notification
-		 * area becomes available.
-		 */
-		purple_debug_info("docklet", "failed to embed within timeout\n");
-		pidgin_docklet_remove();
-		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
-	}
-
-#if GTK_CHECK_VERSION(2,12,0)
-	embed_timeout = 0;
-	return FALSE;
-#else
-	return TRUE;
-#endif
-}
-
-#if GTK_CHECK_VERSION(2,12,0)
-static gboolean
-docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data)
-{
-	if (embed_timeout) {
-		purple_timeout_remove(embed_timeout);
-		embed_timeout = 0;
-	}
-
-	if (gtk_status_icon_is_embedded(docklet)) {
-		purple_debug_info("docklet", "embedded\n");
-
-		pidgin_docklet_embedded();
-		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
-	} else {
-		purple_debug_info("docklet", "detached\n");
-
-		pidgin_docklet_remove();
-		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
-	}
-
-	return TRUE;
-}
-#endif
-
-static void
-docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data)
-{
-	purple_debug_info("docklet", "destroyed\n");
-
-	pidgin_docklet_remove();
-
-	g_object_unref(G_OBJECT(docklet));
-	docklet = NULL;
-
-	g_idle_add(docklet_gtk_recreate_cb, NULL);
-}
-
-static void
-docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data)
-{
-	pidgin_docklet_clicked(1);
-}
-
-static void
-docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data)
-{
-	purple_debug_info("docklet", "The button is %u\n", button);
-#ifdef GDK_WINDOWING_QUARTZ
-	/* You can only click left mouse button on MacOSX native GTK. Let that be the menu */
-	pidgin_docklet_clicked(3);
-#else
-	pidgin_docklet_clicked(button);
-#endif
-}
-
-static void
-docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
-{
-	const gchar *icon_name = NULL;
-
-	switch (status) {
-		case PURPLE_STATUS_OFFLINE:
-			icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
-			break;
-		case PURPLE_STATUS_AWAY:
-			icon_name = PIDGIN_STOCK_TRAY_AWAY;
-			break;
-		case PURPLE_STATUS_UNAVAILABLE:
-			icon_name = PIDGIN_STOCK_TRAY_BUSY;
-			break;
-		case PURPLE_STATUS_EXTENDED_AWAY:
-			icon_name = PIDGIN_STOCK_TRAY_XA;
-			break;
-		case PURPLE_STATUS_INVISIBLE:
-			icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
-			break;
-		default:
-			icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
-			break;
-	}
-
-	if (pending)
-		icon_name = PIDGIN_STOCK_TRAY_PENDING;
-	if (connecting)
-		icon_name = PIDGIN_STOCK_TRAY_CONNECT;
-
-	if (icon_name) {
-		gtk_status_icon_set_from_icon_name(docklet, icon_name);
-	}
-
-	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) {
-		gtk_status_icon_set_blinking(docklet, (pending && !connecting));
-	} else if (gtk_status_icon_get_blinking(docklet)) {
-		gtk_status_icon_set_blinking(docklet, FALSE);
-	}
-}
-
-static void
-docklet_gtk_status_set_tooltip(gchar *tooltip)
-{
-	gtk_status_icon_set_tooltip(docklet, tooltip);
-}
-
-static void
-docklet_gtk_status_position_menu(GtkMenu *menu,
-                                 int *x, int *y, gboolean *push_in,
-                                 gpointer user_data)
-{
-	gtk_status_icon_position_menu(menu, x, y, push_in, docklet);
-}
-
-static void
-docklet_gtk_status_destroy(void)
-{
-	g_return_if_fail(docklet != NULL);
-
-	pidgin_docklet_remove();
-
-	if (embed_timeout) {
-		purple_timeout_remove(embed_timeout);
-		embed_timeout = 0;
-	}
-
-	gtk_status_icon_set_visible(docklet, FALSE);
-	g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
-	g_object_unref(G_OBJECT(docklet));
-	docklet = NULL;
-
-	purple_debug_info("docklet", "GTK+ destroyed\n");
-}
-
-static void
-docklet_gtk_status_create(gboolean recreate)
-{
-	if (docklet) {
-		/* if this is being called when a tray icon exists, it's because
-		   something messed up. try destroying it before we proceed,
-		   although docklet_refcount may be all hosed. hopefully won't happen. */
-		purple_debug_warning("docklet", "trying to create icon but it already exists?\n");
-		docklet_gtk_status_destroy();
-	}
-
-	docklet = gtk_status_icon_new();
-	g_return_if_fail(docklet != NULL);
-
-	g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL);
-	g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL);
-#if GTK_CHECK_VERSION(2,12,0)
-	g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL);
-#endif
-	g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
-
-	gtk_status_icon_set_visible(docklet, TRUE);
-
-	/* This is a hack to avoid a race condition between the docklet getting
-	 * embedded in the notification area and the gtkblist restoring its
-	 * previous visibility state.  If the docklet does not get embedded within
-	 * the timeout, it will be removed as a visibility manager until it does
-	 * get embedded.  Ideally, we would only call docklet_embedded() when the
-	 * icon was actually embedded. This only happens when the docklet is first
-	 * created, not when being recreated.
-	 *
-	 * The gtk docklet tracks whether it successfully embedded in a pref and
-	 * allows for a longer timeout period if it successfully embedded the last
-	 * time it was run. This should hopefully solve problems with the buddy
-	 * list not properly starting hidden when Pidgin is started on login.
-	 */
-	if (!recreate) {
-		pidgin_docklet_embedded();
-#if GTK_CHECK_VERSION(2,12,0)
-		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) {
-			embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
-		} else {
-			embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
-		}
-#else
-		embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
-#endif
-	}
-
-	purple_debug_info("docklet", "GTK+ created\n");
-}
-
-static void
-docklet_gtk_status_create_ui_op(void)
-{
-	docklet_gtk_status_create(FALSE);
-}
-
-static struct docklet_ui_ops ui_ops =
-{
-	docklet_gtk_status_create_ui_op,
-	docklet_gtk_status_destroy,
-	docklet_gtk_status_update_icon,
-	NULL,
-	docklet_gtk_status_set_tooltip,
-	docklet_gtk_status_position_menu
-};
-
-void
-docklet_ui_init(void)
-{
-	pidgin_docklet_set_ui_ops(&ui_ops);
-
-	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/gtk");
-	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) {
-		purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
-		purple_prefs_remove(PIDGIN_PREFS_ROOT "/docklet/x11/embedded");
-	} else {
-		purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
-	}
-
-	gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
-		DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "pidgin" G_DIR_SEPARATOR_S "tray");
-}
-
--- a/pidgin/gtkdocklet.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkdocklet.c	Mon Oct 31 01:25:36 2011 +0000
@@ -30,6 +30,7 @@
 #include "prefs.h"
 #include "signals.h"
 #include "sound.h"
+#include "status.h"
 
 #include "gtkaccount.h"
 #include "gtkblist.h"
@@ -48,8 +49,12 @@
 #define DOCKLET_TOOLTIP_LINE_LIMIT 5
 #endif
 
+#define SHORT_EMBED_TIMEOUT 5
+#define LONG_EMBED_TIMEOUT 15
+
 /* globals */
-static struct docklet_ui_ops *ui_ops = NULL;
+static GtkStatusIcon *docklet = NULL;
+static guint embed_timeout = 0;
 static PurpleStatusPrimitive status = PURPLE_STATUS_OFFLINE;
 static gboolean pending = FALSE;
 static gboolean connecting = FALSE;
@@ -58,9 +63,55 @@
 static gboolean visible = FALSE;
 static gboolean visibility_manager = FALSE;
 
+/* protos */
+static void docklet_gtk_status_create(gboolean);
+static void docklet_gtk_status_destroy(void);
+
 /**************************************************************************
  * docklet status and utility functions
  **************************************************************************/
+static void
+docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
+{
+	const gchar *icon_name = NULL;
+
+	switch (status) {
+		case PURPLE_STATUS_OFFLINE:
+			icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
+			break;
+		case PURPLE_STATUS_AWAY:
+			icon_name = PIDGIN_STOCK_TRAY_AWAY;
+			break;
+		case PURPLE_STATUS_UNAVAILABLE:
+			icon_name = PIDGIN_STOCK_TRAY_BUSY;
+			break;
+		case PURPLE_STATUS_EXTENDED_AWAY:
+			icon_name = PIDGIN_STOCK_TRAY_XA;
+			break;
+		case PURPLE_STATUS_INVISIBLE:
+			icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
+			break;
+		default:
+			icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
+			break;
+	}
+
+	if (pending)
+		icon_name = PIDGIN_STOCK_TRAY_PENDING;
+	if (connecting)
+		icon_name = PIDGIN_STOCK_TRAY_CONNECT;
+
+	if (icon_name) {
+		gtk_status_icon_set_from_icon_name(docklet, icon_name);
+	}
+
+	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) {
+		gtk_status_icon_set_blinking(docklet, (pending && !connecting));
+	} else if (gtk_status_icon_get_blinking(docklet)) {
+		gtk_status_icon_set_blinking(docklet, FALSE);
+	}
+}
+
 static gboolean
 docklet_blink_icon(gpointer data)
 {
@@ -70,11 +121,8 @@
 	blinked = !blinked;
 
 	if(pending && !connecting) {
-		if (blinked) {
-			if (ui_ops && ui_ops->blank_icon)
-				ui_ops->blank_icon();
-		} else {
-			pidgin_docklet_update_icon();
+		if (!blinked) {
+			docklet_gtk_status_update_icon(status, connecting, pending);
 		}
 		ret = TRUE; /* keep blinking */
 	} else {
@@ -126,12 +174,12 @@
 	convs = get_pending_list(DOCKLET_TOOLTIP_LINE_LIMIT);
 
 	if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) {
-		if (convs && ui_ops->create && !visible) {
+		if (convs && !visible) {
 			g_list_free(convs);
-			ui_ops->create();
+			docklet_gtk_status_create(FALSE);
 			return FALSE;
-		} else if (!convs && ui_ops->destroy && visible) {
-			ui_ops->destroy();
+		} else if (!convs && visible) {
+			docklet_gtk_status_destroy();
 			return FALSE;
 		}
 	}
@@ -142,53 +190,49 @@
 	}
 
 	if (convs != NULL) {
+		/* set tooltip if messages are pending */
+		GString *tooltip_text = g_string_new("");
 		newpending = TRUE;
 
-		/* set tooltip if messages are pending */
-		if (ui_ops->set_tooltip) {
-			GString *tooltip_text = g_string_new("");
-			for (l = convs, count = 0 ; l != NULL ; l = l->next, count++) {
-				PurpleConversation *conv = (PurpleConversation *)l->data;
-				PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+		for (l = convs, count = 0 ; l != NULL ; l = l->next, count++) {
+			PurpleConversation *conv = (PurpleConversation *)l->data;
+			PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
 
-				if (count == DOCKLET_TOOLTIP_LINE_LIMIT - 1) {
-					g_string_append(tooltip_text, _("Right-click for more unread messages...\n"));
-				} else if(gtkconv) {
-					g_string_append_printf(tooltip_text,
-						ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count),
-						gtkconv->unseen_count,
-						purple_conversation_get_title(conv));
-				} else {
-					g_string_append_printf(tooltip_text,
-						ngettext("%d unread message from %s\n", "%d unread messages from %s\n",
-						GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))),
-						GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")),
-						purple_conversation_get_title(conv));
-				}
+			if (count == DOCKLET_TOOLTIP_LINE_LIMIT - 1) {
+				g_string_append(tooltip_text, _("Right-click for more unread messages...\n"));
+			} else if(gtkconv) {
+				g_string_append_printf(tooltip_text,
+					ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count),
+					gtkconv->unseen_count,
+					purple_conversation_get_title(conv));
+			} else {
+				g_string_append_printf(tooltip_text,
+					ngettext("%d unread message from %s\n", "%d unread messages from %s\n",
+					GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))),
+					GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")),
+					purple_conversation_get_title(conv));
 			}
-
-			/* get rid of the last newline */
-			if (tooltip_text->len > 0)
-				tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1);
-
-			ui_ops->set_tooltip(tooltip_text->str);
-
-			g_string_free(tooltip_text, TRUE);
 		}
 
+		/* get rid of the last newline */
+		if (tooltip_text->len > 0)
+			tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1);
+
+		gtk_status_icon_set_tooltip(docklet, tooltip_text->str);
+
+		g_string_free(tooltip_text, TRUE);
 		g_list_free(convs);
 
-	} else if (ui_ops->set_tooltip) {
+	} else {
 		char *tooltip_text = g_strconcat(PIDGIN_NAME, " - ",
 			purple_savedstatus_get_title(saved_status), NULL);
-		ui_ops->set_tooltip(tooltip_text);
+		gtk_status_icon_set_tooltip(docklet, tooltip_text);
 		g_free(tooltip_text);
 	}
 
 	for(l = purple_accounts_get_all(); l != NULL; l = l->next) {
 
 		PurpleAccount *account = (PurpleAccount*)l->data;
-		PurpleStatus *account_status;
 
 		if (!purple_account_get_enabled(account, PIDGIN_UI))
 			continue;
@@ -196,7 +240,6 @@
 		if (purple_account_is_disconnected(account))
 			continue;
 
-		account_status = purple_account_get_active_status(account);
 		if (purple_account_is_connecting(account))
 			newconnecting = TRUE;
 	}
@@ -209,7 +252,7 @@
 		pending = newpending;
 		connecting = newconnecting;
 
-		pidgin_docklet_update_icon();
+		docklet_gtk_status_update_icon(status, connecting, pending);
 
 		/* and schedule the blinker function if messages are pending */
 		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")
@@ -229,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;
@@ -266,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();
@@ -276,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();
@@ -288,17 +331,15 @@
 {
 	const char *val = value;
 	if (!strcmp(val, "always")) {
-		if (ui_ops->create) {
-			if (!visible)
-				ui_ops->create();
-			else if (!visibility_manager) {
-				pidgin_blist_visibility_manager_add();
-				visibility_manager = TRUE;
-			}
+		if (!visible)
+			docklet_gtk_status_create(FALSE);
+		else if (!visibility_manager) {
+			pidgin_blist_visibility_manager_add();
+			visibility_manager = TRUE;
 		}
 	} else if (!strcmp(val, "never")) {
-		if (visible && ui_ops->destroy)
-			ui_ops->destroy();
+		if (visible)
+			docklet_gtk_status_destroy();
 	} else {
 		if (visibility_manager) {
 			pidgin_blist_visibility_manager_remove();
@@ -674,6 +715,7 @@
 {
 	static GtkWidget *menu = NULL;
 	GtkWidget *menuitem;
+	GtkMenuPositionFunc pos_func = gtk_status_icon_position_menu;
 
 	if (menu) {
 		gtk_widget_destroy(menu);
@@ -749,24 +791,15 @@
 #ifdef _WIN32
 	g_signal_connect(menu, "leave-notify-event", G_CALLBACK(docklet_menu_leave_enter), NULL);
 	g_signal_connect(menu, "enter-notify-event", G_CALLBACK(docklet_menu_leave_enter), NULL);
+	pos_func = NULL;
 #endif
 	gtk_widget_show_all(menu);
 	gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
-		       ui_ops->position_menu,
-		       NULL, 0, gtk_get_current_event_time());
+		       pos_func,
+		       docklet, 0, gtk_get_current_event_time());
 }
 
-/**************************************************************************
- * public api for ui_ops
- **************************************************************************/
-void
-pidgin_docklet_update_icon()
-{
-	if (ui_ops && ui_ops->update_icon)
-		ui_ops->update_icon(status, connecting, pending);
-}
-
-void
+static void
 pidgin_docklet_clicked(int button_type)
 {
 	switch (button_type) {
@@ -787,8 +820,8 @@
 	}
 }
 
-void
-pidgin_docklet_embedded()
+static void
+pidgin_docklet_embedded(void)
 {
 	if (!visibility_manager
 	    && strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) {
@@ -797,11 +830,11 @@
 	}
 	visible = TRUE;
 	docklet_update_status();
-	pidgin_docklet_update_icon();
+	docklet_gtk_status_update_icon(status, connecting, pending);
 }
 
-void
-pidgin_docklet_remove()
+static void
+pidgin_docklet_remove(void)
 {
 	if (visible) {
 		if (visibility_manager) {
@@ -817,12 +850,183 @@
 	}
 }
 
-void
-pidgin_docklet_set_ui_ops(struct docklet_ui_ops *ops)
+static gboolean
+docklet_gtk_recreate_cb(gpointer data)
+{
+	docklet_gtk_status_create(TRUE);
+
+	return FALSE;
+}
+
+#ifndef _WIN32
+static gboolean
+docklet_gtk_embed_timeout_cb(gpointer data)
 {
-	ui_ops = ops;
+#if !GTK_CHECK_VERSION(2,12,0)
+	if (gtk_status_icon_is_embedded(docklet)) {
+		/* Older GTK+ (<2.12) don't implement the embedded signal, but the
+		   information is still accessible through the above function. */
+		purple_debug_info("docklet", "embedded\n");
+
+		pidgin_docklet_embedded();
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
+	}
+	else
+#endif
+	{
+		/* The docklet was not embedded within the timeout.
+		 * Remove it as a visibility manager, but leave the plugin
+		 * loaded so that it can embed automatically if/when a notification
+		 * area becomes available.
+		 */
+		purple_debug_info("docklet", "failed to embed within timeout\n");
+		pidgin_docklet_remove();
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
+	}
+
+#if GTK_CHECK_VERSION(2,12,0)
+	embed_timeout = 0;
+	return FALSE;
+#else
+	return TRUE;
+#endif
+}
+#endif
+
+#if GTK_CHECK_VERSION(2,12,0)
+static gboolean
+docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data)
+{
+	if (embed_timeout) {
+		purple_timeout_remove(embed_timeout);
+		embed_timeout = 0;
+	}
+
+	if (gtk_status_icon_is_embedded(docklet)) {
+		purple_debug_info("docklet", "embedded\n");
+
+		pidgin_docklet_embedded();
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
+	} else {
+		purple_debug_info("docklet", "detached\n");
+
+		pidgin_docklet_remove();
+		purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
+	}
+
+	return TRUE;
+}
+#endif
+
+static void
+docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data)
+{
+	purple_debug_info("docklet", "destroyed\n");
+
+	pidgin_docklet_remove();
+
+	g_object_unref(G_OBJECT(docklet));
+	docklet = NULL;
+
+	g_idle_add(docklet_gtk_recreate_cb, NULL);
+}
+
+static void
+docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data)
+{
+	pidgin_docklet_clicked(1);
 }
 
+static void
+docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data)
+{
+	purple_debug_info("docklet", "The button is %u\n", button);
+#ifdef GDK_WINDOWING_QUARTZ
+	/* You can only click left mouse button on MacOSX native GTK. Let that be the menu */
+	pidgin_docklet_clicked(3);
+#else
+	pidgin_docklet_clicked(button);
+#endif
+}
+
+static void
+docklet_gtk_status_destroy(void)
+{
+	g_return_if_fail(docklet != NULL);
+
+	pidgin_docklet_remove();
+
+	if (embed_timeout) {
+		purple_timeout_remove(embed_timeout);
+		embed_timeout = 0;
+	}
+
+	gtk_status_icon_set_visible(docklet, FALSE);
+	g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
+	g_object_unref(G_OBJECT(docklet));
+	docklet = NULL;
+
+	purple_debug_info("docklet", "GTK+ destroyed\n");
+}
+
+static void
+docklet_gtk_status_create(gboolean recreate)
+{
+	if (docklet) {
+		/* if this is being called when a tray icon exists, it's because
+		   something messed up. try destroying it before we proceed,
+		   although docklet_refcount may be all hosed. hopefully won't happen. */
+		purple_debug_warning("docklet", "trying to create icon but it already exists?\n");
+		docklet_gtk_status_destroy();
+	}
+
+	docklet = gtk_status_icon_new();
+	g_return_if_fail(docklet != NULL);
+
+	g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL);
+	g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL);
+#if GTK_CHECK_VERSION(2,12,0)
+	g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL);
+#endif
+	g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
+
+	gtk_status_icon_set_visible(docklet, TRUE);
+
+	/* This is a hack to avoid a race condition between the docklet getting
+	 * embedded in the notification area and the gtkblist restoring its
+	 * previous visibility state.  If the docklet does not get embedded within
+	 * the timeout, it will be removed as a visibility manager until it does
+	 * get embedded.  Ideally, we would only call docklet_embedded() when the
+	 * icon was actually embedded. This only happens when the docklet is first
+	 * created, not when being recreated.
+	 *
+	 * The gtk docklet tracks whether it successfully embedded in a pref and
+	 * allows for a longer timeout period if it successfully embedded the last
+	 * time it was run. This should hopefully solve problems with the buddy
+	 * list not properly starting hidden when Pidgin is started on login.
+	 */
+	if (!recreate) {
+		pidgin_docklet_embedded();
+#ifndef _WIN32
+#if GTK_CHECK_VERSION(2,12,0)
+		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) {
+			embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
+		} else {
+			embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
+		}
+#else
+		embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
+#endif
+#endif
+	}
+
+	purple_debug_info("docklet", "GTK+ created\n");
+}
+
+/**************************************************************************
+ * public api
+ **************************************************************************/
+ 
 void*
 pidgin_docklet_get_handle()
 {
@@ -838,6 +1042,7 @@
 	void *accounts_handle = purple_accounts_get_handle();
 	void *status_handle = purple_savedstatuses_get_handle();
 	void *docklet_handle = pidgin_docklet_get_handle();
+	gchar *tmp;
 
 	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet");
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/blink", FALSE);
@@ -845,9 +1050,20 @@
 	purple_prefs_connect_callback(docklet_handle, PIDGIN_PREFS_ROOT "/docklet/show",
 				    docklet_show_pref_changed_cb, NULL);
 
-	docklet_ui_init();
-	if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "always") && ui_ops && ui_ops->create)
-		ui_ops->create();
+	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/gtk");
+	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) {
+		purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
+		purple_prefs_remove(PIDGIN_PREFS_ROOT "/docklet/x11/embedded");
+	} else {
+		purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
+	}
+
+	tmp = g_build_path(G_DIR_SEPARATOR_S, DATADIR, "pixmaps", "pidgin", "tray", NULL);
+	gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), tmp);
+	g_free(tmp);
+
+	if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "always"))
+		docklet_gtk_status_create(FALSE);
 
 	purple_signal_connect(conn_handle, "signed-on",
 			    docklet_handle, PURPLE_CALLBACK(docklet_signed_on_cb), NULL);
@@ -876,6 +1092,7 @@
 void
 pidgin_docklet_uninit()
 {
-	if (visible && ui_ops && ui_ops->destroy)
-		ui_ops->destroy();
+	if (visible)
+		docklet_gtk_status_destroy();
 }
+
--- a/pidgin/gtkdocklet.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkdocklet.h	Mon Oct 31 01:25:36 2011 +0000
@@ -25,31 +25,9 @@
 #ifndef _GTKDOCKLET_H_
 #define _GTKDOCKLET_H_
 
-#include "status.h"
-
-struct docklet_ui_ops
-{
-	void (*create)(void);
-	void (*destroy)(void);
-	void (*update_icon)(PurpleStatusPrimitive, gboolean, gboolean);
-	void (*blank_icon)(void);
-	void (*set_tooltip)(gchar *);
-	GtkMenuPositionFunc position_menu;
-};
-
-
-/* functions in gtkdocklet.c */
-void pidgin_docklet_update_icon(void);
-void pidgin_docklet_clicked(int);
-void pidgin_docklet_embedded(void);
-void pidgin_docklet_remove(void);
-void pidgin_docklet_set_ui_ops(struct docklet_ui_ops *);
-void pidgin_docklet_unload(void);
 void pidgin_docklet_init(void);
 void pidgin_docklet_uninit(void);
 void*pidgin_docklet_get_handle(void);
 
-/* function in gtkdocklet-{gtk,x11,win32}.c */
-void docklet_ui_init(void);
+#endif /* _GTKDOCKLET_H_ */
 
-#endif /* _GTKDOCKLET_H_ */
--- a/pidgin/gtkft.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkft.c	Mon Oct 31 01:25:36 2011 +0000
@@ -37,9 +37,6 @@
 #include "pidginstock.h"
 #include "gtkutils.h"
 
-#define PIDGINXFER(xfer) \
-	(PidginXferUiData *)(xfer)->ui_data
-
 /* the maximum size of files we will try to make a thumbnail for */
 #define PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL 10 * 1024 * 1024
 
@@ -116,14 +113,17 @@
 	double kbps = 0.0;
 	time_t elapsed, now;
 
-	if (xfer->end_time != 0)
-		now = xfer->end_time;
-	else
+	now = purple_xfer_get_end_time(xfer);
+	if (now == 0)
 		now = time(NULL);
 
 	kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0;
 	kb_rem  = purple_xfer_get_bytes_remaining(xfer) / 1024.0;
-	elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0);
+	elapsed = purple_xfer_get_start_time(xfer);
+	if (elapsed > 0)
+		elapsed = now - elapsed;
+	else
+		elapsed = 0;
 	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);
 
 	if (kbsec != NULL) {
@@ -135,9 +135,9 @@
 		int h, m, s;
 		int secs_elapsed;
 
-		if (xfer->start_time > 0)
+		if (purple_xfer_get_start_time(xfer) > 0)
 		{
-			secs_elapsed = now - xfer->start_time;
+			secs_elapsed = now - purple_xfer_get_start_time(xfer);
 
 			h = secs_elapsed / 3600;
 			m = (secs_elapsed % 3600) / 60;
@@ -155,7 +155,7 @@
 		if (purple_xfer_is_completed(xfer)) {
 			*time_remaining = g_strdup(_("Finished"));
 		}
-		else if (purple_xfer_is_canceled(xfer)) {
+		else if (purple_xfer_is_cancelled(xfer)) {
 			*time_remaining = g_strdup(_("Cancelled"));
 		}
 		else if (purple_xfer_get_size(xfer) == 0 || (kb_sent > 0 && kbps == 0)) {
@@ -243,11 +243,11 @@
 	if (dialog == NULL || xfer == NULL)
 		return;
 
-	data = PIDGINXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 
 	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));
@@ -281,10 +281,10 @@
 	}
 
 	gtk_label_set_text(GTK_LABEL(dialog->local_user_label),
-								 purple_account_get_username(xfer->account));
-	gtk_label_set_text(GTK_LABEL(dialog->remote_user_label), xfer->who);
+								 purple_account_get_username(purple_xfer_get_account(xfer)));
+	gtk_label_set_text(GTK_LABEL(dialog->remote_user_label), purple_xfer_get_remote_user(xfer));
 	gtk_label_set_text(GTK_LABEL(dialog->protocol_label),
-								 purple_account_get_protocol_name(xfer->account));
+								 purple_account_get_protocol_name(purple_xfer_get_account(xfer)));
 
 	if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
 		gtk_label_set_text(GTK_LABEL(dialog->filename_label),
@@ -357,7 +357,7 @@
 #endif
 
 		gtk_widget_set_sensitive(dialog->remove_button, TRUE);
-	} else if (purple_xfer_is_canceled(xfer)) {
+	} else if (purple_xfer_is_cancelled(xfer)) {
 		gtk_widget_hide(dialog->stop_button);
 		gtk_widget_show(dialog->remove_button);
 
@@ -732,8 +732,8 @@
 	gtk_widget_show(vbox2);
 
 	/* Setup the listbox */
-	gtk_box_pack_start(GTK_BOX(vbox2), 
-		pidgin_make_scrollable(setup_tree(dialog), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, 140), 
+	gtk_box_pack_start(GTK_BOX(vbox2),
+		pidgin_make_scrollable(setup_tree(dialog), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, 140),
 		TRUE, TRUE, 0);
 
 	/* "Close this window when all transfers finish" */
@@ -869,7 +869,7 @@
 
 	purple_xfer_ref(xfer);
 
-	data = PIDGINXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 	data->in_list = TRUE;
 
 	pidgin_xfer_dialog_show(dialog);
@@ -926,7 +926,7 @@
 	g_return_if_fail(dialog != NULL);
 	g_return_if_fail(xfer != NULL);
 
-	data = PIDGINXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 
 	if (data == NULL)
 		return;
@@ -957,7 +957,7 @@
 	g_return_if_fail(dialog != NULL);
 	g_return_if_fail(xfer != NULL);
 
-	data = PIDGINXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 
 	if (data == NULL)
 		return;
@@ -970,7 +970,7 @@
 		return;
 	}
 
-	data = PIDGINXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 
 	update_detailed_info(dialog, xfer);
 	update_title_progress(dialog);
@@ -979,7 +979,7 @@
 									PIDGIN_STOCK_FILE_CANCELED,
 									GTK_ICON_SIZE_MENU, NULL);
 
-	if (purple_xfer_is_canceled(xfer))
+	if (purple_xfer_is_cancelled(xfer))
 		status = _("Cancelled");
 	else
 		status = _("Failed");
@@ -1007,7 +1007,7 @@
 	g_return_if_fail(dialog != NULL);
 	g_return_if_fail(xfer != NULL);
 
-	if ((data = PIDGINXFER(xfer)) == NULL)
+	if ((data = purple_xfer_get_ui_data(xfer)) == NULL)
 		return;
 
 	if (data->in_list == FALSE)
@@ -1095,9 +1095,9 @@
 {
 	PidginXferUiData *data;
 
-	/* This is where we're setting xfer->ui_data for the first time. */
+	/* This is where we're setting xfer's "ui_data" for the first time. */
 	data = g_new0(PidginXferUiData, 1);
-	xfer->ui_data = data;
+	purple_xfer_set_ui_data(xfer, data);
 }
 
 static void
@@ -1105,11 +1105,11 @@
 {
 	PidginXferUiData *data;
 
-	data = PIDGINXFER(xfer);
+	data = purple_xfer_get_ui_data(xfer);
 	if (data) {
 		g_free(data->name);
 		g_free(data);
-		xfer->ui_data = NULL;
+		purple_xfer_set_ui_data(xfer, NULL);
 	}
 }
 
--- a/pidgin/gtkgaim-compat.h	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
-/**
- * @file gtkgaim-compat.h Gtk Gaim Compat macros
- */
-
-/* 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
- *
- */
-#ifndef _GTKGAIM_COMPAT_H_
-#define _GTKGAIM_COMPAT_H_
-
-#include <pidginstock.h>
-
-#define GAIM_ALERT_TITLE PIDGIN_ALERT_TITLE
-#define GAIM_BROWSER_CURRENT PIDGIN_BROWSER_CURRENT
-#define GAIM_BROWSER_DEFAULT PIDGIN_BROWSER_DEFAULT
-#define GAIM_BROWSER_NEW_TAB PIDGIN_BROWSER_NEW_TAB
-#define GAIM_BROWSER_NEW_WINDOW PIDGIN_BROWSER_NEW_WINDOW
-#define GaimBrowserPlace PidginBrowserPlace
-#define GAIM_BUTTON_HORIZONTAL PIDGIN_BUTTON_HORIZONTAL
-#define GAIM_BUTTON_IMAGE PIDGIN_BUTTON_IMAGE
-#define GAIM_BUTTON_NONE PIDGIN_BUTTON_NONE
-#define GaimButtonOrientation PidginButtonOrientation
-#define GaimButtonStyle PidginButtonStyle
-#define GAIM_BUTTON_TEXT_IMAGE PIDGIN_BUTTON_TEXT_IMAGE
-#define GAIM_BUTTON_TEXT PIDGIN_BUTTON_TEXT
-#define GAIM_BUTTON_VERTICAL PIDGIN_BUTTON_VERTICAL
-#define GaimConvPlacementFunc PidginConvPlacementFunc
-#define GAIM_DIALOG PIDGIN_DIALOG
-#define gaim_dnd_file_manage pidgin_dnd_file_manage
-#define gaim_get_gtkxfer_dialog pidgin_get_xfer_dialog
-#define gaim_gtk_account_dialog_show pidgin_account_dialog_show
-#define GaimGtkAccountDialogType PidginAccountDialogType
-#define gaim_gtk_account_get_handle pidgin_account_get_handle
-#define gaim_gtk_account_init pidgin_account_init
-#define gaim_gtk_account_option_menu_get_selected pidgin_account_option_menu_get_selected
-#define gaim_gtk_account_option_menu_new pidgin_account_option_menu_new
-#define gaim_gtk_account_option_menu_set_selected pidgin_account_option_menu_set_selected
-#define gaim_gtk_accounts_get_ui_ops pidgin_accounts_get_ui_ops
-#define gaim_gtk_accounts_window_hide pidgin_accounts_window_hide
-#define gaim_gtk_accounts_window_show pidgin_accounts_window_show
-#define gaim_gtk_account_uninit pidgin_account_uninit
-#define GAIM_GTK_ADD_ACCOUNT_DIALOG PIDGIN_ADD_ACCOUNT_DIALOG
-#define gaim_gtk_append_blist_node_extended_menu pidgin_append_blist_node_extended_menu
-#define gaim_gtk_append_blist_node_privacy_menu pidgin_append_blist_node_privacy_menu
-#define gaim_gtk_append_blist_node_proto_menu pidgin_append_blist_node_proto_menu
-#define gaim_gtk_append_menu_action pidgin_append_menu_action
-#define gaim_gtk_blist_add_alert pidgin_blist_add_alert
-#define gaim_gtk_blist_get_default_gtk_blist pidgin_blist_get_default_gtk_blist
-#define gaim_gtk_blist_get_handle pidgin_blist_get_handle
-#define gaim_gtk_blist_get_sort_methods pidgin_blist_get_sort_methods
-#define gaim_gtk_blist_get_status_icon pidgin_blist_get_status_icon
-#define gaim_gtk_blist_get_ui_ops pidgin_blist_get_ui_ops
-#define gaim_gtk_blist_init pidgin_blist_init
-#define gaim_gtk_blist_joinchat_is_showable pidgin_blist_joinchat_is_showable
-#define gaim_gtk_blist_joinchat_show pidgin_blist_joinchat_show
-#define gaim_gtk_blist_make_buddy_menu pidgin_blist_make_buddy_menu
-#define gaim_gtk_blist_node_is_contact_expanded pidgin_blist_node_is_contact_expanded
-#define GAIM_GTK_BLIST PIDGIN_BLIST
-#define gaim_gtk_blist_refresh pidgin_blist_refresh
-#define gaim_gtk_blist_set_headline pidgin_blist_set_headline
-#define gaim_gtk_blist_setup_sort_methods pidgin_blist_setup_sort_methods
-#define gaim_gtk_blist_sort_function pidgin_blist_sort_function
-#define gaim_gtk_blist_sort_method pidgin_blist_sort_method
-#define GaimGtkBlistSortMethod PidginBlistSortMethod
-#define gaim_gtk_blist_sort_method_reg pidgin_blist_sort_method_reg
-#define gaim_gtk_blist_sort_method_set pidgin_blist_sort_method_set
-#define gaim_gtk_blist_sort_method_unreg pidgin_blist_sort_method_unreg
-#define gaim_gtk_blist_toggle_visibility pidgin_blist_toggle_visibility
-#define gaim_gtk_blist_uninit pidgin_blist_uninit
-#define gaim_gtk_blist_update_account_error_state pidgin_blist_update_account_error_state
-#define gaim_gtk_blist_update_accounts_menu pidgin_blist_update_accounts_menu
-#define gaim_gtk_blist_update_columns pidgin_blist_update_columns
-#define gaim_gtk_blist_update_plugin_actions pidgin_blist_update_plugin_actions
-#define gaim_gtk_blist_update_refresh_timeout pidgin_blist_update_refresh_timeout
-#define gaim_gtk_blist_update_sort_methods pidgin_blist_update_sort_methods
-#define gaim_gtk_blist_visibility_manager_add pidgin_blist_visibility_manager_add
-#define gaim_gtk_blist_visibility_manager_remove pidgin_blist_visibility_manager_remove
-#define gaim_gtk_buddy_icon_chooser_new pidgin_buddy_icon_chooser_new
-#define gaim_gtk_buddy_icon_get_scale_size pidgin_buddy_icon_get_scale_size
-#define GaimGtkBuddyList PidginBuddyList
-#define GaimGtkCellRendererExpanderClass PidginCellRendererExpanderClass
-#define gaim_gtk_cell_renderer_expander_get_type pidgin_cell_renderer_expander_get_type
-#define gaim_gtk_cell_renderer_expander_new pidgin_cell_renderer_expander_new
-#define GaimGtkCellRendererExpander PidginCellRendererExpander
-#define GaimGtkCellRendererProgressClass PidginCellRendererProgressClass
-#define gaim_gtk_cell_renderer_progress_get_type pidgin_cell_renderer_progress_get_type
-#define gaim_gtk_cell_renderer_progress_new pidgin_cell_renderer_progress_new
-#define GaimGtkCellRendererProgress PidginCellRendererProgress
-#define GaimGtkChatPane PidginChatPane
-#define gaim_gtk_check_if_dir pidgin_check_if_dir
-#define gaim_gtk_clear_cursor pidgin_clear_cursor
-#define gaim_gtk_connection_get_handle pidgin_connection_get_handle
-#define gaim_gtk_connection_init pidgin_connection_init
-#define gaim_gtk_connections_get_ui_ops pidgin_connections_get_ui_ops
-#define gaim_gtk_connection_uninit pidgin_connection_uninit
-#define GaimGtkConversation PidginConversation
-#define GAIM_GTK_CONVERSATION PIDGIN_CONVERSATION
-#define gaim_gtk_conversations_fill_menu pidgin_conversations_fill_menu
-#define gaim_gtk_conversations_find_unseen_list pidgin_conversations_find_unseen_list
-#define gaim_gtk_conversations_get_conv_ui_ops pidgin_conversations_get_conv_ui_ops
-#define gaim_gtk_conversations_get_handle pidgin_conversations_get_handle
-#define gaim_gtk_conversations_init pidgin_conversations_init
-#define gaim_gtk_conversations_uninit pidgin_conversations_uninit
-#define gaim_gtk_convert_buddy_icon pidgin_convert_buddy_icon
-#define gaim_gtkconv_get_tab_at_xy pidgin_conv_get_tab_at_xy
-#define gaim_gtkconv_get_tab_icon pidgin_conv_get_tab_icon
-#define gaim_gtkconv_get_window pidgin_conv_get_window
-#define gaim_gtkconv_is_hidden pidgin_conv_is_hidden
-#define gaim_gtkconv_new pidgin_conv_new
-#define gaim_gtkconv_placement_add_fnc pidgin_conv_placement_add_fnc
-#define gaim_gtkconv_placement_get_current_func pidgin_conv_placement_get_current_func
-#define gaim_gtkconv_placement_get_fnc pidgin_conv_placement_get_fnc
-#define gaim_gtkconv_placement_get_name pidgin_conv_placement_get_name
-#define gaim_gtkconv_placement_get_options pidgin_conv_placement_get_options
-#define gaim_gtkconv_placement_place pidgin_conv_placement_place
-#define gaim_gtkconv_placement_remove_fnc pidgin_conv_placement_remove_fnc
-#define gaim_gtkconv_placement_set_current_func pidgin_conv_placement_set_current_func
-#define gaim_gtkconv_present_conversation pidgin_conv_present_conversation
-#define gaim_gtkconv_switch_active_conversation pidgin_conv_switch_active_conversation
-#define gaim_gtkconv_update_buddy_icon pidgin_conv_update_buddy_icon
-#define gaim_gtkconv_update_buttons_by_protocol pidgin_conv_update_buttons_by_protocol
-#define gaim_gtk_conv_window_add_gtkconv pidgin_conv_window_add_gtkconv
-#define gaim_gtk_conv_window_destroy pidgin_conv_window_destroy
-#define gaim_gtk_conv_window_first_with_type pidgin_conv_window_first_with_type
-#define gaim_gtk_conv_window_get_active_conversation pidgin_conv_window_get_active_conversation
-#define gaim_gtk_conv_window_get_active_gtkconv pidgin_conv_window_get_active_gtkconv
-#define gaim_gtk_conv_window_get_at_xy pidgin_conv_window_get_at_xy
-#define gaim_gtk_conv_window_get_gtkconv_at_index pidgin_conv_window_get_gtkconv_at_index
-#define gaim_gtk_conv_window_get_gtkconv_count pidgin_conv_window_get_gtkconv_count
-#define gaim_gtk_conv_window_get_gtkconvs pidgin_conv_window_get_gtkconvs
-#define gaim_gtk_conv_window_has_focus pidgin_conv_window_has_focus
-#define gaim_gtk_conv_window_hide pidgin_conv_window_hide
-#define gaim_gtk_conv_window_is_active_conversation pidgin_conv_window_is_active_conversation
-#define gaim_gtk_conv_window_last_with_type pidgin_conv_window_last_with_type
-#define gaim_gtk_conv_window_new pidgin_conv_window_new
-#define gaim_gtk_conv_window_raise pidgin_conv_window_raise
-#define gaim_gtk_conv_window_remove_gtkconv pidgin_conv_window_remove_gtkconv
-#define gaim_gtk_conv_windows_get_list pidgin_conv_windows_get_list
-#define gaim_gtk_conv_window_show pidgin_conv_window_show
-#define gaim_gtk_conv_window_switch_gtkconv pidgin_conv_window_switch_gtkconv
-#define gaim_gtk_create_imhtml pidgin_create_imhtml
-#define gaim_gtk_debug_get_handle pidgin_debug_get_handle
-#define gaim_gtk_debug_get_ui_ops pidgin_debug_get_ui_ops
-#define gaim_gtk_debug_init pidgin_debug_init
-#define gaim_gtk_debug_uninit pidgin_debug_uninit
-#define gaim_gtk_debug_window_hide pidgin_debug_window_hide
-#define gaim_gtk_debug_window_show pidgin_debug_window_show
-#define gaim_gtkdialogs_about pidgin_dialogs_about
-#define gaim_gtkdialogs_alias_buddy pidgin_dialogs_alias_buddy
-#define gaim_gtkdialogs_alias_chat pidgin_dialogs_alias_chat
-#define gaim_gtkdialogs_alias_contact pidgin_dialogs_alias_contact
-#define gaim_gtkdialogs_destroy_all pidgin_dialogs_destroy_all
-#define gaim_gtkdialogs_im pidgin_dialogs_im
-#define gaim_gtkdialogs_im_with_user pidgin_dialogs_im_with_user
-#define gaim_gtkdialogs_info pidgin_dialogs_info
-#define gaim_gtkdialogs_log pidgin_dialogs_log
-#define gaim_gtkdialogs_merge_groups pidgin_dialogs_merge_groups
-#define gaim_gtkdialogs_remove_buddy pidgin_dialogs_remove_buddy
-#define gaim_gtkdialogs_remove_chat pidgin_dialogs_remove_chat
-#define gaim_gtkdialogs_remove_contact pidgin_dialogs_remove_contact
-#define gaim_gtkdialogs_remove_group pidgin_dialogs_remove_group
-#define gaim_gtk_docklet_clicked pidgin_docklet_clicked
-#define gaim_gtk_docklet_embedded pidgin_docklet_embedded
-#define gaim_gtk_docklet_get_handle pidgin_docklet_get_handle
-#define gaim_gtk_docklet_init pidgin_docklet_init
-#define gaim_gtk_docklet_remove pidgin_docklet_remove
-#define gaim_gtk_docklet_set_ui_ops pidgin_docklet_set_ui_ops
-#define gaim_gtk_docklet_uninit pidgin_docklet_uninit
-#define gaim_gtk_docklet_unload pidgin_docklet_unload
-#define gaim_gtk_eventloop_get_ui_ops pidgin_eventloop_get_ui_ops
-#define gaim_gtk_idle_get_ui_ops pidgin_idle_get_ui_ops
-#define GaimGtkImPane PidginImPane
-#define gaim_gtk_load_accels pidgin_load_accels
-#define gaim_gtk_log_get_handle pidgin_log_get_handle
-#define gaim_gtk_log_init pidgin_log_init
-#define gaim_gtk_log_show_contact pidgin_log_show_contact
-#define gaim_gtk_log_show pidgin_log_show
-#define gaim_gtk_log_uninit pidgin_log_uninit
-#define GaimGtkLogViewer PidginLogViewer
-#define gaim_gtk_make_frame pidgin_make_frame
-#define gaim_gtk_make_mini_dialog pidgin_make_mini_dialog
-#define gaim_gtk_make_pretty_arrows pidgin_make_pretty_arrows
-#define gaim_gtk_menu_tray_append pidgin_menu_tray_append
-#define GaimGtkMenuTrayClass PidginMenuTrayClass
-#define gaim_gtk_menu_tray_get_box pidgin_menu_tray_get_box
-#define gaim_gtk_menu_tray_get_gtype pidgin_menu_tray_get_gtype
-#define gaim_gtk_menu_tray_new pidgin_menu_tray_new
-#define GaimGtkMenuTray PidginMenuTray
-#define GAIM_GTK_MENU_TRAY PIDGIN_MENU_TRAY
-#define gaim_gtk_menu_tray_prepend pidgin_menu_tray_prepend
-#define gaim_gtk_menu_tray_set_tooltip pidgin_menu_tray_set_tooltip
-#define GAIM_GTK_MODIFY_ACCOUNT_DIALOG PIDGIN_MODIFY_ACCOUNT_DIALOG
-#define gaim_gtk_notify_get_ui_ops pidgin_notify_get_ui_ops
-#define gaim_gtk_parse_x_im_contact pidgin_parse_x_im_contact
-#define gaim_gtk_plugin_dialog_show pidgin_plugin_dialog_show
-#define gaim_gtk_plugin_get_config_frame pidgin_plugin_get_config_frame
-#define GAIM_GTK_PLUGIN PIDGIN_PLUGIN
-#define gaim_gtk_plugin_pref_create_frame pidgin_plugin_pref_create_frame
-#define gaim_gtk_plugins_save pidgin_plugins_save
-#define GAIM_GTK_PLUGIN_TYPE PIDGIN_PLUGIN_TYPE
-#define GaimGtkPluginUiInfo PidginPluginUiInfo
-#define GAIM_GTK_PLUGIN_UI_INFO PIDGIN_PLUGIN_UI_INFO
-#define gaim_gtk_pounce_editor_show pidgin_pounce_editor_show
-#define gaim_gtk_pounces_get_handle pidgin_pounces_get_handle
-#define gaim_gtk_pounces_init pidgin_pounces_init
-#define gaim_gtk_pounces_manager_hide pidgin_pounces_manager_hide
-#define gaim_gtk_pounces_manager_show pidgin_pounces_manager_show
-#define gaim_gtk_prefs_checkbox pidgin_prefs_checkbox
-#define gaim_gtk_prefs_dropdown_from_list pidgin_prefs_dropdown_from_list
-#define gaim_gtk_prefs_dropdown pidgin_prefs_dropdown
-#define gaim_gtk_prefs_init pidgin_prefs_init
-#define gaim_gtk_prefs_labeled_entry pidgin_prefs_labeled_entry
-#define gaim_gtk_prefs_labeled_spin_button pidgin_prefs_labeled_spin_button
-#define gaim_gtk_prefs_show pidgin_prefs_show
-#define gaim_gtk_prefs_update_old pidgin_prefs_update_old
-#define gaim_gtk_privacy_dialog_hide pidgin_privacy_dialog_hide
-#define gaim_gtk_privacy_dialog_show pidgin_privacy_dialog_show
-#define gaim_gtk_privacy_get_ui_ops pidgin_privacy_get_ui_ops
-#define gaim_gtk_privacy_init pidgin_privacy_init
-#define gaim_gtk_protocol_option_menu_new pidgin_protocol_option_menu_new
-#define gaim_gtk_request_add_block pidgin_request_add_block
-#define gaim_gtk_request_add_permit pidgin_request_add_permit
-#define gaim_gtk_request_get_ui_ops pidgin_request_get_ui_ops
-#define gaim_gtk_roomlist_dialog_show pidgin_roomlist_dialog_show
-#define gaim_gtk_roomlist_dialog_show_with_account pidgin_roomlist_dialog_show_with_account
-#define gaim_gtk_roomlist_init pidgin_roomlist_init
-#define gaim_gtk_roomlist_is_showable pidgin_roomlist_is_showable
-#define gaim_gtk_save_accels_cb pidgin_save_accels_cb
-#define gaim_gtk_save_accels pidgin_save_accels
-#define gaim_gtk_session_end pidgin_session_end
-#define gaim_gtk_session_init pidgin_session_init
-#define gaim_gtk_set_cursor pidgin_set_cursor
-#define gaim_gtk_set_custom_buddy_icon pidgin_set_custom_buddy_icon
-#define gaim_gtk_set_sensitive_if_input pidgin_set_sensitive_if_input
-#define gaim_gtk_setup_gtkspell pidgin_setup_gtkspell
-#define gaim_gtk_setup_screenname_autocomplete pidgin_setup_screenname_autocomplete
-#define gaim_gtk_set_urgent pidgin_set_urgent
-#define gaim_gtk_sound_get_event_label pidgin_sound_get_event_label
-#define gaim_gtk_sound_get_event_option pidgin_sound_get_event_option
-#define gaim_gtk_sound_get_handle pidgin_sound_get_handle
-#define gaim_gtk_sound_get_ui_ops pidgin_sound_get_ui_ops
-#define gaim_gtk_status_editor_show pidgin_status_editor_show
-#define gaim_gtk_status_get_handle pidgin_status_get_handle
-#define gaim_gtk_status_init pidgin_status_init
-#define gaim_gtk_status_menu pidgin_status_menu
-#define gaim_gtk_status_uninit pidgin_status_uninit
-#define gaim_gtk_status_window_hide pidgin_status_window_hide
-#define gaim_gtk_status_window_show pidgin_status_window_show
-#define gaim_gtk_stock_init pidgin_stock_init
-#define gaim_gtk_syslog_show pidgin_syslog_show
-#define gaim_gtkthemes_get_proto_smileys pidgin_themes_get_proto_smileys
-#define gaim_gtkthemes_init pidgin_themes_init
-#define gaim_gtkthemes_load_smiley_theme pidgin_themes_load_smiley_theme
-#define gaim_gtkthemes_smileys_disabled pidgin_themes_smileys_disabled
-#define gaim_gtkthemes_smiley_themeize pidgin_themes_smiley_themeize
-#define gaim_gtkthemes_smiley_theme_probe pidgin_themes_smiley_theme_probe
-#define gaim_gtk_toggle_sensitive_array pidgin_toggle_sensitive_array
-#define gaim_gtk_toggle_sensitive pidgin_toggle_sensitive
-#define gaim_gtk_toggle_showhide pidgin_toggle_showhide
-#define gaim_gtk_treeview_popup_menu_position_func pidgin_treeview_popup_menu_position_func
-#define gaim_gtk_tree_view_search_equal_func pidgin_tree_view_search_equal_func
-#define GAIM_GTK_TYPE_MENU_TRAY PIDGIN_TYPE_MENU_TRAY
-#define GAIM_GTK_UI PIDGIN_UI
-#define gaim_gtk_whiteboard_get_ui_ops pidgin_whiteboard_get_ui_ops
-#define GaimGtkWhiteboard PidginWhiteboard
-#define GaimGtkWindow PidginWindow
-#define gaim_gtkxfer_dialog_add_xfer pidgin_xfer_dialog_add_xfer
-#define gaim_gtkxfer_dialog_cancel_xfer pidgin_xfer_dialog_cancel_xfer
-#define gaim_gtkxfer_dialog_destroy pidgin_xfer_dialog_destroy
-#define gaim_gtkxfer_dialog_hide pidgin_xfer_dialog_hide
-#define gaim_gtkxfer_dialog_new pidgin_xfer_dialog_new
-#define GaimGtkXferDialog PidginXferDialog
-#define gaim_gtkxfer_dialog_remove_xfer pidgin_xfer_dialog_remove_xfer
-#define gaim_gtkxfer_dialog_show pidgin_xfer_dialog_show
-#define gaim_gtkxfer_dialog_update_xfer pidgin_xfer_dialog_update_xfer
-#define gaim_gtk_xfers_get_ui_ops pidgin_xfers_get_ui_ops
-#define gaim_gtk_xfers_init pidgin_xfers_init
-#define gaim_gtk_xfers_uninit pidgin_xfers_uninit
-#define GAIM_HIG_BORDER PIDGIN_HIG_BORDER
-#define GAIM_HIG_BOX_SPACE PIDGIN_HIG_BOX_SPACE
-#define GAIM_HIG_CAT_SPACE PIDGIN_HIG_CAT_SPACE
-#if !GTK_CHECK_VERSION(2,16,0)
-#define GAIM_INVISIBLE_CHAR PIDGIN_INVISIBLE_CHAR
-#endif /* Less than GTK+ 2.16 */
-#define GAIM_IS_GTK_CONVERSATION PIDGIN_IS_PIDGIN_CONVERSATION
-#define GAIM_IS_GTK_PLUGIN PIDGIN_IS_PIDGIN_PLUGIN
-#define gaim_new_check_item pidgin_new_check_item
-#define gaim_new_item_from_stock pidgin_new_item_from_stock
-#define gaim_new_item pidgin_new_item
-#define gaim_pixbuf_button_from_stock pidgin_pixbuf_button_from_stock
-#define gaim_pixbuf_toolbar_button_from_stock pidgin_pixbuf_toolbar_button_from_stock
-#define GaimScrollBookClass PidginScrollBookClass
-#define gaim_scroll_book_get_type pidgin_scroll_book_get_type
-#define gaim_scroll_book_new pidgin_scroll_book_new
-#define GaimScrollBook PidginScrollBook
-#define gaim_separator pidgin_separator
-#define gaim_set_accessible_label pidgin_set_accessible_label
-#define gaim_set_gtkxfer_dialog pidgin_set_xfer_dialog
-#define gaim_setup_imhtml pidgin_setup_imhtml
-#define gaim_status_box_add pidgin_status_box_add
-#define gaim_status_box_add_separator pidgin_status_box_add_separator
-#define GaimStatusBoxClass PidginStatusBoxClass
-#define gaim_status_box_get_buddy_icon pidgin_status_box_get_buddy_icon
-#define gaim_status_box_get_message pidgin_status_box_get_message
-#define gaim_status_box_get_type pidgin_status_box_get_type
-#define GaimStatusBoxItemType PidginStatusBoxItemType
-#define gaim_status_box_new pidgin_status_box_new
-#define gaim_status_box_new_with_account pidgin_status_box_new_with_account
-#define GaimStatusBox PidginStatusBox
-#define gaim_status_box_pulse_connecting pidgin_status_box_pulse_connecting
-#define gaim_status_box_set_buddy_icon pidgin_status_box_set_buddy_icon
-#define gaim_status_box_set_connecting pidgin_status_box_set_connecting
-#define gaim_status_box_set_network_available pidgin_status_box_set_network_available
-#define GAIM_STATUS_ICON_LARGE PIDGIN_STATUS_ICON_LARGE
-#define GaimStatusIconSize PidginStatusIconSize
-#define GAIM_STATUS_ICON_SMALL PIDGIN_STATUS_ICON_SMALL
-#define GAIM_STOCK_ABOUT PIDGIN_STOCK_ABOUT
-#define GAIM_STOCK_ACTION PIDGIN_STOCK_ACTION
-#define GAIM_STOCK_ALIAS PIDGIN_STOCK_ALIAS
-#define GAIM_STOCK_AWAY PIDGIN_STOCK_AWAY
-#define GAIM_STOCK_CHAT PIDGIN_STOCK_CHAT
-#define GAIM_STOCK_CLEAR PIDGIN_STOCK_CLEAR
-#define GAIM_STOCK_CLOSE_TABS PIDGIN_STOCK_CLOSE_TABS
-#define GAIM_STOCK_DEBUG PIDGIN_STOCK_DEBUG
-#define GAIM_STOCK_DIALOG_AUTH PIDGIN_STOCK_DIALOG_AUTH
-#define GAIM_STOCK_DIALOG_COOL PIDGIN_STOCK_DIALOG_COOL
-#define GAIM_STOCK_DIALOG_ERROR PIDGIN_STOCK_DIALOG_ERROR
-#define GAIM_STOCK_DIALOG_INFO PIDGIN_STOCK_DIALOG_INFO
-#define GAIM_STOCK_DIALOG_QUESTION PIDGIN_STOCK_DIALOG_QUESTION
-#define GAIM_STOCK_DIALOG_WARNING PIDGIN_STOCK_DIALOG_WARNING
-#define GAIM_STOCK_DISCONNECT PIDGIN_STOCK_DISCONNECT
-#define GAIM_STOCK_DOWNLOAD PIDGIN_STOCK_DOWNLOAD
-#define GAIM_STOCK_EDIT PIDGIN_STOCK_EDIT
-#define GAIM_STOCK_FGCOLOR PIDGIN_STOCK_FGCOLOR
-#define GAIM_STOCK_FILE_CANCELED PIDGIN_STOCK_FILE_CANCELED
-#define GAIM_STOCK_FILE_DONE PIDGIN_STOCK_FILE_DONE
-#define GAIM_STOCK_FILE_TRANSFER PIDGIN_STOCK_FILE_TRANSFER
-#define GAIM_STOCK_IGNORE PIDGIN_STOCK_IGNORE
-#define GAIM_STOCK_IM "gaim-im" /* foo... */
-#define GAIM_STOCK_INVITE PIDGIN_STOCK_INVITE
-#define GAIM_STOCK_MODIFY PIDGIN_STOCK_MODIFY
-#define GAIM_STOCK_OPEN_MAIL PIDGIN_STOCK_OPEN_MAIL
-#define GAIM_STOCK_PAUSE PIDGIN_STOCK_PAUSE
-#define GAIM_STOCK_POUNCE PIDGIN_STOCK_POUNCE
-#define GAIM_STOCK_SIGN_OFF PIDGIN_STOCK_SIGN_OFF
-#define GAIM_STOCK_SIGN_ON PIDGIN_STOCK_SIGN_ON
-#define GAIM_STOCK_STATUS_OFFLINE PIDGIN_STOCK_STATUS_OFFLINE
-#define GAIM_STOCK_TEXT_NORMAL PIDGIN_STOCK_TEXT_NORMAL
-#define GAIM_STOCK_TYPED PIDGIN_STOCK_TYPED
-#define GAIM_STOCK_UPLOAD PIDGIN_STOCK_UPLOAD
-#define GAIM_TYPE_GTK_CELL_RENDERER_EXPANDER PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER
-#define GAIM_TYPE_GTK_CELL_RENDERER_PROGRESS PIDGIN_TYPE_GTK_CELL_RENDERER_PROGRESS
-#define GAIM_UNSEEN_EVENT PIDGIN_UNSEEN_EVENT
-#define GAIM_UNSEEN_NICK PIDGIN_UNSEEN_NICK
-#define GAIM_UNSEEN_NO_LOG PIDGIN_UNSEEN_NO_LOG
-#define GAIM_UNSEEN_NONE PIDGIN_UNSEEN_NONE
-#define GaimUnseenState PidginUnseenState
-#define GAIM_UNSEEN_TEXT PIDGIN_UNSEEN_TEXT
-#define GAIM_WINDOW_ICONIFIED PIDGIN_WINDOW_ICONIFIED
-#define GTK_GAIM_IS_SCROLL_BOOK_CLASS PIDGIN_IS_SCROLL_BOOK_CLASS
-#define GTK_GAIM_IS_SCROLL_BOOK PIDGIN_IS_SCROLL_BOOK
-#define GTK_GAIM_IS_STATUS_BOX_CLASS PIDGIN_IS_STATUS_BOX_CLASS
-#define GTK_GAIM_IS_STATUS_BOX PIDGIN_IS_STATUS_BOX
-#define GTK_GAIM_SCROLL_BOOK_CLASS PIDGIN_SCROLL_BOOK_CLASS
-#define GTK_GAIM_SCROLL_BOOK_GET_CLASS PIDGIN_SCROLL_BOOK_GET_CLASS
-#define gtk_gaim_scroll_book_get_type pidgin_scroll_book_get_type
-#define gtk_gaim_scroll_book_new pidgin_scroll_book_new
-#define GTK_GAIM_SCROLL_BOOK PIDGIN_SCROLL_BOOK
-#define gtk_gaim_status_box_add pidgin_status_box_add
-#define gtk_gaim_status_box_add_separator pidgin_status_box_add_separator
-#define GTK_GAIM_STATUS_BOX_CLASS PIDGIN_STATUS_BOX_CLASS
-#define gtk_gaim_status_box_get_buddy_icon pidgin_status_box_get_buddy_icon
-#define GTK_GAIM_STATUS_BOX_GET_CLASS PIDGIN_STATUS_BOX_GET_CLASS
-#define gtk_gaim_status_box_get_message pidgin_status_box_get_message
-#define gtk_gaim_status_box_get_type pidgin_status_box_get_type
-#define GtkGaimStatusBoxItemType PidginStatusBoxItemType
-#define gtk_gaim_status_box_new pidgin_status_box_new
-#define gtk_gaim_status_box_new_with_account pidgin_status_box_new_with_account
-#define GTK_GAIM_STATUS_BOX_NUM_TYPES PIDGIN_STATUS_BOX_NUM_TYPES
-#define GtkGaimStatusBox PidginStatusBox
-#define GTK_GAIM_STATUS_BOX PIDGIN_STATUS_BOX
-#define gtk_gaim_status_box_pulse_connecting pidgin_status_box_pulse_connecting
-#define gtk_gaim_status_box_set_buddy_icon pidgin_status_box_set_buddy_icon
-#define gtk_gaim_status_box_set_connecting pidgin_status_box_set_connecting
-#define gtk_gaim_status_box_set_network_available pidgin_status_box_set_network_available
-#define GTK_GAIM_STATUS_BOX_TYPE_CUSTOM PIDGIN_STATUS_BOX_TYPE_CUSTOM
-#define GTK_GAIM_STATUS_BOX_TYPE_POPULAR PIDGIN_STATUS_BOX_TYPE_POPULAR
-#define GTK_GAIM_STATUS_BOX_TYPE_PRIMITIVE PIDGIN_STATUS_BOX_TYPE_PRIMITIVE
-#define GTK_GAIM_STATUS_BOX_TYPE_SAVED PIDGIN_STATUS_BOX_TYPE_SAVED
-#define GTK_GAIM_STATUS_BOX_TYPE_SEPARATOR PIDGIN_STATUS_BOX_TYPE_SEPARATOR
-#define GTK_GAIM_TYPE_SCROLL_BOOK PIDGIN_TYPE_SCROLL_BOOK
-#define GTK_GAIM_TYPE_STATUS_BOX PIDGIN_TYPE_STATUS_BOX
-
-#endif /* _GTKGAIM_COMPAT_H */
--- a/pidgin/gtkicon-theme.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkicon-theme.c	Mon Oct 31 01:25:36 2011 +0000
@@ -26,7 +26,7 @@
 #include <gtk/gtk.h>
 
 #define PIDGIN_ICON_THEME_GET_PRIVATE(Gobject) \
-	((PidginIconThemePrivate *) ((PIDGIN_ICON_THEME(Gobject))->priv))
+	(G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_ICON_THEME, PidginIconThemePrivate))
 
 /******************************************************************************
  * Structs
@@ -53,8 +53,6 @@
 {
 	PidginIconThemePrivate *priv;
 
-	(PIDGIN_ICON_THEME(instance))->priv = g_new0(PidginIconThemePrivate, 1);
-
 	priv = PIDGIN_ICON_THEME_GET_PRIVATE(instance);
 
 	priv->icon_files = g_hash_table_new_full(g_str_hash,
@@ -69,7 +67,6 @@
 	priv = PIDGIN_ICON_THEME_GET_PRIVATE(obj);
 
 	g_hash_table_destroy(priv->icon_files);
-	g_free(priv);
 
 	parent_class->finalize(obj);
 }
@@ -82,6 +79,8 @@
 	parent_class = g_type_class_peek_parent(klass);
 
 	obj_class->finalize = pidgin_icon_theme_finalize;
+
+	g_type_class_add_private(klass, sizeof(PidginIconThemePrivate));
 }
 
 GType
--- a/pidgin/gtkicon-theme.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkicon-theme.h	Mon Oct 31 01:25:36 2011 +0000
@@ -50,7 +50,6 @@
 struct _PidginIconTheme
 {
 	PurpleTheme parent;
-	gpointer priv;
 };
 
 struct _PidginIconThemeClass
--- a/pidgin/gtkimhtml.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkimhtml.c	Mon Oct 31 01:25:36 2011 +0000
@@ -83,6 +83,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;
@@ -90,8 +120,13 @@
 	GtkTextTag *tag;
 };
 
-typedef struct _GtkIMHtmlProtocol
-{
+struct _GtkSmileyTree {
+	GString *values;
+	GtkSmileyTree **children;
+	GtkIMHtmlSmiley *image;
+};
+
+typedef struct {
 	char *name;
 	int length;
 
@@ -99,7 +134,8 @@
 	gboolean (*context_menu)(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu);
 } GtkIMHtmlProtocol;
 
-typedef struct _GtkIMHtmlFontDetail {
+/* The five elements contained in a FONT tag */
+typedef struct {
 	gushort size;
 	gchar *face;
 	gchar *fore;
@@ -3593,125 +3629,38 @@
 	gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0);
 }
 
-/* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */
-GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id)
-{
-	GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage));
-
-	GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
-	GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
-	GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free;
-
-	im_image->pixbuf = img;
-	im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
-	im_image->width = gdk_pixbuf_get_width(img);
-	im_image->height = gdk_pixbuf_get_height(img);
-	im_image->mark = NULL;
-	im_image->filename = g_strdup(filename);
-	im_image->id = id;
-	im_image->filesel = NULL;
-
-	g_object_ref(img);
-	return GTK_IMHTML_SCALABLE(im_image);
-}
-
-static gboolean
-animate_image_cb(gpointer data)
-{
-	GtkIMHtmlImage *im_image;
-	int width, height;
-	int delay;
-
-	im_image = data;
-
-	/* Update the pointer to this GdkPixbuf frame of the animation */
-	if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
-		GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
-		g_object_unref(G_OBJECT(im_image->pixbuf));
-		im_image->pixbuf = gdk_pixbuf_copy(pb);
-
-		/* Update the displayed GtkImage */
-		width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
-		height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
-		if (width > 0 && height > 0)
-		{
-			/* Need to scale the new frame to the same size as the old frame */
-			GdkPixbuf *tmp;
-			tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
-			gtk_image_set_from_pixbuf(im_image->image, tmp);
-			g_object_unref(G_OBJECT(tmp));
-		} else {
-			/* Display at full-size */
-			gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
-		}
-	}
-
-	delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
-	GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
-
-	return FALSE;
-}
-
-GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
-{
-	GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1);
-
-	GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
-	GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
-	GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
-
-	GTK_IMHTML_ANIMATION(im_image)->anim = anim;
-	if (gdk_pixbuf_animation_is_static_image(anim)) {
-		im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
-		g_object_ref(im_image->pixbuf);
-	} else {
-		int delay;
-		GdkPixbuf *pb;
-		GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
-		pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
-		im_image->pixbuf = gdk_pixbuf_copy(pb);
-		delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
-		GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
-	}
-	im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
-	im_image->width = gdk_pixbuf_animation_get_width(anim);
-	im_image->height = gdk_pixbuf_animation_get_height(anim);
-	im_image->filename = g_strdup(filename);
-	im_image->id = id;
-
-	g_object_ref(anim);
-
-	return GTK_IMHTML_SCALABLE(im_image);
-}
-
-void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
-{
-	GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
-
-	if (im_image->width > width || im_image->height > height) {
-		double ratio_w, ratio_h, ratio;
-		int new_h, new_w;
-		GdkPixbuf *new_image = NULL;
-
-		ratio_w = ((double)width - 2) / im_image->width;
-		ratio_h = ((double)height - 2) / im_image->height;
-
-		ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
-
-		new_w = (int)(im_image->width * ratio);
-		new_h = (int)(im_image->height * ratio);
-
-		new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR);
-		gtk_image_set_from_pixbuf(im_image->image, new_image);
-		g_object_unref(G_OBJECT(new_image));
-	} else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) {
-		/* Enough space to show the full-size of the image. */
-		GdkPixbuf *new_image;
-
-		new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR);
-		gtk_image_set_from_pixbuf(im_image->image, new_image);
-		g_object_unref(G_OBJECT(new_image));
-	}
+/**
+ * Destroys and frees a GTK+ IM/HTML scalable image.
+ *
+ * @param scale The GTK+ IM/HTML scalable.
+ */
+static void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
+{
+	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
+
+	g_object_unref(image->pixbuf);
+	g_free(image->filename);
+	if (image->filesel)
+		gtk_widget_destroy(image->filesel);
+	g_free(scale);
+}
+
+/**
+ * Destroys and frees a GTK+ IM/HTML scalable animation.
+ *
+ * @param scale The GTK+ IM/HTML scalable.
+ */
+static void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale)
+{
+	GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale;
+
+	if (animation->timer > 0)
+		g_source_remove(animation->timer);
+	if (animation->iter != NULL)
+		g_object_unref(animation->iter);
+	g_object_unref(animation->anim);
+
+	gtk_imhtml_image_free(scale);
 }
 
 static void
@@ -3918,55 +3867,51 @@
 
 }
 
-static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
-{
-	GdkPixbufAnimation *anim = NULL;
-	GtkIMHtmlImageSave *save = NULL;
-	gboolean ret;
-
-	if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
-		return FALSE;
-
-	anim = gtk_smiley_get_image(smiley);
-	if (!anim)
-		return FALSE;
-
-	save = g_new0(GtkIMHtmlImageSave, 1);
-	save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0);
-	save->data = smiley->data;        /* Do not need to memdup here, since the smiley is not
-	                                     destroyed before this GtkIMHtmlImageSave */
-	save->datasize = smiley->datasize;
-	ret = gtk_imhtml_image_clicked(w, event, save);
-	g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free);
-	g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free);
-	return ret;
-}
-
-void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
-{
-	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
-
-	g_object_unref(image->pixbuf);
-	g_free(image->filename);
-	if (image->filesel)
-		gtk_widget_destroy(image->filesel);
-	g_free(scale);
-}
-
-void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale)
-{
-	GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale;
-
-	if (animation->timer > 0)
-		g_source_remove(animation->timer);
-	if (animation->iter != NULL)
-		g_object_unref(animation->iter);
-	g_object_unref(animation->anim);
-
-	gtk_imhtml_image_free(scale);
-}
-
-void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
+/**
+ * Rescales a GTK+ IM/HTML scalable image to a given size.
+ *
+ * @param scale  The GTK+ IM/HTML scalable.
+ * @param width  The new width.
+ * @param height The new height.
+ */
+static void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
+{
+	GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
+
+	if (im_image->width > width || im_image->height > height) {
+		double ratio_w, ratio_h, ratio;
+		int new_h, new_w;
+		GdkPixbuf *new_image = NULL;
+
+		ratio_w = ((double)width - 2) / im_image->width;
+		ratio_h = ((double)height - 2) / im_image->height;
+
+		ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
+
+		new_w = (int)(im_image->width * ratio);
+		new_h = (int)(im_image->height * ratio);
+
+		new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR);
+		gtk_image_set_from_pixbuf(im_image->image, new_image);
+		g_object_unref(G_OBJECT(new_image));
+	} else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) {
+		/* Enough space to show the full-size of the image. */
+		GdkPixbuf *new_image;
+
+		new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR);
+		gtk_image_set_from_pixbuf(im_image->image, new_image);
+		g_object_unref(G_OBJECT(new_image));
+	}
+}
+
+/**
+ * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter.
+ *
+ * @param scale  The GTK+ IM/HTML scalable.
+ * @param imhtml The GTK+ IM/HTML.
+ * @param iter   The GtkTextIter at which to add the scalable.
+ */
+static void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
 {
 	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
 	GtkWidget *box = gtk_event_box_new();
@@ -3994,6 +3939,121 @@
 	g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free);
 }
 
+/**
+ * Creates and returns a new GTK+ IM/HTML scalable object with an image.
+ *
+ * @param img      A GdkPixbuf of the image to add.
+ * @param filename The filename to associate with the image.
+ * @param id       The id to associate with the image.
+ *
+ * @return A new IM/HTML Scalable object with an image.
+ */
+static GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id)
+{
+	GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage));
+
+	GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
+	GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
+	GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free;
+
+	im_image->pixbuf = img;
+	im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
+	im_image->width = gdk_pixbuf_get_width(img);
+	im_image->height = gdk_pixbuf_get_height(img);
+	im_image->mark = NULL;
+	im_image->filename = g_strdup(filename);
+	im_image->id = id;
+	im_image->filesel = NULL;
+
+	g_object_ref(img);
+	return GTK_IMHTML_SCALABLE(im_image);
+}
+
+static gboolean
+animate_image_cb(gpointer data)
+{
+	GtkIMHtmlImage *im_image;
+	int width, height;
+	int delay;
+
+	im_image = data;
+
+	/* Update the pointer to this GdkPixbuf frame of the animation */
+	if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
+		GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
+		g_object_unref(G_OBJECT(im_image->pixbuf));
+		im_image->pixbuf = gdk_pixbuf_copy(pb);
+
+		/* Update the displayed GtkImage */
+		width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
+		height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
+		if (width > 0 && height > 0)
+		{
+			/* Need to scale the new frame to the same size as the old frame */
+			GdkPixbuf *tmp;
+			tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
+			gtk_image_set_from_pixbuf(im_image->image, tmp);
+			g_object_unref(G_OBJECT(tmp));
+		} else {
+			/* Display at full-size */
+			gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
+		}
+	}
+
+	delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
+	GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
+
+	return FALSE;
+}
+
+/**
+ * Creates and returns a new GTK+ IM/HTML scalable object with an
+ * animated image.
+ *
+ * @param img      A GdkPixbufAnimation of the image to add.
+ * @param filename The filename to associate with the image.
+ * @param id       The id to associate with the image.
+ *
+ * @return A new IM/HTML Scalable object with an image.
+ */
+/*
+ * TODO: All this animation code could be combined much better with
+ *       the image code.  It couldn't be done when it was written
+ *       because it requires breaking backward compatibility.  It
+ *       would be good to do it for 3.0.0.
+ */
+static GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
+{
+	GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1);
+
+	GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
+	GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
+	GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
+
+	GTK_IMHTML_ANIMATION(im_image)->anim = anim;
+	if (gdk_pixbuf_animation_is_static_image(anim)) {
+		im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
+		g_object_ref(im_image->pixbuf);
+	} else {
+		int delay;
+		GdkPixbuf *pb;
+		GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
+		pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
+		im_image->pixbuf = gdk_pixbuf_copy(pb);
+		delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
+		GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
+	}
+	im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
+	im_image->width = gdk_pixbuf_animation_get_width(anim);
+	im_image->height = gdk_pixbuf_animation_get_height(anim);
+	im_image->filename = g_strdup(filename);
+	im_image->id = id;
+
+	g_object_ref(anim);
+
+	return GTK_IMHTML_SCALABLE(im_image);
+}
+
 GtkIMHtmlScalable *gtk_imhtml_hr_new()
 {
 	GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr));
@@ -4918,6 +4978,30 @@
 	}
 }
 
+static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
+{
+	GdkPixbufAnimation *anim = NULL;
+	GtkIMHtmlImageSave *save = NULL;
+	gboolean ret;
+
+	if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
+		return FALSE;
+
+	anim = gtk_smiley_get_image(smiley);
+	if (!anim)
+		return FALSE;
+
+	save = g_new0(GtkIMHtmlImageSave, 1);
+	save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0);
+	save->data = smiley->data;        /* Do not need to memdup here, since the smiley is not
+	                                     destroyed before this GtkIMHtmlImageSave */
+	save->datasize = smiley->datasize;
+	ret = gtk_imhtml_image_clicked(w, event, save);
+	g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free);
+	g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free);
+	return ret;
+}
+
 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter)
 {
 	GdkPixbuf *pixbuf = NULL;
@@ -5367,9 +5451,9 @@
 			tag = sl->data;
 			/** don't worry about non-printing tags ending */
 			if (tag_ends_here(tag, &iter, &next_iter) &&
-					strlen(tag_to_html_end(tag)) > 0 &&
-					strlen(tag_to_html_start(tag)) > 0) {
-
+					*tag_to_html_end(tag) &&
+					*tag_to_html_start(tag))
+			{
 				PidginTextTagData *tmp;
 				GQueue *r = g_queue_new();
 
--- a/pidgin/gtkimhtml.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkimhtml.h	Mon Oct 31 01:25:36 2011 +0000
@@ -50,9 +50,6 @@
 
 typedef struct _GtkIMHtml			GtkIMHtml;
 typedef struct _GtkIMHtmlClass		GtkIMHtmlClass;
-#if !(defined PIDGIN_DISABLE_DEPRECATED) && !(defined _PIDGIN_GTKIMHTML_C_)
-typedef struct _GtkIMHtmlFontDetail	GtkIMHtmlFontDetail;	/* The five elements contained in a FONT tag */
-#endif
 typedef struct _GtkSmileyTree		GtkSmileyTree;
 typedef struct _GtkIMHtmlSmiley		GtkIMHtmlSmiley;
 typedef struct _GtkIMHtmlScalable	GtkIMHtmlScalable;
@@ -61,9 +58,6 @@
 typedef struct _GtkIMHtmlHr			GtkIMHtmlHr;
 typedef struct _GtkIMHtmlFuncs		GtkIMHtmlFuncs;
 
-/**
- * @since 2.6.0
- */
 typedef struct _GtkIMHtmlLink       GtkIMHtmlLink;
 
 typedef enum {
@@ -81,7 +75,7 @@
 	GTK_IMHTML_SMILEY =     1 << 11,
 	GTK_IMHTML_LINKDESC =   1 << 12,
 	GTK_IMHTML_STRIKE =     1 << 13,
-	/** Show custom smileys when appropriate. @since 2.5.0 */
+	/** Show custom smileys when appropriate. */
 	GTK_IMHTML_CUSTOM_SMILEY = 1 << 14,
 	GTK_IMHTML_ALL =       -1
 } GtkIMHtmlButtons;
@@ -135,16 +129,6 @@
 		GtkTextTag *link;
 	} edit;
 
-#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKIMHTML_C_)
-	/** @deprecated */
-	char *clipboard_text_string;
-	/** @deprecated */
-	char *clipboard_html_string;
-#else
-	char *depr1;
-	char *depr2;
-#endif
-
 	GSList *im_images;
 	GtkIMHtmlFuncs *funcs;
 	GtkSourceUndoManager *undo_manager;
@@ -164,26 +148,6 @@
 	GList *protocols; /* List of GtkIMHtmlProtocol's */
 };
 
-#if !(defined PIDGIN_DISABLE_DEPRECATED) && !(defined _PIDGIN_GTKIMHTML_C_)
-/** @deprecated as of 2.7.10 */
-struct _GtkIMHtmlFontDetail {
-	gushort size;
-	gchar *face;
-	gchar *fore;
-	gchar *back;
-	gchar *bg;
-	gchar *sml;
-	gboolean underline;
-	gshort bold;
-};
-#endif
-
-struct _GtkSmileyTree {
-	GString *values;
-	GtkSmileyTree **children;
-	GtkIMHtmlSmiley *image;
-};
-
 struct _GtkIMHtmlSmiley {
 	gchar *smile;
 	gchar *file;
@@ -193,38 +157,8 @@
 	GSList *anchors;
 	GtkIMHtmlSmileyFlags flags;
 	GtkIMHtml *imhtml;
-	gpointer data;       /** @since 2.6.0 */
-	gsize datasize;      /** @since 2.6.0 */
-};
-
-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;
+	gpointer data;
+	gsize datasize;
 };
 
 typedef enum {
@@ -443,73 +377,6 @@
 GtkIMHtmlScalable *gtk_imhtml_scalable_new(void);
 
 /**
- * Creates and returns a new GTK+ IM/HTML scalable object with an image.
- *
- * @param img      A GdkPixbuf of the image to add.
- * @param filename The filename to associate with the image.
- * @param id       The id to associate with the image.
- *
- * @return A new IM/HTML Scalable object with an image.
- */
-GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id);
-
-/**
- * Creates and returns a new GTK+ IM/HTML scalable object with an
- * animated image.
- *
- * @param img      A GdkPixbufAnimation of the image to add.
- * @param filename The filename to associate with the image.
- * @param id       The id to associate with the image.
- *
- * @return A new IM/HTML Scalable object with an image.
- *
- * @since 2.1.0
- */
-/*
- * TODO: All this animation code could be combined much better with
- *       the image code.  It couldn't be done when it was written
- *       because it requires breaking backward compatibility.  It
- *       would be good to do it for 3.0.0.
- */
-GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *img, const gchar *filename, int id);
-
-/**
- * Destroys and frees a GTK+ IM/HTML scalable image.
- *
- * @param scale The GTK+ IM/HTML scalable.
- */
-/* TODO: Is there any reason this isn't private? */
-void gtk_imhtml_image_free(GtkIMHtmlScalable *scale);
-
-/**
- * Destroys and frees a GTK+ IM/HTML scalable animation.
- *
- * @param scale The GTK+ IM/HTML scalable.
- */
-/* TODO: Is there any reason this isn't private? */
-void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale);
-
-/**
- * Rescales a GTK+ IM/HTML scalable image to a given size.
- *
- * @param scale  The GTK+ IM/HTML scalable.
- * @param width  The new width.
- * @param height The new height.
- */
-/* TODO: Is there any reason this isn't private? */
-void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height);
-
-/**
- * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter.
- *
- * @param scale  The GTK+ IM/HTML scalable.
- * @param imhtml The GTK+ IM/HTML.
- * @param iter   The GtkTextIter at which to add the scalable.
- */
-/* TODO: Is there any reason this isn't private? */
-void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter);
-
-/**
  * Creates and returns an new GTK+ IM/HTML scalable with a horizontal rule.
  *
  * @return A new IM/HTML Scalable object with an image.
@@ -860,8 +727,6 @@
  *
  * @param imhtml  The GTK+ IM/HTML.
  * @param flags   The connection flag which describes the allowed types of formatting.
- *
- * @since 2.1.0
  */
 void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags);
 
@@ -874,7 +739,6 @@
  * @param flags      The smiley flags
  *
  * @return The newly created smiley
- * @since 2.5.0
  */
 GtkIMHtmlSmiley *gtk_imhtml_smiley_create(const char *file, const char *shortcut, gboolean hide,
 		GtkIMHtmlSmileyFlags flags);
@@ -883,8 +747,6 @@
  * Reload the image data for the smiley.
  *
  * @param smiley   The smiley to reload
- *
- * @since 2.5.0
  */
 void gtk_imhtml_smiley_reload(GtkIMHtmlSmiley *smiley);
 
@@ -892,8 +754,6 @@
  * Destroy a GtkIMHtmlSmiley.
  *
  * @param smiley   The smiley to destroy
- *
- * @since 2.5.0
  */
 void gtk_imhtml_smiley_destroy(GtkIMHtmlSmiley *smiley);
 
@@ -912,8 +772,6 @@
  *                      successfully, @c FALSE otherwise.
  *
  * @return  @c TRUE if the protocol was successfully registered (or unregistered, when \a activate is @c NULL)
- *
- * @since 2.6.0
  */
 gboolean gtk_imhtml_class_register_protocol(const char *name,
 		gboolean (*activate)(GtkIMHtml *imhtml, GtkIMHtmlLink *link),
@@ -925,8 +783,6 @@
  * @param link   The GtkIMHtmlLink object sent to the callback functions
  *
  * @return  The URL
- *
- * @since 2.6.0
  */
 const char *gtk_imhtml_link_get_url(GtkIMHtmlLink *link);
 
@@ -936,8 +792,6 @@
  * @param link   The GtkIMHtmlLink object sent to the callback functions
  *
  * @return  The GtkTextTag object, or @c NULL
- *
- * @since 2.6.0
  */
 const GtkTextTag *gtk_imhtml_link_get_text_tag(GtkIMHtmlLink *link);
 
@@ -948,8 +802,6 @@
  * @param link   The GtkIMHtmlLink object sent to the callback functions
  *
  * @return  @c TRUE if 'url-clicked' signal was emitted, @c FALSE otherwise.
- *
- * @since 2.6.0
  */
 gboolean gtk_imhtml_link_activate(GtkIMHtmlLink *link);
 
--- a/pidgin/gtkimhtmltoolbar.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Mon Oct 31 01:25:36 2011 +0000
@@ -904,7 +904,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);
@@ -1239,6 +1239,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;
@@ -1257,14 +1258,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);
-	gtk_tooltips_set_tip(toolbar->tooltips, button, _("Send Attention"), NULL);
-	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);
@@ -1327,7 +1320,6 @@
 	GtkWidget *insert_menu;
 	GtkWidget *menuitem;
 	GtkWidget *sep;
-	GObject *wide_attention_button;
 	int i;
 	struct {
 		const char *label;
@@ -1478,8 +1470,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);
@@ -1491,16 +1481,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);
@@ -1581,16 +1571,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	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkimhtmltoolbar.h	Mon Oct 31 01:25:36 2011 +0000
@@ -65,6 +65,7 @@
 	GtkWidget *image;
 	GtkWidget *link;
 	GtkWidget *smiley;
+	GtkWidget *attention;
 
 	GtkWidget *font_dialog;
 	GtkWidget *fgcolor_dialog;
@@ -90,9 +91,6 @@
 void gtk_imhtmltoolbar_attach    (GtkIMHtmlToolbar *toolbar, GtkWidget *imhtml);
 void gtk_imhtmltoolbar_associate_smileys (GtkIMHtmlToolbar *toolbar, const char *proto_id);
 
-/**
- * @since 2.7.0
- */
 void gtk_imhtmltoolbar_switch_active_conversation(GtkIMHtmlToolbar *toolbar,
 	PurpleConversation *conv);
 
--- a/pidgin/gtklog.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtklog.c	Mon Oct 31 01:25:36 2011 +0000
@@ -35,9 +35,9 @@
 
 #include "pidginstock.h"
 #include "gtkblist.h"
-#include "gtkimhtml.h"
 #include "gtklog.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 
 static GHashTable *log_viewers = NULL;
 static void populate_log_tree(PidginLogViewer *lv);
@@ -130,7 +130,7 @@
 		populate_log_tree(lv);
 		g_free(lv->search);
 		lv->search = NULL;
-		gtk_imhtml_search_clear(GTK_IMHTML(lv->imhtml));
+		webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(lv->web_view));
 		select_first_log(lv);
 		return;
 	}
@@ -138,7 +138,7 @@
 	if (lv->search != NULL && !strcmp(lv->search, search_term))
 	{
 		/* Searching for the same term acts as "Find Next" */
-		gtk_imhtml_search_find(GTK_IMHTML(lv->imhtml), lv->search);
+		webkit_web_view_search_text(WEBKIT_WEB_VIEW(lv->web_view), lv->search, FALSE, TRUE, TRUE);
 		return;
 	}
 
@@ -148,7 +148,7 @@
 	lv->search = g_strdup(search_term);
 
 	gtk_tree_store_clear(lv->treestore);
-	gtk_imhtml_clear(GTK_IMHTML(lv->imhtml));
+	webkit_web_view_open(WEBKIT_WEB_VIEW(lv->web_view), "about:blank"); /* clear the view */
 
 	for (logs = lv->logs; logs != NULL; logs = logs->next) {
 		char *read = purple_log_read((PurpleLog*)logs->data, NULL);
@@ -419,8 +419,9 @@
 static gboolean search_find_cb(gpointer data)
 {
 	PidginLogViewer *viewer = data;
-	gtk_imhtml_search_find(GTK_IMHTML(viewer->imhtml), viewer->search);
-	g_object_steal_data(G_OBJECT(viewer->entry), "search-find-cb");
+	webkit_web_view_mark_text_matches(WEBKIT_WEB_VIEW(viewer->web_view), viewer->search, FALSE, 0);
+	webkit_web_view_set_highlight_text_matches(WEBKIT_WEB_VIEW(viewer->web_view), TRUE);
+	webkit_web_view_search_text(WEBKIT_WEB_VIEW(viewer->web_view), viewer->search, FALSE, TRUE, TRUE);
 	return FALSE;
 }
 
@@ -461,23 +462,16 @@
 	read = purple_log_read(log, &flags);
 	viewer->flags = flags;
 
-	gtk_imhtml_clear(GTK_IMHTML(viewer->imhtml));
-	gtk_imhtml_set_protocol_name(GTK_IMHTML(viewer->imhtml),
-	                            purple_account_get_protocol_name(log->account));
+	webkit_web_view_open(WEBKIT_WEB_VIEW(viewer->web_view), "about:blank");
 
 	purple_signal_emit(pidgin_log_get_handle(), "log-displaying", viewer, log);
 
-	gtk_imhtml_append_text(GTK_IMHTML(viewer->imhtml), read,
-			       GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_SCROLL |
-			       ((flags & PURPLE_LOG_READ_NO_NEWLINE) ? GTK_IMHTML_NO_NEWLINE : 0));
+	webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(viewer->web_view), read, "");
 	g_free(read);
 
 	if (viewer->search != NULL) {
-		guint source;
-		gtk_imhtml_search_clear(GTK_IMHTML(viewer->imhtml));
-		source = g_idle_add(search_find_cb, viewer);
-		g_object_set_data_full(G_OBJECT(viewer->entry), "search-find-cb",
-		                       GINT_TO_POINTER(source), (GDestroyNotify)g_source_remove);
+		webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(viewer->web_view));
+		g_idle_add(search_find_cb, viewer);
 	}
 
 	pidgin_clear_cursor(viewer->window);
@@ -620,7 +614,7 @@
 	col = gtk_tree_view_column_new_with_attributes ("time", rend, "markup", 0, NULL);
 	gtk_tree_view_append_column (GTK_TREE_VIEW(lv->treeview), col);
 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (lv->treeview), FALSE);
-	gtk_paned_add1(GTK_PANED(pane), 
+	gtk_paned_add1(GTK_PANED(pane),
 		pidgin_make_scrollable(lv->treeview, GTK_POLICY_NEVER, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1));
 
 	populate_log_tree(lv);
@@ -655,9 +649,9 @@
 	gtk_paned_add2(GTK_PANED(pane), vbox);
 
 	/* Viewer ************/
-	frame = pidgin_create_imhtml(FALSE, &lv->imhtml, NULL, NULL);
-	gtk_widget_set_name(lv->imhtml, "pidgin_log_imhtml");
-	gtk_widget_set_size_request(lv->imhtml, 320, 200);
+	frame = pidgin_create_webview(FALSE, &lv->web_view, NULL, NULL);
+	gtk_widget_set_name(lv->web_view, "pidgin_log_web_view");
+	gtk_widget_set_size_request(lv->web_view, 320, 200);
 	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 	gtk_widget_show(frame);
 
--- a/pidgin/gtklog.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtklog.h	Mon Oct 31 01:25:36 2011 +0000
@@ -43,7 +43,7 @@
 	GtkWidget        *window;    /**< The viewer's window                      */
 	GtkTreeStore     *treestore; /**< The treestore containing said logs       */
 	GtkWidget        *treeview;  /**< The treeview representing said treestore */
-	GtkWidget        *imhtml;    /**< The imhtml to display said logs          */
+	GtkWidget        *web_view;  /**< The webkit web view to display said logs */
 	GtkWidget        *entry;     /**< The search entry, in which search terms
 	                              *   are entered                              */
 	PurpleLogReadFlags flags;      /**< The most recently used log flags         */
--- a/pidgin/gtkmain.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkmain.c	Mon Oct 31 01:25:36 2011 +0000
@@ -498,7 +498,6 @@
 	int opt;
 	gboolean gui_check;
 	gboolean debug_enabled;
-	gboolean migration_failed = FALSE;
 	GList *active_accounts;
 	struct stat st;
 
@@ -730,16 +729,6 @@
 
 	purple_debug_set_enabled(debug_enabled);
 
-	/* If we're using a custom configuration directory, we
-	 * do NOT want to migrate, or weird things will happen. */
-	if (opt_config_dir_arg == NULL)
-	{
-		if (!purple_core_migrate())
-		{
-			migration_failed = TRUE;
-		}
-	}
-
 	search_path = g_build_filename(purple_user_dir(), "gtkrc-2.0", NULL);
 	gtk_rc_add_default_file(search_path);
 	g_free(search_path);
@@ -765,37 +754,6 @@
 	winpidgin_init(hint);
 #endif
 
-	if (migration_failed)
-	{
-		char *old = g_strconcat(purple_home_dir(),
-		                        G_DIR_SEPARATOR_S ".gaim", NULL);
-		const char *text = _(
-			"%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");
-		GtkWidget *dialog;
-
-		dialog = gtk_message_dialog_new(NULL,
-		                                0,
-		                                GTK_MESSAGE_ERROR,
-		                                GTK_BUTTONS_CLOSE,
-		                                text, PIDGIN_NAME,
-		                                old, purple_user_dir());
-		g_free(old);
-
-		g_signal_connect_swapped(dialog, "response",
-		                         G_CALLBACK(gtk_main_quit), NULL);
-
-		gtk_widget_show_all(dialog);
-
-		gtk_main();
-
-#ifdef HAVE_SIGNAL_H
-		g_free(segfault_message);
-#endif
-		return 0;
-	}
-
 	purple_core_set_ui_ops(pidgin_core_get_ui_ops());
 	purple_eventloop_set_ui_ops(pidgin_eventloop_get_ui_ops());
 
--- a/pidgin/gtknotify.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtknotify.c	Mon Oct 31 01:25:36 2011 +0000
@@ -36,10 +36,10 @@
 #include "util.h"
 
 #include "gtkblist.h"
-#include "gtkimhtml.h"
 #include "gtknotify.h"
 #include "gtkpounce.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 
 typedef struct
 {
@@ -810,21 +810,6 @@
 	return FALSE;
 }
 
-static GtkIMHtmlOptions
-notify_imhtml_options(void)
-{
-	GtkIMHtmlOptions options = 0;
-
-	if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting"))
-		options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES;
-
-	options |= GTK_IMHTML_NO_COMMENTS;
-	options |= GTK_IMHTML_NO_TITLE;
-	options |= GTK_IMHTML_NO_NEWLINE;
-	options |= GTK_IMHTML_NO_SCROLL;
-	return options;
-}
-
 static void *
 pidgin_notify_formatted(const char *title, const char *primary,
 						  const char *secondary, const char *text)
@@ -833,7 +818,7 @@
 	GtkWidget *vbox;
 	GtkWidget *label;
 	GtkWidget *button;
-	GtkWidget *imhtml;
+	GtkWidget *web_view;
 	GtkWidget *frame;
 	char label_text[2048];
 	char *linked_text, *primary_esc, *secondary_esc;
@@ -869,12 +854,10 @@
 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 	gtk_widget_show(label);
 
-	/* Add the imhtml */
-	frame = pidgin_create_imhtml(FALSE, &imhtml, NULL, NULL);
-	gtk_widget_set_name(imhtml, "pidgin_notify_imhtml");
-	gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml),
-			gtk_imhtml_get_format_functions(GTK_IMHTML(imhtml)) | GTK_IMHTML_IMAGE);
-	gtk_widget_set_size_request(imhtml, 300, 250);
+	/* Add the webview */
+	frame = pidgin_create_webview(FALSE, &web_view, NULL, NULL);
+	gtk_widget_set_name(web_view, "pidgin_notify_webview");
+	gtk_widget_set_size_request(web_view, 300, 250);
 	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 	gtk_widget_show(frame);
 
@@ -889,10 +872,10 @@
 
 	/* Make sure URLs are clickable */
 	linked_text = purple_markup_linkify(text);
-	gtk_imhtml_append_text(GTK_IMHTML(imhtml), linked_text, notify_imhtml_options());
+	webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(web_view), linked_text, "");
 	g_free(linked_text);
 
-	g_object_set_data(G_OBJECT(window), "info-widget", imhtml);
+	g_object_set_data(G_OBJECT(window), "webview-widget", web_view);
 
 	/* Show the window */
 	pidgin_auto_parent_window(window);
@@ -1034,7 +1017,11 @@
 		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);
+
 		i++;
 	}
 
@@ -1089,7 +1076,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;
@@ -1143,10 +1130,9 @@
 	info = purple_notify_user_info_get_text_with_newline(user_info, "<br />");
 	pinfo = g_hash_table_lookup(userinfo, key);
 	if (pinfo != NULL) {
-		GtkIMHtml *imhtml = g_object_get_data(G_OBJECT(pinfo->window), "info-widget");
+		GtkWidget *webview = g_object_get_data(G_OBJECT(pinfo->window), "webview-widget");
 		char *linked_text = purple_markup_linkify(info);
-		gtk_imhtml_clear(imhtml);
-		gtk_imhtml_append_text(imhtml, linked_text, notify_imhtml_options());
+		gtk_webview_load_html_string_with_imgstore(GTK_WEBVIEW(webview), linked_text);
 		g_free(linked_text);
 		g_free(key);
 		ui_handle = pinfo->window;
@@ -1646,7 +1632,7 @@
 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(vbox), 
+	gtk_box_pack_start(GTK_BOX(vbox),
 		pidgin_make_scrollable(spec_dialog->treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1),
 		TRUE, TRUE, 2);
 
--- a/pidgin/gtkpounce.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkpounce.c	Mon Oct 31 01:25:36 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 && account->gc) ? account->gc->flags : PURPLE_CONNECTION_HTML);
+			(account && purple_account_get_connection(account)) ? purple_connection_get_flags(purple_account_get_connection(account)) : PURPLE_CONNECTION_HTML);
 }
 
 void
@@ -1483,7 +1483,7 @@
 			purple_conversation_write(conv, NULL, message,
 									PURPLE_MESSAGE_SEND, time(NULL));
 
-			serv_send_im(account->gc, (char *)pouncee, (char *)message, 0);
+			serv_send_im(purple_account_get_connection(account), (char *)pouncee, (char *)message, 0);
 		}
 	}
 
--- a/pidgin/gtkprefs.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkprefs.c	Mon Oct 31 01:25:36 2011 +0000
@@ -45,6 +45,7 @@
 
 #include "gtkblist.h"
 #include "gtkconv.h"
+#include "gtkconv-theme.h"
 #include "gtkdebug.h"
 #include "gtkdialogs.h"
 #include "gtkimhtml.h"
@@ -83,6 +84,8 @@
 /* Themes page */
 static GtkWidget *prefs_sound_themes_combo_box;
 static GtkWidget *prefs_blist_themes_combo_box;
+static GtkWidget *prefs_conv_themes_combo_box;
+static GtkWidget *prefs_conv_variants_combo_box;
 static GtkWidget *prefs_status_themes_combo_box;
 static GtkWidget *prefs_smiley_themes_combo_box;
 
@@ -94,6 +97,8 @@
 /* These exist outside the lifetime of the prefs dialog */
 static GtkListStore *prefs_sound_themes;
 static GtkListStore *prefs_blist_themes;
+static GtkListStore *prefs_conv_themes;
+static GtkListStore *prefs_conv_variants;
 static GtkListStore *prefs_status_icon_themes;
 static GtkListStore *prefs_smiley_themes;
 
@@ -339,6 +344,8 @@
 
 	prefs_sound_themes_combo_box = NULL;
 	prefs_blist_themes_combo_box = NULL;
+	prefs_conv_themes_combo_box = NULL;
+	prefs_conv_variants_combo_box = NULL;
 	prefs_status_themes_combo_box = NULL;
 	prefs_smiley_themes_combo_box = NULL;
 
@@ -490,6 +497,18 @@
 		g_free(markup);
 		if (pixbuf != NULL)
 			g_object_unref(G_OBJECT(pixbuf));
+
+	} else if (PIDGIN_IS_CONV_THEME(theme)) {
+		/* No image available? */
+
+		name = purple_theme_get_name(theme);
+		/* No author available */
+		/* No description available */
+
+		markup = get_theme_markup(name, FALSE, NULL, NULL);
+
+		gtk_list_store_append(prefs_conv_themes, &iter);
+		gtk_list_store_set(prefs_conv_themes, &iter, 1, markup, 2, name, -1);
 	}
 }
 
@@ -545,6 +564,17 @@
 	gtk_list_store_set(prefs_blist_themes, &iter, 0, pixbuf, 1, tmp, 2, "", -1);
 	g_free(tmp);
 
+	/* conversation themes */
+	gtk_list_store_clear(prefs_conv_themes);
+	gtk_list_store_append(prefs_conv_themes, &iter);
+	tmp = get_theme_markup(_("Default"), FALSE, _("Penguin Pimps"),
+		_("The default Pidgin conversation theme"));
+	gtk_list_store_set(prefs_conv_themes, &iter, 0, pixbuf, 1, tmp, 2, "", -1);
+	g_free(tmp);
+
+	/* conversation theme variants */
+	gtk_list_store_clear(prefs_conv_variants);
+
 	/* status icon themes */
 	gtk_list_store_clear(prefs_status_icon_themes);
 	gtk_list_store_append(prefs_status_icon_themes, &iter);
@@ -565,6 +595,7 @@
 	/* set active */
 	prefs_set_active_theme_combo(prefs_sound_themes_combo_box, prefs_sound_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme"));
 	prefs_set_active_theme_combo(prefs_blist_themes_combo_box, prefs_blist_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/theme"));
+	prefs_set_active_theme_combo(prefs_conv_themes_combo_box, prefs_conv_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme"));
 	prefs_set_active_theme_combo(prefs_status_themes_combo_box, prefs_status_icon_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/status/icon-theme"));
 	prefs_set_active_theme_combo(prefs_smiley_themes_combo_box, prefs_smiley_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/smileys/theme"));
 	prefs_sound_themes_loading = FALSE;
@@ -578,6 +609,10 @@
 
 	prefs_blist_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
 
+	prefs_conv_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
+
+	prefs_conv_variants = gtk_list_store_new(1, G_TYPE_STRING);
+
 	prefs_status_icon_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
 
 	prefs_smiley_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
@@ -856,7 +891,7 @@
 		} else if (!g_ascii_strncasecmp(name, "http://", 7)) {
 			/* Oo, a web drag and drop. This is where things
 			 * will start to get interesting */
-			purple_util_fetch_url(name, TRUE, NULL, FALSE, theme_got_url, info);
+			purple_util_fetch_url(name, TRUE, NULL, FALSE, -1, theme_got_url, info);
 		} else if (!g_ascii_strncasecmp(name, "https://", 8)) {
 			/* purple_util_fetch_url() doesn't support HTTPS, but we want users
 			 * to be able to drag and drop links from the SF trackers, so
@@ -867,7 +902,7 @@
 			tmp[2] = 't';
 			tmp[3] = 'p';
 
-			purple_util_fetch_url(tmp, TRUE, NULL, FALSE, theme_got_url, info);
+			purple_util_fetch_url(tmp, TRUE, NULL, FALSE, -1, theme_got_url, info);
 			g_free(tmp);
 		} else
 			free_theme_info(info);
@@ -1019,6 +1054,72 @@
 	}
 }
 
+/* sets the current conversation theme */
+static void
+prefs_set_conv_theme_cb(GtkComboBox *combo_box, gpointer user_data)
+{
+	PidginConvTheme *theme =  NULL;
+	GtkTreeIter iter;
+	gchar *name = NULL;
+
+	if (gtk_combo_box_get_active_iter(combo_box, &iter)) {
+		const GList *variants;
+		const char *current_variant;
+		gboolean unset = TRUE;
+
+		gtk_tree_model_get(GTK_TREE_MODEL(prefs_conv_themes), &iter, 2, &name, -1);
+		if (!name || !*name) {
+			g_free(name);
+			return;
+		}
+
+		purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/theme", name);
+
+		/* Update list of variants */
+		gtk_list_store_clear(prefs_conv_variants);
+
+		theme = PIDGIN_CONV_THEME(purple_theme_manager_find_theme(name, "conversation"));
+		current_variant = pidgin_conversation_theme_get_variant(theme);
+
+		variants = pidgin_conversation_theme_get_variants(theme);
+		for (; variants && current_variant; variants = g_list_next(variants)) {
+			gtk_list_store_append(prefs_conv_variants, &iter);
+			gtk_list_store_set(prefs_conv_variants, &iter, 0, variants->data, -1);
+
+			if (g_str_equal(variants->data, current_variant)) {
+				gtk_combo_box_set_active_iter(GTK_COMBO_BOX(prefs_conv_variants_combo_box), &iter);
+				unset = FALSE;
+			}
+		}
+
+		if (unset)
+			gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_conv_variants_combo_box), 0);
+
+		g_free(name);
+	}
+}
+
+/* sets the current conversation theme variant */
+static void
+prefs_set_conv_variant_cb(GtkComboBox *combo_box, gpointer user_data)
+{
+	PidginConvTheme *theme =  NULL;
+	GtkTreeIter iter;
+	gchar *name = NULL;
+
+	if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(prefs_conv_themes_combo_box), &iter)) {
+		gtk_tree_model_get(GTK_TREE_MODEL(prefs_conv_themes), &iter, 2, &name, -1);
+		theme = PIDGIN_CONV_THEME(purple_theme_manager_find_theme(name, "conversation"));
+		g_free(name);
+
+		if (gtk_combo_box_get_active_iter(combo_box, &iter)) {
+			gtk_tree_model_get(GTK_TREE_MODEL(prefs_conv_variants), &iter, 0, &name, -1);
+			pidgin_conversation_theme_set_variant(theme, name);
+			g_free(name);
+		}
+	}
+}
+
 /* sets the current icon theme */
 static void
 prefs_set_status_icon_theme_cb(GtkComboBox *combo_box, gpointer user_data)
@@ -1072,6 +1173,40 @@
 }
 
 static GtkWidget *
+add_child_theme_prefs_combo(GtkWidget *vbox, GtkSizeGroup *combo_sg,
+                             GtkSizeGroup *label_sg, GtkListStore *theme_store,
+                             GCallback combo_box_cb, gpointer combo_box_cb_user_data,
+                             const char *label_str)
+{
+	GtkWidget *label;
+	GtkWidget *combo_box;
+	GtkWidget *themesel_hbox;
+	GtkCellRenderer *cell_rend;
+
+	themesel_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_box_pack_start(GTK_BOX(vbox), themesel_hbox, FALSE, FALSE, 0);
+
+	label = gtk_label_new(label_str);
+	gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+	gtk_size_group_add_widget(label_sg, label);
+	gtk_box_pack_start(GTK_BOX(themesel_hbox), label, FALSE, FALSE, 0);
+
+	combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(theme_store));
+
+	cell_rend = gtk_cell_renderer_text_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo_box), cell_rend, TRUE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box), cell_rend, "text", 0, NULL);
+	g_object_set(cell_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+
+	g_signal_connect(G_OBJECT(combo_box), "changed",
+						(GCallback)combo_box_cb, combo_box_cb_user_data);
+	gtk_size_group_add_widget(combo_sg, combo_box);
+	gtk_box_pack_start(GTK_BOX(themesel_hbox), combo_box, TRUE, TRUE, 0);
+
+	return combo_box;
+}
+
+static GtkWidget *
 theme_page(void)
 {
 	GtkWidget *label;
@@ -1101,6 +1236,20 @@
 		(GCallback)prefs_set_blist_theme_cb, NULL,
 		_("Buddy List Theme:"), PIDGIN_PREFS_ROOT "/blist/theme", "blist");
 
+	/* Conversation Themes */
+	prefs_conv_themes_combo_box = add_theme_prefs_combo(
+		vbox, combo_sg, label_sg, prefs_conv_themes,
+		(GCallback)prefs_set_conv_theme_cb, NULL,
+		_("Conversation Theme:"), PIDGIN_PREFS_ROOT "/conversations/theme", "conversation");
+
+	/* Conversation Theme Variants */
+	prefs_conv_variants_combo_box = add_child_theme_prefs_combo(
+		vbox, combo_sg, label_sg, prefs_conv_variants,
+		(GCallback)prefs_set_conv_variant_cb, NULL, _("\tVariant:"));
+
+	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(prefs_conv_variants),
+	                                     0, GTK_SORT_ASCENDING);
+
 	/* Status Icon Themes */
 	prefs_status_themes_combo_box = add_theme_prefs_combo(
 		vbox, combo_sg, label_sg, prefs_status_icon_themes,
@@ -2866,6 +3015,10 @@
 	/* Themes */
 	prefs_themes_init();
 
+	/* Conversation Themes */
+	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations");
+	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/theme", "Default");
+
 	/* Smiley Themes */
 	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/smileys");
 	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/smileys/theme", "Default");
@@ -2882,8 +3035,6 @@
 {
 	const char *str = NULL;
 
-	purple_prefs_rename("/gaim/gtk", PIDGIN_PREFS_ROOT);
-
 	/* Rename some old prefs */
 	purple_prefs_rename(PIDGIN_PREFS_ROOT "/logging/log_ims", "/purple/logging/log_ims");
 	purple_prefs_rename(PIDGIN_PREFS_ROOT "/logging/log_chats", "/purple/logging/log_chats");
@@ -2907,12 +3058,6 @@
 		purple_prefs_remove(PIDGIN_PREFS_ROOT "/browsers/command");
 	}
 
-	/* this string pref moved into the core, try to be friendly */
-	purple_prefs_rename(PIDGIN_PREFS_ROOT "/idle/reporting_method", "/purple/away/idle_reporting");
-	if ((str = purple_prefs_get_string("/purple/away/idle_reporting")) &&
-			strcmp(str, "gaim") == 0)
-		purple_prefs_set_string("/purple/away/idle_reporting", "purple");
-
 	/* Remove some no-longer-used prefs */
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/auto_expand_contacts");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/button_style");
--- a/pidgin/gtkprefs.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkprefs.h	Mon Oct 31 01:25:36 2011 +0000
@@ -92,8 +92,6 @@
  * @return      An hbox containing both the label and the entry.  Can be used to set
  *               the widgets to sensitive or insensitive based on the value of a
  *               checkbox.
- *
- * @since 2.6.0
  */
 GtkWidget *pidgin_prefs_labeled_password(GtkWidget *page, const gchar *title,
 										const char *key, GtkSizeGroup *sg);
--- a/pidgin/gtkprivacy.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkprivacy.c	Mon Oct 31 01:25:36 2011 +0000
@@ -211,7 +211,7 @@
 	dialog->account = account;
 
 	for (i = 0; i < menu_entry_count; i++) {
-		if (menu_entries[i].num == account->perm_deny) {
+		if (menu_entries[i].num == purple_account_get_privacy_type(account)) {
 			gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->type_menu), i);
 			break;
 		}
@@ -230,7 +230,7 @@
 {
 	int new_type = menu_entries[gtk_combo_box_get_active(combo)].num;
 
-	dialog->account->perm_deny = new_type;
+	purple_account_set_privacy_type(dialog->account, new_type);
 	serv_set_permit_deny(purple_account_get_connection(dialog->account));
 
 	gtk_widget_hide(dialog->allow_widget);
@@ -371,7 +371,7 @@
 		gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->type_menu),
 		                          _(menu_entries[i].text));
 
-		if (menu_entries[i].num == dialog->account->perm_deny)
+		if (menu_entries[i].num == purple_account_get_privacy_type(dialog->account))
 			selected = i;
 	}
 
@@ -411,12 +411,12 @@
 
 	type_changed_cb(GTK_COMBO_BOX(dialog->type_menu), dialog);
 #if 0
-	if (dialog->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) {
+	if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_ALLOW_USERS) {
 		gtk_widget_show(dialog->allow_widget);
 		gtk_widget_show(dialog->button_box);
 		dialog->in_allow_list = TRUE;
 	}
-	else if (dialog->account->perm_deny == PURPLE_PRIVACY_DENY_USERS) {
+	else if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_DENY_USERS) {
 		gtk_widget_show(dialog->block_widget);
 		gtk_widget_show(dialog->button_box);
 		dialog->in_allow_list = FALSE;
--- a/pidgin/gtkrequest.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkrequest.c	Mon Oct 31 01:25:36 2011 +0000
@@ -749,6 +749,7 @@
 req_entry_field_changed_cb(GtkWidget *entry, PurpleRequestField *field)
 {
 	PurpleRequestFieldGroup *group;
+	PurpleRequestFields *fields;
 	PidginRequestData *req_data;
 
 	if (purple_request_field_string_is_multiline(field))
@@ -771,10 +772,11 @@
 	}
 
 	group = purple_request_field_get_group(field);
-	req_data = (PidginRequestData *)group->fields_list->ui_data;
+	fields = purple_request_field_group_get_fields_list(group);
+	req_data = purple_request_fields_get_ui_data(fields);
 
 	gtk_widget_set_sensitive(req_data->ok_button,
-		purple_request_fields_all_required_filled(group->fields_list));
+		purple_request_fields_all_required_filled(fields));
 }
 
 static void
@@ -796,7 +798,7 @@
 		{
 			GtkWidget *optmenu = NULL;
 			PurpleRequestFieldGroup *group = purple_request_field_get_group(field);
-			GList *fields = group->fields;
+			GList *fields = purple_request_field_group_get_fields(group);
 
 			/* Ensure the account option menu is created (if the widget hasn't
 			 * been initialized already) for username auto-completion. */
@@ -857,6 +859,10 @@
 			gtk_text_buffer_set_text(buffer, value, -1);
 		}
 
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(textview, purple_request_field_get_tooltip(field));
+#endif
+
 		gtk_text_view_set_editable(GTK_TEXT_VIEW(textview),
 			purple_request_field_string_is_editable(field));
 
@@ -881,6 +887,10 @@
 		if (value != NULL)
 			gtk_entry_set_text(GTK_ENTRY(widget), value);
 
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 		if (purple_request_field_string_is_masked(field))
 		{
 			gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE);
@@ -921,6 +931,10 @@
 		gtk_entry_set_text(GTK_ENTRY(widget), buf);
 	}
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 	g_signal_connect(G_OBJECT(widget), "focus-out-event",
 					 G_CALLBACK(field_int_focus_out_cb), field);
 
@@ -935,6 +949,10 @@
 	widget = gtk_check_button_new_with_label(
 		purple_request_field_get_label(field));
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
 		purple_request_field_bool_get_default_value(field));
 
@@ -965,6 +983,10 @@
 		gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
 						purple_request_field_choice_get_default_value(field));
 
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 		g_signal_connect(G_OBJECT(widget), "changed",
 						 G_CALLBACK(field_choice_menu_cb), field);
 	}
@@ -982,6 +1004,10 @@
 
 		widget = box;
 
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 		for (l = labels, i = 0; l != NULL; l = l->next, i++)
 		{
 			const char *text = l->data;
@@ -1024,6 +1050,10 @@
 	g_object_unref(G_OBJECT(buf));
 	g_object_unref(G_OBJECT(scale));
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 	return widget;
 }
 
@@ -1039,6 +1069,10 @@
 		purple_request_field_account_get_filter(field),
 		field);
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
+#endif
+
 	return widget;
 }
 
@@ -1188,7 +1222,7 @@
 	data->user_data = user_data;
 	data->u.multifield.fields = fields;
 
-	fields->ui_data = data;
+	purple_request_fields_set_ui_data(fields, data);
 
 	data->cb_count = 2;
 	data->cbs = g_new0(GCallback, 2);
--- a/pidgin/gtkroomlist.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkroomlist.c	Mon Oct 31 01:25:36 2011 +0000
@@ -91,7 +91,7 @@
 		purple_timeout_remove(dialog->pg_update_to);
 
 	if (dialog->roomlist) {
-		PidginRoomlist *rl = dialog->roomlist->ui_data;
+		PidginRoomlist *rl = purple_roomlist_get_ui_data(dialog->roomlist);
 
 		if (dialog->pg_update_to > 0)
 			/* yes, that's right, unref it twice. */
@@ -115,7 +115,7 @@
 	dialog->account = account;
 
 	if (change && dialog->roomlist) {
-		PidginRoomlist *rl = dialog->roomlist->ui_data;
+		PidginRoomlist *rl = purple_roomlist_get_ui_data(dialog->roomlist);
 		if (rl->tree) {
 			gtk_widget_destroy(rl->tree);
 			rl->tree = NULL;
@@ -135,7 +135,7 @@
 		return;
 
 	if (dialog->roomlist != NULL) {
-		rl = dialog->roomlist->ui_data;
+		rl = purple_roomlist_get_ui_data(dialog->roomlist);
 		gtk_widget_destroy(rl->tree);
 		purple_roomlist_unref(dialog->roomlist);
 	}
@@ -144,7 +144,7 @@
 	if (!dialog->roomlist)
 		return;
 	purple_roomlist_ref(dialog->roomlist);
-	rl = dialog->roomlist->ui_data;
+	rl = purple_roomlist_get_ui_data(dialog->roomlist);
 	rl->dialog = dialog;
 
 	if (dialog->account_widget)
@@ -203,7 +203,7 @@
 		val.g_type = 0;
 		gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val);
 		room = g_value_get_pointer(&val);
-		if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) {
+		if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) {
 			gtk_widget_set_sensitive(dialog->join_button, FALSE);
 			gtk_widget_set_sensitive(dialog->add_button, FALSE);
 			return;
@@ -228,18 +228,19 @@
 static void do_add_room_cb(GtkWidget *w, struct _menu_cb_info *info)
 {
 	char *name;
-	PurpleConnection *gc = purple_account_get_connection(info->list->account);
+	PurpleAccount *account = purple_roomlist_get_account(info->list);
+	PurpleConnection *gc = purple_account_get_connection(account);
 	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);
 	else
-		name = g_strdup(info->room->name);
+		name = g_strdup(purple_roomlist_room_get_name(info->room));
 
-	purple_blist_request_add_chat(info->list->account, NULL, NULL, name);
+	purple_blist_request_add_chat(account, NULL, NULL, name);
 
 	g_free(name);
 }
@@ -247,7 +248,7 @@
 static void add_room_to_blist_cb(GtkButton *button, PidginRoomlistDialog *dialog)
 {
 	PurpleRoomlist *rl = dialog->roomlist;
-	PidginRoomlist *grl = rl->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(rl);
 	struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info");
 
 	if(info != NULL)
@@ -262,7 +263,7 @@
 static void join_button_cb(GtkButton *button, PidginRoomlistDialog *dialog)
 {
 	PurpleRoomlist *rl = dialog->roomlist;
-	PidginRoomlist *grl = rl->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(rl);
 	struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info");
 
 	if(info != NULL)
@@ -272,7 +273,7 @@
 static void row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *arg2,
                       PurpleRoomlist *list)
 {
-	PidginRoomlist *grl = list->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
 	GtkTreeIter iter;
 	PurpleRoomlistRoom *room;
 	GValue val;
@@ -282,7 +283,7 @@
 	val.g_type = 0;
 	gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val);
 	room = g_value_get_pointer(&val);
-	if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM))
+	if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM))
 		return;
 
 	info.list = list;
@@ -294,7 +295,7 @@
 static gboolean room_click_cb(GtkWidget *tv, GdkEventButton *event, PurpleRoomlist *list)
 {
 	GtkTreePath *path;
-	PidginRoomlist *grl = list->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
 	GValue val;
 	PurpleRoomlistRoom *room;
 	GtkTreeIter iter;
@@ -313,7 +314,7 @@
 	gtk_tree_model_get_value (GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val);
 	room = g_value_get_pointer(&val);
 
-	if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM))
+	if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM))
 		return FALSE;
 
 	info.list = list;
@@ -341,9 +342,9 @@
 	gtk_tree_model_get_value(gtk_tree_view_get_model(treeview), arg1, ROOM_COLUMN, &val);
 	category = g_value_get_pointer(&val);
 
-	if (!category->expanded_once) {
+	if (!purple_roomlist_room_get_expanded_once(category)) {
 		purple_roomlist_expand_category(list, category);
-		category->expanded_once = TRUE;
+		purple_roomlist_room_set_expanded_once(category, TRUE);
 	}
 }
 
@@ -354,7 +355,7 @@
 pidgin_roomlist_paint_tooltip(GtkWidget *widget, gpointer user_data)
 {
 	PurpleRoomlist *list = user_data;
-	PidginRoomlist *grl = list->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
 	GtkStyle *style;
 	int current_height, max_width;
 	int max_text_width;
@@ -393,7 +394,7 @@
 
 static gboolean pidgin_roomlist_create_tip(PurpleRoomlist *list, GtkTreePath *path)
 {
-	PidginRoomlist *grl = list->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
 	PurpleRoomlistRoom *room;
 	GtkTreeIter iter;
 	GValue val;
@@ -414,19 +415,23 @@
 	gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val);
 	room = g_value_get_pointer(&val);
 
-	if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM))
+	if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM))
 		return FALSE;
 
 	tooltip_text = g_string_new("");
 	gtk_tree_model_get(GTK_TREE_MODEL(grl->model), &iter, NAME_COLUMN, &name, -1);
 
-	for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) {
+	for (j = NUM_OF_COLUMNS,
+				l = purple_roomlist_room_get_fields(room),
+				k = purple_roomlist_get_fields(list);
+			l && k; j++, l = l->next, k = k->next)
+	{
 		PurpleRoomlistField *f = k->data;
 		gchar *label;
-		if (f->hidden)
+		if (purple_roomlist_field_get_hidden(f))
 			continue;
-		label = g_markup_escape_text(f->label, -1);
-		switch (f->type) {
+		label = g_markup_escape_text(purple_roomlist_field_get_label(f), -1);
+		switch (purple_roomlist_field_get_type(f)) {
 			case PURPLE_ROOMLIST_FIELD_BOOL:
 				g_string_append_printf(tooltip_text, "%s<b>%s:</b> %s", first ? "" : "\n", label, l->data ? "True" : "False");
 				break;
@@ -478,7 +483,7 @@
 		gpointer data, int *w, int *h)
 {
 	PurpleRoomlist *list = data;
-	PidginRoomlist *grl = list->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
 	grl->tipwindow = widget;
 	if (!pidgin_roomlist_create_tip(data, path))
 		return FALSE;
@@ -497,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);
 }
@@ -622,7 +627,7 @@
 {
 	PidginRoomlist *rl = g_new0(PidginRoomlist, 1);
 
-	list->ui_data = rl;
+	purple_roomlist_set_ui_data(list, rl);
 
 	rl->cats = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)gtk_tree_row_reference_free);
 
@@ -685,7 +690,7 @@
 
 static void pidgin_roomlist_set_fields(PurpleRoomlist *list, GList *fields)
 {
-	PidginRoomlist *grl = list->ui_data;
+	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
 	gint columns = NUM_OF_COLUMNS;
 	int j;
 	GtkTreeStore *model;
@@ -707,7 +712,7 @@
 	for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) {
 		PurpleRoomlistField *f = l->data;
 
-		switch (f->type) {
+		switch (purple_roomlist_field_get_type(f)) {
 		case PURPLE_ROOMLIST_FIELD_BOOL:
 			types[j] = G_TYPE_BOOLEAN;
 			break;
@@ -749,18 +754,19 @@
 	for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) {
 		PurpleRoomlistField *f = l->data;
 
-		if (f->hidden)
+		if (purple_roomlist_field_get_hidden(f))
 			continue;
 
 		renderer = gtk_cell_renderer_text_new();
-		column = gtk_tree_view_column_new_with_attributes(f->label, renderer,
-		                                                  "text", j, NULL);
+		column = gtk_tree_view_column_new_with_attributes(
+				purple_roomlist_field_get_label(f), renderer,
+				"text", j, NULL);
 		gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
 		                                GTK_TREE_VIEW_COLUMN_GROW_ONLY);
 		gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE);
 		gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), j);
 		gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE);
-		if (f->type == PURPLE_ROOMLIST_FIELD_INT) {
+		if (purple_roomlist_field_get_type(f) == PURPLE_ROOMLIST_FIELD_INT) {
 			gtk_tree_view_column_set_cell_data_func(column, renderer, int_cell_data_func,
 			                                        GINT_TO_POINTER(j), NULL);
 			gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), j, int_sort_func,
@@ -789,7 +795,7 @@
 static gboolean pidgin_progress_bar_pulse(gpointer data)
 {
 	PurpleRoomlist *list = data;
-	PidginRoomlist *rl = list->ui_data;
+	PidginRoomlist *rl = purple_roomlist_get_ui_data(list);
 
 	if (!rl || !rl->dialog || !rl->dialog->pg_needs_pulse) {
 		if (rl && rl->dialog)
@@ -805,7 +811,7 @@
 
 static void pidgin_roomlist_add_room(PurpleRoomlist *list, PurpleRoomlistRoom *room)
 {
-	PidginRoomlist *rl = list->ui_data;
+	PidginRoomlist *rl = purple_roomlist_get_ui_data(list);
 	GtkTreeRowReference *rr, *parentrr = NULL;
 	GtkTreePath *path;
 	GtkTreeIter iter, parent, child;
@@ -814,7 +820,7 @@
 	gboolean append = TRUE;
 
 	rl->total_rooms++;
-	if (room->type == PURPLE_ROOMLIST_ROOMTYPE_ROOM)
+	if (purple_roomlist_room_get_type(room) == PURPLE_ROOMLIST_ROOMTYPE_ROOM)
 		rl->num_rooms++;
 
 	if (rl->dialog) {
@@ -826,8 +832,8 @@
 			rl->dialog->pg_needs_pulse = TRUE;
 	}
 
-	if (room->parent) {
-		parentrr = g_hash_table_lookup(rl->cats, room->parent);
+	if (purple_roomlist_room_get_parent(room)) {
+		parentrr = g_hash_table_lookup(rl->cats, purple_roomlist_room_get_parent(room));
 		path = gtk_tree_row_reference_get_path(parentrr);
 		if (path) {
 			PurpleRoomlistRoom *tmproom = NULL;
@@ -848,24 +854,28 @@
 	else
 		iter = child;
 
-	if (room->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
+	if (purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
 		gtk_tree_store_append(rl->model, &child, &iter);
 
 	path = gtk_tree_model_get_path(GTK_TREE_MODEL(rl->model), &iter);
 
-	if (room->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) {
+	if (purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) {
 		rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(rl->model), path);
 		g_hash_table_insert(rl->cats, room, rr);
 	}
 
 	gtk_tree_path_free(path);
 
-	gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, room->name, -1);
+	gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, purple_roomlist_room_get_name(room), -1);
 	gtk_tree_store_set(rl->model, &iter, ROOM_COLUMN, room, -1);
 
-	for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) {
+	for (j = NUM_OF_COLUMNS,
+				l = purple_roomlist_room_get_fields(room),
+				k = purple_roomlist_get_fields(list);
+			l && k; j++, l = l->next, k = k->next)
+	{
 		PurpleRoomlistField *f = k->data;
-		if (f->hidden)
+		if (purple_roomlist_field_get_hidden(f))
 			continue;
 		gtk_tree_store_set(rl->model, &iter, j, l->data, -1);
 	}
@@ -873,7 +883,7 @@
 
 static void pidgin_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress)
 {
-	PidginRoomlist *rl = list->ui_data;
+	PidginRoomlist *rl = purple_roomlist_get_ui_data(list);
 
 	if (!rl || !rl->dialog)
 		return;
@@ -895,7 +905,7 @@
 
 static void pidgin_roomlist_destroy(PurpleRoomlist *list)
 {
-	PidginRoomlist *rl = list->ui_data;
+	PidginRoomlist *rl = purple_roomlist_get_ui_data(list);
 
 	roomlists = g_list_remove(roomlists, list);
 
@@ -903,7 +913,7 @@
 
 	g_hash_table_destroy(rl->cats);
 	g_free(rl);
-	list->ui_data = NULL;
+	purple_roomlist_set_ui_data(list, NULL);
 }
 
 static PurpleRoomlistUiOps ops = {
--- a/pidgin/gtksmiley.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtksmiley.c	Mon Oct 31 01:25:36 2011 +0000
@@ -47,9 +47,9 @@
 	GtkWidget *smiley_image;
 	gchar *filename;
 	GdkPixbuf *custom_pixbuf;
-	gpointer data; /** @since 2.6.0 */
-	gsize datasize; /** @since 2.6.0 */
-	gint entry_len; /** @since 2.6.0 */
+	gpointer data;
+	gsize datasize;
+	gint entry_len;
 };
 
 typedef struct
@@ -750,7 +750,7 @@
 		} else if (!g_ascii_strncasecmp(name, "http://", 7)) {
 			/* Oo, a web drag and drop. This is where things
 			 * will start to get interesting */
-			purple_util_fetch_url(name, TRUE, NULL, FALSE, smiley_got_url, dialog);
+			purple_util_fetch_url(name, TRUE, NULL, FALSE, -1, smiley_got_url, dialog);
 		} else if (!g_ascii_strncasecmp(name, "https://", 8)) {
 			/* purple_util_fetch_url() doesn't support HTTPS */
 			char *tmp = g_strdup(name + 1);
@@ -759,7 +759,7 @@
 			tmp[2] = 't';
 			tmp[3] = 'p';
 
-			purple_util_fetch_url(tmp, TRUE, NULL, FALSE, smiley_got_url, dialog);
+			purple_util_fetch_url(tmp, TRUE, NULL, FALSE, -1, smiley_got_url, dialog);
 			g_free(tmp);
 		}
 
--- a/pidgin/gtksmiley.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtksmiley.h	Mon Oct 31 01:25:36 2011 +0000
@@ -1,7 +1,6 @@
 /**
  * @file gtksmiley.h GTK+ Custom Smiley API
  * @ingroup pidgin
- * @since 2.5.0
  */
 
 /* pidgin
@@ -106,8 +105,6 @@
  * @param editor A smiley editor dialog
  * @param data A pointer to smiley's data
  * @param datasize The size of smiley's data
- *
- * @since 2.6.0
  */
 void pidgin_smiley_editor_set_data(PidginSmiley *editor, gpointer data, gsize datasize);
 
--- a/pidgin/gtksound.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtksound.c	Mon Oct 31 01:25:36 2011 +0000
@@ -96,8 +96,8 @@
 	if (chat==NULL)
 		return ret;
 
-	nick = g_strdup(purple_normalize(conv->account, chat->nick));
-	name = g_strdup(purple_normalize(conv->account, aname));
+	nick = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_conv_chat_get_nick(chat)));
+	name = g_strdup(purple_normalize(purple_conversation_get_account(conv), aname));
 
 	if (g_utf8_collate(nick, name) == 0)
 		ret = TRUE;
@@ -212,7 +212,7 @@
 	if (chat_nick_matches_name(conv, sender))
 		return;
 
-	if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, chat->nick))
+	if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_conv_chat_get_nick(chat)))
 		/* This isn't quite right; if you have the PURPLE_SOUND_CHAT_NICK event disabled
 		 * and the PURPLE_SOUND_CHAT_SAY event enabled, you won't get a sound at all */
 		play_conv_event(conv, PURPLE_SOUND_CHAT_NICK);
--- a/pidgin/gtksound.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtksound.h	Mon Oct 31 01:25:36 2011 +0000
@@ -67,8 +67,6 @@
  * Returns true Pidgin is using customized sounds
  *
  * @return TRUE if non default sounds are used.
- *
- * @since 2.6.0
  */
 gboolean pidgin_sound_is_customized(void);
 
--- a/pidgin/gtkstatusbox.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkstatusbox.c	Mon Oct 31 01:25:36 2011 +0000
@@ -412,7 +412,7 @@
 	if (src == NULL)
 		return FALSE;
 
-	purple_util_fetch_url(src, TRUE, NULL, FALSE, statusbox_got_url, data);
+	purple_util_fetch_url(src, TRUE, NULL, FALSE, -1, statusbox_got_url, data);
 	return TRUE;
 }
 
--- a/pidgin/gtkthemes.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkthemes.c	Mon Oct 31 01:25:36 2011 +0000
@@ -122,6 +122,8 @@
 
 static void _pidgin_themes_smiley_themeize(GtkWidget *imhtml, gboolean custom)
 {
+	/* TODO WEBKIT: move imhtml dependency to use webview. */
+#if 0
 	struct smiley_list *list;
 	if (!current_smiley_theme)
 		return;
@@ -147,6 +149,7 @@
 
 		list = list->next;
 	}
+#endif /* if 0 */
 }
 
 void pidgin_themes_smiley_themeize(GtkWidget *imhtml)
@@ -278,6 +281,8 @@
 		if (*i == '[' && strchr(i, ']') && load) {
 			struct smiley_list *child = g_new0(struct smiley_list, 1);
 			child->sml = g_strndup(i+1, strchr(i, ']') - i - 1);
+			child->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
 			if (theme->list)
 				list->next = child;
 			else
@@ -320,6 +325,7 @@
 				} else {
 					GtkIMHtmlSmiley *smiley = gtk_imhtml_smiley_create(sfile, l, hidden, 0);
 					list->smileys = g_slist_prepend(list->smileys, smiley);
+					g_hash_table_insert (list->files, g_strdup(l), g_strdup(sfile));
 				}
 				while (isspace(*i))
 					i++;
@@ -358,7 +364,6 @@
 
 			if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) {
 				/* We want to see our custom smileys on our entry if we write the shortcut */
-				pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml);
 				pidgin_themes_smiley_themeize_custom(PIDGIN_CONVERSATION(conv)->entry);
 			}
 		}
--- a/pidgin/gtkthemes.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkthemes.h	Mon Oct 31 01:25:36 2011 +0000
@@ -29,6 +29,7 @@
 struct smiley_list {
 	char *sml;
 	GSList *smileys;
+	GHashTable *files; /**< map from smiley shortcut to filename */
 	struct smiley_list *next;
 };
 
@@ -51,18 +52,12 @@
 
 void pidgin_themes_smiley_themeize(GtkWidget *);
 
-/**
- * @since 2.5.0
- */
 void pidgin_themes_smiley_themeize_custom(GtkWidget *);
 
 void pidgin_themes_smiley_theme_probe(void);
 
 void pidgin_themes_load_smiley_theme(const char *file, gboolean load);
 
-/**
- * @since 2.1.0
- */
 void pidgin_themes_remove_smiley_theme(const char *file);
 
 GSList *pidgin_themes_get_proto_smileys(const char *id);
--- a/pidgin/gtkutils.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkutils.c	Mon Oct 31 01:25:36 2011 +0000
@@ -67,6 +67,7 @@
 #include "pidginstock.h"
 #include "gtkthemes.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 #include "pidgin/minidialog.h"
 
 typedef struct {
@@ -276,6 +277,69 @@
 	return frame;
 }
 
+GtkWidget *
+pidgin_create_webview(gboolean editable, GtkWidget **webview_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret)
+{
+	GtkWidget *frame;
+	GtkWidget *webview;
+	GtkWidget *sep;
+	GtkWidget *sw;
+	GtkWidget *toolbar = NULL;
+	GtkWidget *vbox;
+
+	frame = gtk_frame_new(NULL);
+	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	gtk_widget_show(vbox);
+
+	if (editable) {
+		toolbar = gtk_imhtmltoolbar_new();
+		gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
+		gtk_widget_show(toolbar);
+
+		sep = gtk_hseparator_new();
+		gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
+		g_signal_connect_swapped(G_OBJECT(toolbar), "show", G_CALLBACK(gtk_widget_show), sep);
+		g_signal_connect_swapped(G_OBJECT(toolbar), "hide", G_CALLBACK(gtk_widget_hide), sep);
+		gtk_widget_show(sep);
+	}
+
+	webview = gtk_webview_new();
+#if 0
+	/* TODO WEBKIT: Don't have editable webview yet. */
+	gtk_webview_set_editable(GTK_WEBVIEW(webview), editable);
+#endif /* if 0 */
+#ifdef USE_GTKSPELL
+	if (editable && purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck"))
+		pidgin_setup_gtkspell(GTK_TEXT_VIEW(webview));
+#endif
+	gtk_widget_show(webview);
+
+	if (editable) {
+		gtk_imhtmltoolbar_attach(GTK_IMHTMLTOOLBAR(toolbar), webview);
+		gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(toolbar), "default");
+	}
+
+	sw = pidgin_make_scrollable(webview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1);
+	gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
+
+	gtk_webview_set_vadjustment(GTK_WEBVIEW(webview),
+			gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw)));
+
+	if (webview_ret != NULL)
+		*webview_ret = webview;
+
+	if (editable && (toolbar_ret != NULL))
+		*toolbar_ret = toolbar;
+
+	if (sw_ret != NULL)
+		*sw_ret = sw;
+
+	return frame;
+}
+
 void
 pidgin_set_sensitive_if_input(GtkWidget *entry, GtkWidget *dialog)
 {
@@ -922,24 +986,6 @@
 	return optmenu;
 }
 
-gboolean
-pidgin_check_if_dir(const char *path, GtkFileSelection *filesel)
-{
-	char *dirname = NULL;
-
-	if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
-		/* append a / if needed */
-		if (path[strlen(path) - 1] != G_DIR_SEPARATOR) {
-			dirname = g_strconcat(path, G_DIR_SEPARATOR_S, NULL);
-		}
-		gtk_file_selection_set_filename(filesel, (dirname != NULL) ? dirname : path);
-		g_free(dirname);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
 void
 pidgin_setup_gtkspell(GtkTextView *textview)
 {
@@ -1002,7 +1048,7 @@
 show_retrieveing_info(PurpleConnection *conn, const char *name)
 {
 	PurpleNotifyUserInfo *info = purple_notify_user_info_new();
-	purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
+	purple_notify_user_info_add_pair_plaintext(info, _("Information"), _("Retrieving..."));
 	purple_notify_userinfo(conn, name, info, NULL, NULL);
 	purple_notify_user_info_destroy(info);
 }
@@ -1023,7 +1069,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 +1195,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 +1237,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);
@@ -1308,7 +1354,7 @@
 
 	monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
 
-	push_in = FALSE;
+	*push_in = FALSE;
 
 	/*
 	 * The placement of popup menus horizontally works like this (with
@@ -1603,7 +1649,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;
@@ -1834,21 +1880,27 @@
                             gpointer object)
 {
 	GtkWidget *menuitem;
+	GList *list;
 
 	if (act == NULL) {
 		return pidgin_separator(menu);
 	}
 
-	if (act->children == NULL) {
-		menuitem = gtk_menu_item_new_with_mnemonic(act->label);
-
-		if (act->callback != NULL) {
+	list = purple_menu_action_get_children(act);
+	menuitem = gtk_menu_item_new_with_mnemonic(purple_menu_action_get_label(act));
+
+	if (list == NULL) {
+		PurpleCallback callback;
+
+		callback = purple_menu_action_get_callback(act);
+
+		if (callback != NULL) {
 			g_object_set_data(G_OBJECT(menuitem),
 							  "purplecallback",
-							  act->callback);
+							  callback);
 			g_object_set_data(G_OBJECT(menuitem),
 							  "purplecallbackdata",
-							  act->data);
+							  purple_menu_action_get_data(act));
 			g_signal_connect(G_OBJECT(menuitem), "activate",
 							 G_CALLBACK(menu_action_cb),
 							 object);
@@ -1862,7 +1914,6 @@
 		GtkWidget *submenu = NULL;
 		GtkAccelGroup *group;
 
-		menuitem = gtk_menu_item_new_with_mnemonic(act->label);
 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 
 		submenu = gtk_menu_new();
@@ -1870,19 +1921,20 @@
 
 		group = gtk_menu_get_accel_group(GTK_MENU(menu));
 		if (group) {
-			char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label);
+			char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path,
+					purple_menu_action_get_label(act));
 			gtk_menu_set_accel_path(GTK_MENU(submenu), path);
 			g_free(path);
 			gtk_menu_set_accel_group(GTK_MENU(submenu), group);
 		}
 
-		for (l = act->children; l; l = l->next) {
+		for (l = list; l; l = l->next) {
 			PurpleMenuAction *act = (PurpleMenuAction *)l->data;
 
 			pidgin_append_menu_action(submenu, act, object);
 		}
-		g_list_free(act->children);
-		act->children = NULL;
+		g_list_free(list);
+		purple_menu_action_set_children(act, NULL);
 	}
 	purple_menu_action_free(act);
 	return menuitem;
@@ -2082,8 +2134,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)
 													 );
 				}
 			}
@@ -2175,19 +2227,12 @@
 	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));
 	}
 }
 
-void
-pidgin_setup_screenname_autocomplete(GtkWidget *entry, GtkWidget *accountopt, gboolean all) {
-	pidgin_setup_screenname_autocomplete_with_filter(entry, accountopt, pidgin_screenname_autocomplete_default_filter, GINT_TO_POINTER(all));
-}
-
-
-
 void pidgin_set_cursor(GtkWidget *widget, GdkCursorType cursor_type)
 {
 	GdkCursor *cursor;
@@ -2533,21 +2578,6 @@
 	return NULL;
 }
 
-void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename)
-{
-	PurpleBuddy *buddy;
-	PurpleContact *contact;
-
-	buddy = purple_find_buddy(account, who);
-	if (!buddy) {
-		purple_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n");
-		return;
-	}
-
-	contact = purple_buddy_get_contact(buddy);
-	purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, filename);
-}
-
 char *pidgin_make_pretty_arrows(const char *str)
 {
 	char *ret;
@@ -3450,7 +3480,7 @@
 		return TRUE;
 	purple_request_file(conv->active_conv, _("Save File"), NULL, TRUE,
 	                    G_CALLBACK(savefile_write_cb), NULL,
-	                    conv->active_conv->account, NULL, conv->active_conv,
+	                    purple_conversation_get_account(conv->active_conv), NULL, conv->active_conv,
 	                    (void *)url);
 	return TRUE;
 }
--- a/pidgin/gtkutils.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkutils.h	Mon Oct 31 01:25:36 2011 +0000
@@ -109,12 +109,34 @@
 GtkWidget *pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret);
 
 /**
+ * Create an GtkWebView widget and associated GtkIMHtmlToolbar widget.  This
+ * function puts both widgets in a nice GtkFrame.  They're separated by an
+ * attractive GtkSeparator.
+ * TODO WEBKIT: editable isn't supported yet
+ *
+ * @param editable @c TRUE if this webview should be editable.  If this is
+ *        @c FALSE, then the toolbar will NOT be created.  If this webview
+ *        should be read-only at first, but may become editable later, then
+ *        pass in @c TRUE here and then manually call gtk_webview_set_editable()
+ *        later.
+ * @param webview_ret A pointer to a pointer to a GtkWidget.  This pointer
+ *        will be set to the webview when this function exits.
+ * @param toolbar_ret A pointer to a pointer to a GtkWidget.  If editable is
+ *        TRUE then this will be set to the toolbar when this function exits.
+ *        Otherwise this will be set to @c NULL.
+ * @param sw_ret This will be filled with a pointer to the scrolled window
+ *        widget which contains the webview.
+ *
+ * @return The GtkFrame containing the toolbar and webview.
+ */
+GtkWidget *pidgin_create_webview(gboolean editable, GtkWidget **webview_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret);
+
+/**
  * Creates a small button
  *
  * @param  image   A button image.
  *
  * @return   A GtkButton created from the image.
- * @since 2.7.0
  */
 GtkWidget *pidgin_create_small_button(GtkWidget *image);
 
@@ -125,8 +147,6 @@
  * @param border_width The window's desired border width
  * @param role         A string indicating what the window is responsible for doing, or @c NULL
  * @param resizable    Whether the window should be resizable (@c TRUE) or not (@c FALSE)
- *
- * @since 2.1.0
  */
 GtkWidget *pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable);
 
@@ -137,8 +157,6 @@
  * @param border_width The window's desired border width
  * @param role         A string indicating what the window is responsible for doing, or @c NULL
  * @param resizable    Whether the window should be resizable (@c TRUE) or not (@c FALSE)
- *
- * @since 2.4.0
  */
 GtkWidget *pidgin_create_dialog(const char *title, guint border_width, const char *role, gboolean resizable);
 
@@ -148,8 +166,6 @@
  * @param dialog       The dialog window
  * @param homogeneous  TRUE if all children are to be given equal space allotments.
  * @param spacing      the number of pixels to place by default between children
- *
- * @since 2.4.0
  */
 GtkWidget *pidgin_dialog_get_vbox_with_properties(GtkDialog *dialog, gboolean homogeneous, gint spacing);
 
@@ -157,8 +173,6 @@
  * Retrieves the main content box (vbox) from a pidgin dialog window
  *
  * @param dialog       The dialog window
- *
- * @since 2.4.0
  */
 GtkWidget *pidgin_dialog_get_vbox(GtkDialog *dialog);
 
@@ -171,7 +185,6 @@
  * @param callbackdata   The user data for the callback function
  *
  * @return The created button.
- * @since 2.4.0
  */
 GtkWidget *pidgin_dialog_add_button(GtkDialog *dialog, const char *label,
 		GCallback callback, gpointer callbackdata);
@@ -180,8 +193,6 @@
  * Retrieves the action area (button box) from a pidgin dialog window
  *
  * @param dialog       The dialog window
- *
- * @since 2.4.0
  */
 GtkWidget *pidgin_dialog_get_action_area(GtkDialog *dialog);
 
@@ -384,39 +395,6 @@
 gboolean pidgin_screenname_autocomplete_default_filter(const PidginBuddyCompletionEntry *completion_entry, gpointer all_accounts);
 
 /**
- * Add autocompletion of screenames to an entry.
- *
- * @deprecated
- *   For new code, use the equivalent:
- *   #pidgin_setup_screenname_autocomplete_with_filter(@a entry, @a optmenu,
- *   #pidgin_screenname_autocomplete_default_filter, <tt>GINT_TO_POINTER(@a
- *   all)</tt>)
- *
- * @param entry     The GtkEntry on which to setup autocomplete.
- * @param optmenu   A menu for accounts, returned by
- *                  pidgin_account_option_menu_new().  If @a optmenu is not @c
- *                  NULL, it'll be updated when a username is chosen from the
- *                  autocomplete list.
- * @param all       Whether to include usernames from disconnected accounts.
- */
-void pidgin_setup_screenname_autocomplete(GtkWidget *entry, GtkWidget *optmenu, gboolean all);
-
-/**
- * Check if the given path is a directory or not.  If it is, then modify
- * the given GtkFileSelection dialog so that it displays the given path.
- * If the given path is not a directory, then do nothing.
- *
- * @param path    The path entered in the file selection window by the user.
- * @param filesel The file selection window.
- *
- * @return TRUE if given path is a directory, FALSE otherwise.
- * @deprecated Pidgin no longer uses GtkFileSelection internally. It has also
- *             been deprecated by GTK+. Use GtkFileChooser instead and ignore
- *             this function.
- */
-gboolean pidgin_check_if_dir(const char *path, GtkFileSelection *filesel);
-
-/**
  * Sets up GtkSpell for the given GtkTextView, reporting errors
  * if encountered.
  *
@@ -448,8 +426,6 @@
  *
  * @param conn   The connection to get information from.
  * @param name   The user to get information about.
- *
- * @since 2.1.0
  */
 void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name);
 
@@ -459,8 +435,6 @@
  * @param conn   The connection to get information from.
  * @param name   The user to get information about.
  * @param chatid The chat id.
- *
- * @since 2.1.0
  */
 void pidgin_retrieve_user_info_in_chat(PurpleConnection *conn, const char *name, int chatid);
 
@@ -499,8 +473,6 @@
  *
  * @param w The widget that we want to label.
  * @param l A GtkLabel that we want to use as the label for the widget.
- *
- * @since 2.2.0
  */
 void pidgin_set_accessible_relations(GtkWidget *w, GtkWidget *l);
 
@@ -515,8 +487,6 @@
  *        where the menu shall be drawn. This is an output parameter.
  * @param push_in This is an output parameter?
  * @param data Not used by this particular position function.
- *
- * @since 2.1.0
  */
 void pidgin_menu_position_func_helper(GtkMenu *menu, gint *x, gint *y,
 										gboolean *push_in, gpointer data);
@@ -588,8 +558,6 @@
  * @param prim   The status primitive
  *
  * @return The stock-id
- *
- * @since 2.6.0
  */
 const char *pidgin_stock_id_from_status_primitive(PurpleStatusPrimitive prim);
 
@@ -599,8 +567,6 @@
  * @param presence   The presence.
  *
  * @return The stock-id
- *
- * @since 2.6.0
  */
 const char *pidgin_stock_id_from_presence(PurplePresence *presence);
 
@@ -661,19 +627,6 @@
  */
 gpointer pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len);
 
-#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKUTILS_C_)
-/**
- * Set or unset a custom buddyicon for a user.
- *
- * @param account   The account the user belongs to.
- * @param who       The name of the user.
- * @param filename  The path of the custom icon. If this is @c NULL, then any
- *                  previously set custom buddy icon for the user is removed.
- * @deprecated See purple_buddy_icons_node_set_custom_icon_from_file()
- */
-void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename);
-#endif
-
 /**
  * Converts "->" and "<-" in strings to Unicode arrow characters, for use in referencing
  * menu items.
@@ -781,8 +734,6 @@
  *
  * @return               A newly created text GtkComboBox containing a GtkEntry
  *                       child.
- *
- * @since 2.2.0
  */
 GtkWidget *pidgin_text_combo_box_entry_new(const char *default_item, GList *items);
 
@@ -792,8 +743,6 @@
  * @param widget         The simple text GtkComboBoxEntry equivalent widget
  *
  * @return               The text in the widget's entry. It must not be freed
- *
- * @since 2.2.0
  */
 const char *pidgin_text_combo_box_entry_get_text(GtkWidget *widget);
 
@@ -802,8 +751,6 @@
  *
  * @param widget         The simple text GtkComboBoxEntry equivalent widget
  * @param text           The text to set
- *
- * @since 2.2.0
  */
 void pidgin_text_combo_box_entry_set_text(GtkWidget *widget, const char *text);
 
@@ -813,8 +760,6 @@
  * @param window    The window to make transient.
  *
  * @return Whether the window was made transient or not.
- *
- * @since 2.4.0
  */
 gboolean pidgin_auto_parent_window(GtkWidget *window);
 
@@ -829,7 +774,6 @@
  * @param p_label      Place to store a pointer to the GtkLabel, or @c NULL if you don't care.
  *
  * @return  A GtkHBox already added to the GtkVBox containing the GtkLabel and the GtkWidget.
- * @since 2.4.0
  */
 GtkWidget *pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label);
 
@@ -841,8 +785,6 @@
  *
  * @return A GdkPixbuf created from the image data, or NULL if
  *         there was an error parsing the data.
- *
- * @since 2.9.0
  */
 GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count);
 
@@ -854,8 +796,6 @@
  *
  * @return A GdkPixbufAnimation created from the image data, or NULL if
  *         there was an error parsing the data.
- *
- * @since 2.9.0
  */
 GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count);
 
@@ -865,8 +805,6 @@
  * @param  image   A PurpleStoredImage.
  *
  * @return   A GdkPixbuf created from the stored image.
- *
- * @since 2.5.0
  */
 GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image);
 
@@ -890,8 +828,6 @@
  *
  * @return The GdkPixbuf if successful.  Otherwise NULL is returned and
  *         a warning is logged.
- *
- * @since 2.9.0
  */
 GdkPixbuf *pidgin_pixbuf_new_from_file(const char *filename);
 
@@ -917,8 +853,6 @@
  *
  * @return The GdkPixbuf if successful.  Otherwise NULL is returned and
  *         a warning is logged.
- *
- * @since 2.9.0
  */
 GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height);
 
@@ -945,35 +879,27 @@
  *
  * @return The GdkPixbuf if successful.  Otherwise NULL is returned and
  *         a warning is logged.
- *
- * @since 2.9.0
  */
 GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio);
 
 /**
  * Add scrollbars to a widget
- * @param widget      The child widget
- * @hscrollbar_policy Horizontal scrolling policy
- * @vscrollbar_policy Vertical scrolling policy
- * @shadow            Shadow type
- * @width             Desired widget width, or -1 for default
- * @height            Desired widget height, or -1 for default
- *
- * @since 2.8.0
+ * @param child              The child widget
+ * @param hscrollbar_policy  Horizontal scrolling policy
+ * @param vscrollbar_policy  Vertical scrolling policy
+ * @param shadow_type        Shadow type
+ * @param width              Desired widget width, or -1 for default
+ * @param height             Desired widget height, or -1 for default
  */
 GtkWidget *pidgin_make_scrollable(GtkWidget *child, GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy, GtkShadowType shadow_type, int width, int height);
 
 /**
  * Initialize some utility functions.
- *
- * @since 2.6.0
  */
 void pidgin_utils_init(void);
 
 /**
  * Uninitialize some utility functions.
- *
- * @since 2.6.0
  */
 void pidgin_utils_uninit(void);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkwebview.c	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,419 @@
+/*
+ * @file gtkwebview.c GTK+ WebKitWebView wrapper class.
+ * @ingroup pidgin
+ */
+
+/* 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <JavaScriptCore/JavaScript.h>
+
+#include "util.h"
+#include "gtkwebview.h"
+#include "imgstore.h"
+
+static WebKitWebViewClass *parent_class = NULL;
+
+struct GtkWebViewPriv {
+	GHashTable *images; /**< a map from id to temporary file for the image */
+	gboolean empty;  /**< whether anything has been appended **/
+
+	/* JS execute queue */
+	GQueue *js_queue;
+	gboolean is_loading;
+	GtkAdjustment *vadj;
+	guint scroll_src;
+	GTimer *scroll_time;
+};
+
+GtkWidget *
+gtk_webview_new(void)
+{
+	GtkWebView* ret = GTK_WEBVIEW(g_object_new(gtk_webview_get_type(), NULL));
+	return GTK_WIDGET(ret);
+}
+
+static char *
+get_image_filename_from_id(GtkWebView* view, int id)
+{
+	char *filename = NULL;
+	FILE *file;
+	PurpleStoredImage* img;
+
+	if (!view->priv->images)
+		view->priv->images = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
+
+	filename = (char *)g_hash_table_lookup(view->priv->images, GINT_TO_POINTER(id));
+	if (filename)
+		return filename;
+
+	/* else get from img store */
+	file = purple_mkstemp(&filename, TRUE);
+
+	img = purple_imgstore_find_by_id(id);
+
+	fwrite(purple_imgstore_get_data(img), purple_imgstore_get_size(img), 1, file);
+	g_hash_table_insert(view->priv->images, GINT_TO_POINTER(id), filename);
+	fclose(file);
+	return filename;
+}
+
+static void
+clear_single_image(gpointer key, gpointer value, gpointer userdata)
+{
+	g_unlink((char *)value);
+}
+
+static void
+clear_images(GtkWebView *view)
+{
+	if (!view->priv->images)
+		return;
+	g_hash_table_foreach(view->priv->images, clear_single_image, NULL);
+	g_hash_table_unref(view->priv->images);
+}
+
+/*
+ * Replace all <img id=""> tags with <img src="">. I hoped to never
+ * write any HTML parsing code, but I'm forced to do this, until
+ * purple changes the way it works.
+ */
+static char *
+replace_img_id_with_src(GtkWebView *view, const char *html)
+{
+	GString *buffer = g_string_sized_new(strlen(html));
+	const char* cur = html;
+	char *id;
+	int nid;
+
+	while (*cur) {
+		const char *img = strstr(cur, "<img");
+		if (!img) {
+			g_string_append(buffer, cur);
+			break;
+		} else
+			g_string_append_len(buffer, cur, img - cur);
+
+		cur = strstr(img, "/>");
+		if (!cur)
+			cur = strstr(img, ">");
+
+		if (!cur) { /* invalid html? */
+			g_string_printf(buffer, "%s", html);
+			break;
+		}
+
+		if (strstr(img, "src=") || !strstr(img, "id=")) {
+			g_string_printf(buffer, "%s", html);
+			break;
+		}
+
+		/*
+		 * if this is valid HTML, then I can be sure that it
+		 * has an id= and does not have an src=, since
+		 * '=' cannot appear in parameters.
+		 */
+
+		id = strstr(img, "id=") + 3;
+
+		/* *id can't be \0, since a ">" appears after this */
+		if (isdigit(*id))
+			nid = atoi(id);
+		else
+			nid = atoi(id + 1);
+
+		/* let's dump this, tag and then dump the src information */
+		g_string_append_len(buffer, img, cur - img);
+
+		g_string_append_printf(buffer, " src='file://%s' ", get_image_filename_from_id(view, nid));
+	}
+
+	return g_string_free(buffer, FALSE);
+}
+
+static void
+gtk_webview_finalize(GObject *view)
+{
+	gpointer temp;
+
+	while ((temp = g_queue_pop_head(GTK_WEBVIEW(view)->priv->js_queue)))
+		g_free(temp);
+	g_queue_free(GTK_WEBVIEW(view)->priv->js_queue);
+
+	clear_images(GTK_WEBVIEW(view));
+	g_free(GTK_WEBVIEW(view)->priv);
+	G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(view));
+}
+
+static void
+gtk_webview_class_init(GtkWebViewClass *klass, gpointer userdata)
+{
+	parent_class = g_type_class_ref(webkit_web_view_get_type());
+	G_OBJECT_CLASS(klass)->finalize = gtk_webview_finalize;
+}
+
+static gboolean
+webview_link_clicked(WebKitWebView *view,
+		      WebKitWebFrame *frame,
+		      WebKitNetworkRequest *request,
+		      WebKitWebNavigationAction *navigation_action,
+		      WebKitWebPolicyDecision *policy_decision)
+{
+	const gchar *uri;
+	WebKitWebNavigationReason reason;
+
+	uri = webkit_network_request_get_uri(request);
+	reason = webkit_web_navigation_action_get_reason(navigation_action);
+
+	if (reason == WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) {
+		/* the gtk imhtml way was to create an idle cb, not sure
+		 * why, so right now just using purple_notify_uri directly */
+		purple_notify_uri(NULL, uri);
+	} else
+		webkit_web_policy_decision_use(policy_decision);
+
+	return TRUE;
+}
+
+static gboolean
+process_js_script_queue(GtkWebView *view)
+{
+	char *script;
+	if (view->priv->is_loading)
+		return FALSE; /* we will be called when loaded */
+	if (!view->priv->js_queue || g_queue_is_empty(view->priv->js_queue))
+		return FALSE; /* nothing to do! */
+
+	script = g_queue_pop_head(view->priv->js_queue);
+	webkit_web_view_execute_script(WEBKIT_WEB_VIEW(view), script);
+	g_free(script);
+
+	return TRUE; /* there may be more for now */
+}
+
+static void
+webview_load_started(WebKitWebView *view,
+		      WebKitWebFrame *frame,
+		      gpointer userdata)
+{
+	/* is there a better way to test for is_loading? */
+	GTK_WEBVIEW(view)->priv->is_loading = TRUE;
+}
+
+static void
+webview_load_finished(WebKitWebView *view,
+		       WebKitWebFrame *frame,
+		       gpointer userdata)
+{
+	GTK_WEBVIEW(view)->priv->is_loading = FALSE;
+	g_idle_add((GSourceFunc)process_js_script_queue, view);
+}
+
+void
+gtk_webview_safe_execute_script(GtkWebView *view, const char *script)
+{
+	g_queue_push_tail(view->priv->js_queue, g_strdup(script));
+	g_idle_add((GSourceFunc)process_js_script_queue, view);
+}
+
+static void
+gtk_webview_init(GtkWebView *view, gpointer userdata)
+{
+	view->priv = g_new0(struct GtkWebViewPriv, 1);
+	g_signal_connect(view, "navigation-policy-decision-requested",
+			  G_CALLBACK(webview_link_clicked),
+			  view);
+
+	g_signal_connect(view, "load-started",
+			  G_CALLBACK(webview_load_started),
+			  view);
+
+	g_signal_connect(view, "load-finished",
+			  G_CALLBACK(webview_load_finished),
+			  view);
+
+	view->priv->empty = TRUE;
+	view->priv->js_queue = g_queue_new();
+}
+
+
+void
+gtk_webview_load_html_string_with_imgstore(GtkWebView *view, const char *html)
+{
+	char *html_imged;
+
+	clear_images(view);
+	html_imged = replace_img_id_with_src(view, html);
+	webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(view), html_imged, "file:///");
+	g_free(html_imged);
+}
+
+char *
+gtk_webview_quote_js_string(const char *text)
+{
+	GString *str = g_string_new("\"");
+	const char *cur = text;
+
+	while (cur && *cur) {
+		switch (*cur) {
+			case '\\':
+				g_string_append(str, "\\\\");
+				break;
+			case '\"':
+				g_string_append(str, "\\\"");
+				break;
+			case '\r':
+				g_string_append(str, "<br/>");
+				break;
+			case '\n':
+				break;
+			default:
+				g_string_append_c(str, *cur);
+		}
+		cur++;
+	}
+	g_string_append_c(str, '"');
+	return g_string_free(str, FALSE);
+}
+
+void
+gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj)
+{
+	webview->priv->vadj = vadj;
+}
+
+/* this is a "hack", my plan is to eventually handle this
+ * correctly using a signals and a plugin: the plugin will have
+ * the information as to what javascript function to call. It seems
+ * wrong to hardcode that here.
+ */
+void
+gtk_webview_append_html(GtkWebView *view, const char *html)
+{
+	char *escaped = gtk_webview_quote_js_string(html);
+	char *script = g_strdup_printf("document.write(%s)", escaped);
+	webkit_web_view_execute_script(WEBKIT_WEB_VIEW(view), script);
+	view->priv->empty = FALSE;
+	gtk_webview_scroll_to_end(view, TRUE);
+	g_free(script);
+	g_free(escaped);
+}
+
+gboolean
+gtk_webview_is_empty(GtkWebView *view)
+{
+	return view->priv->empty;
+}
+
+#define MAX_SCROLL_TIME 0.4 /* seconds */
+#define SCROLL_DELAY 33 /* milliseconds */
+
+/*
+ * Smoothly scroll a WebView.
+ *
+ * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom.
+ */
+static gboolean
+smooth_scroll_cb(gpointer data)
+{
+	struct GtkWebViewPriv *priv = data;
+	GtkAdjustment *adj = priv->vadj;
+	gdouble max_val = adj->upper - adj->page_size;
+	gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3);
+
+	g_return_val_if_fail(priv->scroll_time != NULL, FALSE);
+
+	if (g_timer_elapsed(priv->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) {
+		/* time's up. jump to the end and kill the timer */
+		gtk_adjustment_set_value(adj, max_val);
+		g_timer_destroy(priv->scroll_time);
+		priv->scroll_time = NULL;
+		g_source_remove(priv->scroll_src);
+		priv->scroll_src = 0;
+		return FALSE;
+	}
+
+	/* scroll by 1/3rd the remaining distance */
+	gtk_adjustment_set_value(adj, scroll_val);
+	return TRUE;
+}
+
+static gboolean
+scroll_idle_cb(gpointer data)
+{
+	struct GtkWebViewPriv *priv = data;
+	GtkAdjustment *adj = priv->vadj;
+	if (adj) {
+		gtk_adjustment_set_value(adj, adj->upper - adj->page_size);
+	}
+	priv->scroll_src = 0;
+	return FALSE;
+}
+
+void
+gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth)
+{
+	struct GtkWebViewPriv *priv = webview->priv;
+	if (priv->scroll_time)
+		g_timer_destroy(priv->scroll_time);
+	if (priv->scroll_src)
+		g_source_remove(priv->scroll_src);
+	if(smooth) {
+		priv->scroll_time = g_timer_new();
+		priv->scroll_src = g_timeout_add_full(G_PRIORITY_LOW, SCROLL_DELAY, smooth_scroll_cb, priv, NULL);
+	} else {
+		priv->scroll_time = NULL;
+		priv->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, priv, NULL);
+	}
+}
+
+GType
+gtk_webview_get_type(void)
+{
+	static GType mview_type = 0;
+	if (G_UNLIKELY(mview_type == 0)) {
+		static const GTypeInfo mview_info = {
+			sizeof(GtkWebViewClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gtk_webview_class_init,
+			NULL,
+			NULL,
+			sizeof(GtkWebView),
+			0,
+			(GInstanceInitFunc) gtk_webview_init,
+			NULL
+		};
+		mview_type = g_type_register_static(webkit_web_view_get_type(),
+				"GtkWebView", &mview_info, 0);
+	}
+	return mview_type;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/gtkwebview.h	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,147 @@
+/**
+ * @file gtkwebview.h Wrapper over the Gtk WebKitWebView component
+ * @ingroup pidgin
+ */
+
+/* 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
+ *
+ */
+
+#ifndef _PIDGIN_WEBVIEW_H_
+#define _PIDGIN_WEBVIEW_H_
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <webkit/webkit.h>
+
+#include "notify.h"
+
+#define GTK_TYPE_WEBVIEW            (gtk_webview_get_type())
+#define GTK_WEBVIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_WEBVIEW, GtkWebView))
+#define GTK_WEBVIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_WEBVIEW, GtkWebViewClass))
+#define GTK_IS_WEBVIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_WEBVIEW))
+#define GTK_IS_WEBVIEW_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_WEBVIEW))
+
+
+struct GtkWebViewPriv;
+
+struct _GtkWebView
+{
+	WebKitWebView webkit_web_view;
+
+	/*< private >*/
+	struct GtkWebViewPriv *priv;
+};
+
+typedef struct _GtkWebView GtkWebView;
+
+struct _GtkWebViewClass
+{
+	WebKitWebViewClass parent;
+};
+
+typedef struct _GtkWebViewClass GtkWebViewClass;
+
+
+/**
+ * Returns the GType for a 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
+ */
+GtkWidget *gtk_webview_new(void);
+
+/**
+ * Set the vertical adjustment for the GtkWebView.
+ *
+ * @param webview  The GtkWebView object
+ * @param vadj     The GtkAdjustment that control the webview
+ */
+void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj);
+
+/**
+ * A very basic routine to append html, which can be considered
+ * equivalent to a "document.write" using JavaScript.
+ *
+ * @param webview The GtkWebView object
+ * @param markup  The html markup to append
+ */
+void gtk_webview_append_html(GtkWebView *webview, const char *markup);
+
+/**
+ * Rather than use webkit_webview_load_string, this routine
+ * parses and displays the \<img id=?\> tags that make use of the
+ * Pidgin imgstore.
+ *
+ * @param webview The GtkWebView object
+ * @param html    The HTML content to load
+ */
+void gtk_webview_load_html_string_with_imgstore(GtkWebView *webview, const char *html);
+
+/**
+ * TODO WEBKIT: Right now this just tests whether an append has been called
+ * since the last clear or since the Widget was created.  So it does not
+ * test for load_string's called in between.
+ *
+ * @param webview The GtkWebView object
+ *
+ * @return gboolean indicating whether the webview is empty
+ */
+gboolean gtk_webview_is_empty(GtkWebView *webview);
+
+/**
+ * Execute the JavaScript only after the webkit_webview_load_string
+ * loads completely. We also guarantee that the scripts are executed
+ * in the order they are called here. This is useful to avoid race
+ * conditions when calling JS functions immediately after opening the
+ * page.
+ *
+ * @param webview The GtkWebView object
+ * @param script  The script to execute
+ */
+void gtk_webview_safe_execute_script(GtkWebView *webview, const char *script);
+
+/**
+ * A convenience routine to quote a string for use as a JavaScript
+ * string. For instance, "hello 'world'" becomes "'hello \\'world\\''"
+ *
+ * @param str The string to escape and quote
+ *
+ * @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 object
+ * @param smooth  A boolean indicating if smooth scrolling should be used
+ */
+void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth);
+
+#endif /* _PIDGIN_WEBVIEW_H_ */
+
--- a/pidgin/gtkwhiteboard.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/gtkwhiteboard.c	Mon Oct 31 01:25:36 2011 +0000
@@ -125,7 +125,7 @@
 	PidginWhiteboard *gtkwb = g_new0(PidginWhiteboard, 1);
 
 	gtkwb->wb = wb;
-	wb->ui_data = gtkwb;
+	purple_whiteboard_set_ui_data(wb, gtkwb);
 
 	/* Get dimensions (default?) for the whiteboard canvas */
 	if (!purple_whiteboard_get_dimensions(wb, &gtkwb->width, &gtkwb->height))
@@ -145,11 +145,11 @@
 	/* Try and set window title as the name of the buddy, else just use their
 	 * username
 	 */
-	buddy = purple_find_buddy(wb->account, wb->who);
+	buddy = purple_find_buddy(purple_whiteboard_get_account(wb), purple_whiteboard_get_who(wb));
 
-	window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : wb->who, 0, NULL, FALSE);
+	window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : purple_whiteboard_get_who(wb), 0, NULL, FALSE);
 	gtkwb->window = window;
-	gtk_widget_set_name(window, wb->who);
+	gtk_widget_set_name(window, purple_whiteboard_get_who(wb));
 
 	g_signal_connect(G_OBJECT(window), "delete_event",
 					 G_CALLBACK(whiteboard_close_cb), gtkwb);
@@ -274,7 +274,7 @@
 	GtkWidget *colour_dialog;
 
 	g_return_if_fail(wb != NULL);
-	gtkwb = wb->ui_data;
+	gtkwb = purple_whiteboard_get_ui_data(wb);
 	g_return_if_fail(gtkwb != NULL);
 
 	/* TODO Ask if user wants to save picture before the session is closed */
@@ -301,7 +301,7 @@
 		gtkwb->window = NULL;
 	}
 	g_free(gtkwb);
-	wb->ui_data = NULL;
+	purple_whiteboard_set_ui_data(wb, NULL);
 }
 
 static gboolean whiteboard_close_cb(GtkWidget *widget, GdkEvent *event, PidginWhiteboard *gtkwb)
@@ -406,7 +406,7 @@
 	GdkPixmap *pixmap = gtkwb->pixmap;
 
 	PurpleWhiteboard *wb = gtkwb->wb;
-	GList *draw_list = wb->draw_list;
+	GList *draw_list = purple_whiteboard_get_draw_list(wb);
 
 	if(BrushState != BRUSH_STATE_UP)
 	{
@@ -441,7 +441,7 @@
 											 gtkwb->brush_color, gtkwb->brush_size);
 	}
 
-	wb->draw_list = draw_list;
+	purple_whiteboard_set_draw_list(wb, draw_list);
 
 	return TRUE;
 }
@@ -459,7 +459,7 @@
 	GdkPixmap *pixmap = gtkwb->pixmap;
 
 	PurpleWhiteboard *wb = gtkwb->wb;
-	GList *draw_list = wb->draw_list;
+	GList *draw_list = purple_whiteboard_get_draw_list(wb);
 
 	if(event->is_hint)
 		gdk_window_get_pointer(event->window, &x, &y, &state);
@@ -528,7 +528,7 @@
 		LastY = y;
 	}
 
-	wb->draw_list = draw_list;
+	purple_whiteboard_set_draw_list(wb, draw_list);
 
 	return TRUE;
 }
@@ -539,7 +539,7 @@
 	GdkPixmap *pixmap = gtkwb->pixmap;
 
 	PurpleWhiteboard *wb = gtkwb->wb;
-	GList *draw_list = wb->draw_list;
+	GList *draw_list = purple_whiteboard_get_draw_list(wb);
 
 	if((BrushState != BRUSH_STATE_DOWN) && (BrushState != BRUSH_STATE_MOTION))
 	{
@@ -583,7 +583,7 @@
 		if(draw_list)
 			purple_whiteboard_draw_list_destroy(draw_list);
 
-		wb->draw_list = NULL;
+		purple_whiteboard_set_draw_list(wb, NULL);
 	}
 
 	return TRUE;
@@ -591,7 +591,7 @@
 
 static void pidgin_whiteboard_draw_brush_point(PurpleWhiteboard *wb, int x, int y, int color, int size)
 {
-	PidginWhiteboard *gtkwb = wb->ui_data;
+	PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb);
 	GtkWidget *widget = gtkwb->drawing_area;
 	GdkPixmap *pixmap = gtkwb->pixmap;
 
@@ -684,7 +684,7 @@
 
 static void pidgin_whiteboard_set_dimensions(PurpleWhiteboard *wb, int width, int height)
 {
-	PidginWhiteboard *gtkwb = wb->ui_data;
+	PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb);
 
 	gtkwb->width = width;
 	gtkwb->height = height;
@@ -692,7 +692,7 @@
 
 static void pidgin_whiteboard_set_brush(PurpleWhiteboard *wb, int size, int color)
 {
-	PidginWhiteboard *gtkwb = wb->ui_data;
+	PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb);
 
 	gtkwb->brush_size = size;
 	gtkwb->brush_color = color;
@@ -700,7 +700,7 @@
 
 static void pidgin_whiteboard_clear(PurpleWhiteboard *wb)
 {
-	PidginWhiteboard *gtkwb = wb->ui_data;
+	PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb);
 	GdkPixmap *pixmap = gtkwb->pixmap;
 	GtkWidget *drawing_area = gtkwb->drawing_area;
 	cairo_t *cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
--- a/pidgin/pidgin-2-uninstalled.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-abs_srcdir=@abs_srcdir@
-abs_builddir=@abs_builddir@
-
-abs_top_srcdir=@abs_top_srcdir@
-abs_top_builddir=@abs_top_builddir@
-
-plugindir=${libdir}/pidgin
-
-Name: Pidgin
-Description: Pidgin is a GTK2-based instant messenger application.
-Version: @VERSION@
-Requires: gtk+-2.0 purple
-Cflags: -I${abs_top_srcdir}
--- a/pidgin/pidgin-2.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-plugindir=${libdir}/pidgin
-
-Name: Pidgin
-Description: Pidgin is a GTK2-based instant messenger application.
-Version: @VERSION@
-Requires: gtk+-2.0 purple
-Cflags: -I${includedir}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidgin-3-uninstalled.pc.in	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,21 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+
+abs_srcdir=@abs_srcdir@
+abs_builddir=@abs_builddir@
+
+abs_top_srcdir=@abs_top_srcdir@
+abs_top_builddir=@abs_top_builddir@
+
+plugindir=${libdir}/pidgin
+
+Name: Pidgin
+Description: Pidgin is a GTK2-based instant messenger application.
+Version: @VERSION@
+Requires: gtk+-2.0 purple-3
+Cflags: -I${abs_top_srcdir}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidgin-3.pc.in	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+
+plugindir=${libdir}/pidgin
+
+Name: Pidgin
+Description: Pidgin is a GTK2-based instant messenger application.
+Version: @VERSION@
+Requires: gtk+-2.0 purple-3
+Cflags: -I${includedir}
--- a/pidgin/pidgin-uninstalled.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-abs_srcdir=@abs_srcdir@
-abs_builddir=@abs_builddir@
-
-plugindir=${libdir}/pidgin
-
-Name: Pidgin
-Description: Pidgin is a GTK2-based instant messenger application.
-Version: @VERSION@
-Requires: gtk+-2.0 purple
-Cflags: -I${abs_srcdir}
--- a/pidgin/pidgin.pc.in	Mon Oct 31 01:22:26 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-sysconfdir=@sysconfdir@
-
-plugindir=${libdir}/pidgin
-
-Name: Pidgin
-Description: Pidgin is a GTK2-based instant messenger application.
-Version: @VERSION@
-Requires: gtk+-2.0 purple
-Cflags: -I${includedir}/pidgin
-
--- a/pidgin/pidgintooltip.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/pidgintooltip.h	Mon Oct 31 01:25:36 2011 +0000
@@ -36,7 +36,6 @@
  * @param h          The value of this should be set to the desired height of the tooltip window.
  *
  * @return  @c TRUE if the tooltip was created correctly, @c FALSE otherwise.
- * @since 2.4.0
  */
 typedef gboolean (*PidginTooltipCreateForTree)(GtkWidget *tipwindow,
 			GtkTreePath *path, gpointer userdata, int *w, int *h);
@@ -48,7 +47,6 @@
  * @param h          The value of this should be set to the desired height of the tooltip window.
  *
  * @return  @c TRUE if the tooltip was created correctly, @c FALSE otherwise.
- * @since 2.4.0
  */
 typedef gboolean (*PidginTooltipCreate)(GtkWidget *tipwindow,
 			gpointer userdata, int *w, int *h);
@@ -58,7 +56,6 @@
  * @param  userdata    The userdata set during pidgin_tooltip_setup_for_treeview or pidgin_tooltip_show.
  *
  * @return  @c TRUE if the tooltip was painted correctly, @c FALSE otherwise.
- * @since 2.4.0
  */
 typedef gboolean (*PidginTooltipPaint)(GtkWidget *tipwindow, gpointer userdata);
 
@@ -71,7 +68,6 @@
  * @param paint_cb     Callback function to paint the tooltip
  *
  * @return   @c TRUE if the tooltip callbacks were setup correctly.
- * @since 2.4.0
  */
 gboolean pidgin_tooltip_setup_for_treeview(GtkWidget *tree, gpointer userdata,
 		PidginTooltipCreateForTree create_cb, PidginTooltipPaint paint_cb);
@@ -85,14 +81,12 @@
  * @param paint_cb     Callback function to paint the tooltip
  *
  * @return   @c TRUE if the tooltip callbacks were setup correctly.
- * @since 2.4.0
  */
 gboolean pidgin_tooltip_setup_for_widget(GtkWidget *widget, gpointer userdata,
 		PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb);
 
 /**
  * Destroy the tooltip.
- * @since 2.4.0
  */
 void pidgin_tooltip_destroy(void);
 
@@ -103,8 +97,6 @@
  * @param userdata    The userdata to send to the callback functions
  * @param create_cb    Callback function to create the tooltip from the GtkTreePath
  * @param paint_cb     Callback function to paint the tooltip
- *
- * @since 2.4.0
  */
 void pidgin_tooltip_show(GtkWidget *widget, gpointer userdata,
 		PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb);
--- a/pidgin/plugins/Makefile.am	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/Makefile.am	Mon Oct 31 01:25:36 2011 +0000
@@ -38,16 +38,14 @@
 gtkbuddynote_la_LDFLAGS     = -module -avoid-version
 history_la_LDFLAGS          = -module -avoid-version
 iconaway_la_LDFLAGS         = -module -avoid-version
-markerline_la_LDFLAGS       = -module -avoid-version
 notify_la_LDFLAGS           = -module -avoid-version
 pidginrc_la_LDFLAGS         = -module -avoid-version
 relnot_la_LDFLAGS           = -module -avoid-version
 sendbutton_la_LDFLAGS       = -module -avoid-version
 spellchk_la_LDFLAGS         = -module -avoid-version
 themeedit_la_LDFLAGS        = -module -avoid-version
-timestamp_la_LDFLAGS        = -module -avoid-version
-timestamp_format_la_LDFLAGS = -module -avoid-version
 vvconfig_la_LDFLAGS         = -module -avoid-version
+webkit_la_LDFLAGS           = -module -avoid-version
 xmppconsole_la_LDFLAGS      = -module -avoid-version
 
 if PLUGINS
@@ -58,15 +56,13 @@
 	gtkbuddynote.la     \
 	history.la          \
 	iconaway.la         \
-	markerline.la       \
 	notify.la           \
 	pidginrc.la         \
 	relnot.la           \
 	sendbutton.la       \
 	spellchk.la         \
-	themeedit.la         \
-	timestamp.la        \
-	timestamp_format.la \
+	themeedit.la        \
+	webkit.la           \
 	xmppconsole.la
 
 if USE_VV
@@ -84,16 +80,13 @@
 gtkbuddynote_la_SOURCES     = gtkbuddynote.c
 history_la_SOURCES          = history.c
 iconaway_la_SOURCES         = iconaway.c
-markerline_la_SOURCES       = markerline.c
 notify_la_SOURCES           = notify.c
 pidginrc_la_SOURCES         = pidginrc.c
 relnot_la_SOURCES           = relnot.c
 sendbutton_la_SOURCES       = sendbutton.c
 spellchk_la_SOURCES         = spellchk.c
 themeedit_la_SOURCES        = themeedit.c themeedit-icon.c themeedit-icon.h
-timestamp_la_SOURCES        = timestamp.c
-timestamp_format_la_SOURCES = timestamp_format.c
-vvconfig_la_SOURCES         = vvconfig.c
+webkit_la_SOURCES           = webkit.c
 xmppconsole_la_SOURCES      = xmppconsole.c
 
 convcolors_la_LIBADD        = $(GTK_LIBS)
@@ -103,16 +96,13 @@
 gtkbuddynote_la_LIBADD      = $(GTK_LIBS)
 history_la_LIBADD           = $(GTK_LIBS)
 iconaway_la_LIBADD          = $(GTK_LIBS)
-markerline_la_LIBADD        = $(GTK_LIBS)
 notify_la_LIBADD            = $(GTK_LIBS)
 pidginrc_la_LIBADD          = $(GTK_LIBS)
 relnot_la_LIBADD            = $(GLIB_LIBS)
 sendbutton_la_LIBADD        = $(GTK_LIBS)
 spellchk_la_LIBADD          = $(GTK_LIBS)
 themeedit_la_LIBADD         = $(GTK_LIBS)
-timestamp_la_LIBADD         = $(GTK_LIBS)
-timestamp_format_la_LIBADD  = $(GTK_LIBS)
-vvconfig_la_LIBADD          = $(GTK_LIBS) $(GSTREAMER_LIBS)
+webkit_la_LIBADD            = $(GTK_LIBS) $(WEBKIT_LIBS)
 xmppconsole_la_LIBADD       = $(GTK_LIBS)
 
 endif # PLUGINS
@@ -136,6 +126,7 @@
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
+	$(WEBKIT_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
 	$(PLUGIN_CFLAGS)
 
--- a/pidgin/plugins/gestures/gestures.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/gestures/gestures.c	Mon Oct 31 01:25:36 2011 +0000
@@ -48,7 +48,7 @@
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
-	gstroke_cleanup(gtkconv->imhtml);
+	gstroke_cleanup(gtkconv->webview);
 	purple_conversation_destroy(conv);
 }
 
@@ -126,15 +126,15 @@
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
-	gstroke_enable(gtkconv->imhtml);
-	gstroke_signal_connect(gtkconv->imhtml, "14789",  stroke_close,    conv);
-	gstroke_signal_connect(gtkconv->imhtml, "1456",   stroke_close,    conv);
-	gstroke_signal_connect(gtkconv->imhtml, "1489",   stroke_close,    conv);
-	gstroke_signal_connect(gtkconv->imhtml, "74123",  stroke_next_tab, conv);
-	gstroke_signal_connect(gtkconv->imhtml, "7456",   stroke_next_tab, conv);
-	gstroke_signal_connect(gtkconv->imhtml, "96321",  stroke_prev_tab, conv);
-	gstroke_signal_connect(gtkconv->imhtml, "9654",   stroke_prev_tab, conv);
-	gstroke_signal_connect(gtkconv->imhtml, "25852",  stroke_new_win,  conv);
+	gstroke_enable(gtkconv->webview);
+	gstroke_signal_connect(gtkconv->webview, "14789",  stroke_close,    conv);
+	gstroke_signal_connect(gtkconv->webview, "1456",   stroke_close,    conv);
+	gstroke_signal_connect(gtkconv->webview, "1489",   stroke_close,    conv);
+	gstroke_signal_connect(gtkconv->webview, "74123",  stroke_next_tab, conv);
+	gstroke_signal_connect(gtkconv->webview, "7456",   stroke_next_tab, conv);
+	gstroke_signal_connect(gtkconv->webview, "96321",  stroke_prev_tab, conv);
+	gstroke_signal_connect(gtkconv->webview, "9654",   stroke_prev_tab, conv);
+	gstroke_signal_connect(gtkconv->webview, "25852",  stroke_new_win,  conv);
 }
 
 static void
@@ -215,8 +215,8 @@
 
 		gtkconv = PIDGIN_CONVERSATION(conv);
 
-		gstroke_cleanup(gtkconv->imhtml);
-		gstroke_disable(gtkconv->imhtml);
+		gstroke_cleanup(gtkconv->webview);
+		gstroke_disable(gtkconv->webview);
 	}
 
 	return TRUE;
--- a/pidgin/plugins/gevolution/gevo-util.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/gevolution/gevo-util.c	Mon Oct 31 01:25:36 2011 +0000
@@ -49,7 +49,7 @@
 		purple_blist_add_buddy(buddy, NULL, group, NULL);
 	}
 
-	purple_account_add_buddy(account, buddy);
+	purple_account_add_buddy(account, buddy, NULL);
 
 	if (conv != NULL)
 	{
--- a/pidgin/plugins/history.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/history.c	Mon Oct 31 01:25:36 2011 +0000
@@ -16,16 +16,17 @@
 #include "gtkconv.h"
 #include "gtkimhtml.h"
 #include "gtkplugin.h"
+#include "gtkwebview.h"
 
 #define HISTORY_PLUGIN_ID "gtk-history"
 
 #define HISTORY_SIZE (4 * 1024)
 
-static gboolean _scroll_imhtml_to_end(gpointer data)
+static gboolean _scroll_webview_to_end(gpointer data)
 {
-	GtkIMHtml *imhtml = data;
-	gtk_imhtml_scroll_to_end(GTK_IMHTML(imhtml), FALSE);
-	g_object_unref(G_OBJECT(imhtml));
+	GtkWebView *webview = data;
+	gtk_webview_scroll_to_end(GTK_WEBVIEW(webview), FALSE);
+	g_object_unref(G_OBJECT(webview));
 	return FALSE;
 }
 
@@ -39,9 +40,15 @@
 	guint flags;
 	char *history;
 	PidginConversation *gtkconv;
+#if 0
+	/* FIXME: WebView has no options */
 	GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS;
+#endif
 	char *header;
+#if 0
+	/* FIXME: WebView has no protocol setting */
 	char *protocol;
+#endif
 	char *escaped_alias;
 	const char *header_date;
 
@@ -116,15 +123,21 @@
 
 	history = purple_log_read((PurpleLog*)logs->data, &flags);
 	gtkconv = PIDGIN_CONVERSATION(c);
+#if 0
+	/* FIXME: WebView has no options */
 	if (flags & PURPLE_LOG_READ_NO_NEWLINE)
 		options |= GTK_IMHTML_NO_NEWLINE;
+#endif
 
+#if 0
+	/* FIXME: WebView has no protocol setting */
 	protocol = g_strdup(gtk_imhtml_get_protocol_name(GTK_IMHTML(gtkconv->imhtml)));
 	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml),
 			purple_account_get_protocol_name(((PurpleLog*)logs->data)->account));
+#endif
 
-	if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml))))
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", options);
+	if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview)))
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR>");
 
 	escaped_alias = g_markup_escape_text(alias, -1);
 
@@ -134,21 +147,24 @@
 		header_date = purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time));
 
 	header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), escaped_alias, header_date);
-	gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), header, options);
+	gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), header);
 	g_free(header);
 	g_free(escaped_alias);
 
 	g_strchomp(history);
-	gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), history, options);
+	gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), history);
 	g_free(history);
 
-	gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<hr>", options);
+	gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<hr>");
 
+#if 0
+	/* FIXME: WebView has no protocol setting */
 	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol);
 	g_free(protocol);
+#endif
 
-	g_object_ref(G_OBJECT(gtkconv->imhtml));
-	g_idle_add(_scroll_imhtml_to_end, gtkconv->imhtml);
+	g_object_ref(G_OBJECT(gtkconv->webview));
+	g_idle_add(_scroll_webview_to_end, gtkconv->webview);
 
 	g_list_foreach(logs, (GFunc)purple_log_free, NULL);
 	g_list_free(logs);
--- a/pidgin/plugins/musicmessaging/musicmessaging.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/musicmessaging/musicmessaging.c	Mon Oct 31 01:25:36 2011 +0000
@@ -104,7 +104,7 @@
 	{
 		if (mmconv->originator)
 		{
-			char *name = (mmconv->conv)->name;
+			const char *name = purple_conversation_get_name(mmconv->conv);
 			send_change_request (session, name, command, parameters);
 		} else
 		{
@@ -376,7 +376,7 @@
 				if (mmconv->originator)
 				{
 					int session = mmconv_from_conv_loc(conv);
-					char *id = (mmconv->conv)->name;
+					const char *id = purple_conversation_get_name(mmconv->conv);
 					char *command;
 					char *parameters;
 
@@ -424,7 +424,8 @@
 				command = strtok(NULL, " ");
 				/* char *parameters = strtok(NULL, "#"); DONT NEED PARAMETERS */
 
-				if ((mmconv->conv)->name == id)
+				// TODO: Shouldn't this be strcmp() ?
+				if (purple_conversation_get_name(mmconv->conv) == id)
 				{
 					purple_notify_message(plugin_pointer, PURPLE_NOTIFY_MSG_ERROR,
 							    _("Music Messaging"),
@@ -465,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/notify.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/notify.c	Mon Oct 31 01:25:36 2011 +0000
@@ -303,7 +303,7 @@
 attach_signals(PurpleConversation *conv)
 {
 	PidginConversation *gtkconv = NULL;
-	GSList *imhtml_ids = NULL, *entry_ids = NULL;
+	GSList *webview_ids = NULL, *entry_ids = NULL;
 	guint id;
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
@@ -322,9 +322,9 @@
 		                      G_CALLBACK(unnotify_cb), conv);
 		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
 
-		id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "focus-in-event",
+		id = g_signal_connect(G_OBJECT(gtkconv->webview), "focus-in-event",
 		                      G_CALLBACK(unnotify_cb), conv);
-		imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id));
+		webview_ids = g_slist_append(webview_ids, GUINT_TO_POINTER(id));
 	}
 
 	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_click")) {
@@ -334,9 +334,9 @@
 		                      G_CALLBACK(unnotify_cb), conv);
 		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
 
-		id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "button-press-event",
+		id = g_signal_connect(G_OBJECT(gtkconv->webview), "button-press-event",
 		                      G_CALLBACK(unnotify_cb), conv);
-		imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id));
+		webview_ids = g_slist_append(webview_ids, GUINT_TO_POINTER(id));
 	}
 
 	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_type")) {
@@ -345,7 +345,7 @@
 		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
 	}
 
-	purple_conversation_set_data(conv, "notify-imhtml-signals", imhtml_ids);
+	purple_conversation_set_data(conv, "notify-webview-signals", webview_ids);
 	purple_conversation_set_data(conv, "notify-entry-signals", entry_ids);
 
 	return 0;
@@ -361,9 +361,9 @@
 	if (!gtkconv)
 		return;
 
-	ids = purple_conversation_get_data(conv, "notify-imhtml-signals");
+	ids = purple_conversation_get_data(conv, "notify-webview-signals");
 	for (l = ids; l != NULL; l = l->next)
-		g_signal_handler_disconnect(gtkconv->imhtml, GPOINTER_TO_INT(l->data));
+		g_signal_handler_disconnect(gtkconv->webview, GPOINTER_TO_INT(l->data));
 	g_slist_free(ids);
 
 	ids = purple_conversation_get_data(conv, "notify-entry-signals");
@@ -373,7 +373,7 @@
 
 	purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
 
-	purple_conversation_set_data(conv, "notify-imhtml-signals", NULL);
+	purple_conversation_set_data(conv, "notify-webview-signals", NULL);
 	purple_conversation_set_data(conv, "notify-entry-signals", NULL);
 }
 
--- a/pidgin/plugins/perl/common/GtkBlist.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/perl/common/GtkBlist.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -69,8 +69,3 @@
 
 void
 pidgin_blist_joinchat_show()
-
-void
-pidgin_blist_update_account_error_state(account, message)
-	Purple::Account account
-	const char * message
--- a/pidgin/plugins/perl/common/GtkDialogs.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/perl/common/GtkDialogs.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -24,10 +24,6 @@
 pidgin_dialogs_log()
 
 void
-pidgin_dialogs_alias_contact(contact)
-	Purple::BuddyList::Contact contact
-
-void
 pidgin_dialogs_alias_buddy(buddy)
 	Purple::BuddyList::Buddy buddy
 
--- a/pidgin/plugins/perl/common/GtkIMHtml.xs	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/perl/common/GtkIMHtml.xs	Mon Oct 31 01:25:36 2011 +0000
@@ -77,26 +77,6 @@
 	Gtk::TextIter end
 */
 
-/* This can't work at the moment since I don't have a typemap for Gdk::Pixbuf.
- * I thought about using the one from libgtk2-perl but wasn't sure how to go
- * about doing that.
-Pidgin::IMHtml::Scalable
-gtk_imhtml_image_new(img, filename, id)
-	Gdk::Pixbuf img
-	const gchar * filename
-	int id
-*/
-
-/* This can't work at the moment since I don't have a typemap for Gtk::Widget.
- * I thought about using the one from libgtk2-perl but wasn't sure how to go
- * about doing that.
-void
-gtk_imhtml_image_add_to(scale, imhtml, iter)
-	Pidgin::IMHtml::Scalable scale
-	Pidgin::IMHtml imhtml
-	Gtk::TextIter iter
-*/
-
 /* This can't work at the moment since I don't have a typemap for Gtk::Widget.
  * I thought about using the one from libgtk2-perl but wasn't sure how to go
  * about doing that.
@@ -323,19 +303,6 @@
 	}
 	XPUSHs(sv_2mortal(newRV_noinc((SV *)lines)));
 
-MODULE = Pidgin::IMHtml  PACKAGE = Pidgin::IMHtml::Scalable  PREFIX = gtk_imhtml_image_
-PROTOTYPES: ENABLE
-
-void
-gtk_imhtml_image_free(scale)
-	Pidgin::IMHtml::Scalable scale
-
-void
-gtk_imhtml_image_scale(scale, width, height)
-	Pidgin::IMHtml::Scalable scale
-	int width
-	int height
-
 MODULE = Pidgin::IMHtml  PACKAGE = Pidgin::IMHtml::Hr  PREFIX = gtk_imhtml_hr_
 PROTOTYPES: ENABLE
 
--- a/pidgin/plugins/relnot.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/relnot.c	Mon Oct 31 01:25:36 2011 +0000
@@ -152,7 +152,7 @@
 				url,
 				host);
 
-		purple_util_fetch_url_request_len(url, TRUE, NULL, FALSE,
+		purple_util_fetch_url_request(NULL, url, TRUE, NULL, FALSE,
 			request, TRUE, -1, version_fetch_cb, NULL);
 
 		g_free(request);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/webkit.c	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,201 @@
+/*
+ * WebKit - Open the inspector on any WebKit views.
+ * Copyright (C) 2011 Elliott Sales de Andrade <qulogic@pidgin.im>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "internal.h"
+
+#include "version.h"
+
+#include "pidgin.h"
+
+#include "gtkconv.h"
+#include "gtkplugin.h"
+#include "gtkwebview.h"
+
+static WebKitWebView *
+create_gtk_window_around_it(WebKitWebInspector *inspector,
+                            WebKitWebView      *webview,
+                            PidginConversation *gtkconv)
+{
+	GtkWidget *win;
+	GtkWidget *view;
+	char *title;
+
+	win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	title = g_strdup_printf(_("%s - Inspector"),
+	                        gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)));
+	gtk_window_set_title(GTK_WINDOW(win), title);
+	g_free(title);
+	gtk_window_set_default_size(GTK_WINDOW(win), 600, 400);
+	g_signal_connect_swapped(G_OBJECT(gtkconv->tab_cont), "destroy", G_CALLBACK(gtk_widget_destroy), win);
+
+	view = webkit_web_view_new();
+	gtk_container_add(GTK_CONTAINER(win), view);
+	g_object_set_data(G_OBJECT(webview), "inspector-window", win);
+
+	return WEBKIT_WEB_VIEW(view);
+}
+
+static gboolean
+show_inspector_window(WebKitWebInspector *inspector,
+                      GtkWidget          *webview)
+{
+	GtkWidget *win;
+
+	win = g_object_get_data(G_OBJECT(webview), "inspector-window");
+
+	gtk_widget_show_all(win);
+
+	return TRUE;
+}
+
+static void
+setup_inspector(PidginConversation *gtkconv)
+{
+	GtkWidget *webview = gtkconv->webview;
+	WebKitWebSettings *settings;
+	WebKitWebInspector *inspector;
+
+	settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview));
+	inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(webview));
+
+	g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL);
+
+	g_signal_connect(G_OBJECT(inspector), "inspect-web-view",
+	                 G_CALLBACK(create_gtk_window_around_it), gtkconv);
+	g_signal_connect(G_OBJECT(inspector), "show-window",
+	                 G_CALLBACK(show_inspector_window), webview);
+}
+
+static void
+remove_inspector(PidginConversation *gtkconv)
+{
+	GtkWidget *webview = gtkconv->webview;
+	GtkWidget *win;
+	WebKitWebSettings *settings;
+
+	win = g_object_get_data(G_OBJECT(webview), "inspector-window");
+	gtk_widget_destroy(win);
+	g_object_set_data(G_OBJECT(webview), "inspector-window", NULL);
+
+	settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview));
+
+	g_object_set(G_OBJECT(settings), "enable-developer-extras", FALSE, NULL);
+}
+
+static void
+conversation_displayed_cb(PidginConversation *gtkconv)
+{
+	GtkWidget *inspect = NULL;
+
+	inspect = g_object_get_data(G_OBJECT(gtkconv->webview),
+	                            "inspector-window");
+	if (inspect == NULL) {
+		setup_inspector(gtkconv);
+	}
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin)
+{
+	GList *convs = purple_get_conversations();
+	void *gtk_conv_handle = pidgin_conversations_get_handle();
+
+	purple_signal_connect(gtk_conv_handle, "conversation-displayed", plugin,
+	                      PURPLE_CALLBACK(conversation_displayed_cb), NULL);
+
+	while (convs) {
+		PurpleConversation *conv = (PurpleConversation *)convs->data;
+
+		/* Setup WebKit Inspector */
+		if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) {
+			setup_inspector(PIDGIN_CONVERSATION(conv));
+		}
+
+		convs = convs->next;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin)
+{
+	GList *convs = purple_get_conversations();
+
+	while (convs) {
+		PurpleConversation *conv = (PurpleConversation *)convs->data;
+
+		/* Remove WebKit Inspector */
+		if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) {
+			remove_inspector(PIDGIN_CONVERSATION(conv));
+		}
+
+		convs = convs->next;
+	}
+
+	return TRUE;
+}
+
+static PurplePluginInfo info =
+{
+	PURPLE_PLUGIN_MAGIC,
+	PURPLE_MAJOR_VERSION,                           /**< major version */
+	PURPLE_MINOR_VERSION,                           /**< minor version */
+	PURPLE_PLUGIN_STANDARD,                         /**< type */
+	PIDGIN_PLUGIN_TYPE,                             /**< ui_requirement */
+	0,                                              /**< flags */
+	NULL,                                           /**< dependencies */
+	PURPLE_PRIORITY_DEFAULT,                        /**< priority */
+
+	"gtkwebkit-inspect",                            /**< id */
+	N_("WebKit Development"),                       /**< name */
+	DISPLAY_VERSION,                                /**< version */
+	N_("Enables WebKit Inspector."),                /**< summary */
+	N_("Enables WebKit's built-in inspector in a "
+	   "conversation window. This may be viewed "
+	   "by right-clicking a WebKit widget and "
+	   "selecting 'Inspect Element'."),             /**< description */
+	"Elliott Sales de Andrade <qulogic@pidgin.im>", /**< author */
+	PURPLE_WEBSITE,                                 /**< homepage */
+	plugin_load,                                    /**< load */
+	plugin_unload,                                  /**< unload */
+	NULL,                                           /**< destroy */
+	NULL,                                           /**< ui_info */
+	NULL,                                           /**< extra_info */
+	NULL,                                           /**< prefs_info */
+	NULL,                                           /**< actions */
+
+	/* padding */
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+init_plugin(PurplePlugin *plugin)
+{
+}
+
+PURPLE_INIT_PLUGIN(webkit-devel, init_plugin, info)
+
--- a/pidgin/plugins/xmppconsole.c	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/plugins/xmppconsole.c	Mon Oct 31 01:25:36 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);
@@ -643,7 +643,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++;
 
@@ -733,10 +733,10 @@
 
 	account = purple_accounts_find(gtk_combo_box_get_active_text(GTK_COMBO_BOX(console->dropdown)),
 				    "prpl-jabber");
-	if (!account || !account->gc)
+	if (!account || !purple_account_get_connection(account))
 		return;
 
-	console->gc = account->gc;
+	console->gc = purple_account_get_connection(account);
 	gtk_imhtml_clear(GTK_IMHTML(console->imhtml));
 }
 
@@ -793,14 +793,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/smileyparser.c	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,169 @@
+/* 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 <gtk/gtk.h>
+#include <debug.h>
+#include "smileyparser.h"
+#include <smiley.h>
+#include <string.h>
+#include "gtkthemes.h"
+
+static char *
+get_fullpath(const char *filename)
+{
+	if (g_path_is_absolute(filename))
+		return g_strdup(filename);
+	else
+		return g_build_path(g_get_current_dir(), filename, NULL);
+}
+
+static void
+parse_for_shortcut_plaintext(const char *text, const char *shortcut, const char *file, GString *ret)
+{
+	const char *tmp = text;
+
+	for (;*tmp;) {
+		const char *end = strstr(tmp, shortcut);
+		char *path;
+		char *escaped_path;
+
+		if (end == NULL) {
+			g_string_append(ret, tmp);
+			break;
+		}
+		path = get_fullpath(file);
+		escaped_path = g_markup_escape_text(path, -1);
+
+		g_string_append_len(ret, tmp, end-tmp);
+		g_string_append_printf(ret,"<img alt='%s' src='%s' />",
+					shortcut, escaped_path);
+		g_free(path);
+		g_free(escaped_path);
+		g_assert(strlen(tmp) >= strlen(shortcut));
+		tmp = end + strlen(shortcut);
+	}
+}
+
+static char *
+parse_for_shortcut(const char *markup, const char *shortcut, const char *file)
+{
+	GString* ret = g_string_new("");
+	char *local_markup = g_strdup(markup);
+	char *escaped_shortcut = g_markup_escape_text(shortcut, -1);
+
+	char *temp = local_markup;
+
+	for (;*temp;) {
+		char *end = strchr(temp, '<');
+		char *end_of_tag;
+
+		if (!end) {
+			parse_for_shortcut_plaintext(temp, escaped_shortcut, file, ret);
+			break;
+		}
+
+		*end = 0;
+		parse_for_shortcut_plaintext(temp, escaped_shortcut, file, ret);
+		*end = '<';
+
+		/* if this is well-formed, then there should be no '>' within
+		 * the tag. TODO: handle a comment tag better :( */
+		end_of_tag = strchr(end, '>');
+		if (!end_of_tag) {
+			g_string_append(ret, end);
+			break;
+		}
+
+		g_string_append_len(ret, end, end_of_tag - end + 1);
+
+		temp = end_of_tag + 1;
+	}
+	g_free(local_markup);
+	g_free(escaped_shortcut);
+	return g_string_free(ret, FALSE);
+}
+
+static char *
+parse_for_purple_smiley(const char *markup, PurpleSmiley *smiley)
+{
+	char *file = purple_smiley_get_full_path(smiley);
+	char *ret = parse_for_shortcut(markup, purple_smiley_get_shortcut(smiley), file);
+	g_free(file);
+	return ret;
+}
+
+static char *
+parse_for_smiley_list(const char *markup, GHashTable *smileys)
+{
+	GHashTableIter iter;
+	char *key, *value;
+	char *ret = g_strdup(markup);
+
+	g_hash_table_iter_init(&iter, smileys);
+	while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
+	{
+		char *temp = parse_for_shortcut(ret, key, value);
+		g_free(ret);
+		ret = temp;
+	}
+
+	return ret;
+}
+
+char *
+smiley_parse_markup(const char *markup, const char *proto_id)
+{
+	GList *smileys = purple_smileys_get_all();
+	char *temp = g_strdup(markup), *temp2;
+	struct smiley_list *list;
+	const char *proto_name = "default";
+
+	if (proto_id != NULL) {
+		PurplePlugin *proto;
+		proto = purple_find_prpl(proto_id);
+		proto_name = proto->info->name;
+	}
+
+	/* unnecessarily slow, but lets manage for now. */
+	for (; smileys; smileys = g_list_next(smileys)) {
+		temp2 = parse_for_purple_smiley(temp, PURPLE_SMILEY(smileys->data));
+		g_free(temp);
+		temp = temp2;
+	}
+
+	/* now for each theme smiley, observe that this does look nasty */
+	if (!current_smiley_theme || !(current_smiley_theme->list)) {
+		purple_debug_warning("smiley", "theme does not exist\n");
+		return temp;
+	}
+
+	for (list = current_smiley_theme->list; list; list = list->next) {
+		if (g_str_equal(list->sml, proto_name)) {
+			temp2 = parse_for_smiley_list(temp, list->files);
+			g_free(temp);
+			temp = temp2;
+		}
+	}
+
+	return temp;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/smileyparser.h	Mon Oct 31 01:25:36 2011 +0000
@@ -0,0 +1,25 @@
+/* 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
+ *
+ */
+
+char *
+smiley_parse_markup(const char *markup, const char *sml);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/themes/Makefile.am	Mon Oct 31 01:25:36 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	Mon Oct 31 01:25:36 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/pidgin/win32/untar.h	Mon Oct 31 01:22:26 2011 +0000
+++ b/pidgin/win32/untar.h	Mon Oct 31 01:25:36 2011 +0000
@@ -12,7 +12,7 @@
 extern "C" {
 #endif /* __cplusplus */
 
-typedef enum _untar_opt {
+typedef enum {
 	UNTAR_LISTING =      (1 << 0),
 	UNTAR_QUIET =        (1 << 1),
 	UNTAR_VERBOSE =      (1 << 2),
--- a/po/POTFILES.in	Mon Oct 31 01:22:26 2011 +0000
+++ b/po/POTFILES.in	Mon Oct 31 01:25:36 2011 +0000
@@ -160,14 +160,6 @@
 libpurple/protocols/silc/silc.c
 libpurple/protocols/silc/util.c
 libpurple/protocols/silc/wb.c
-libpurple/protocols/silc10/buddy.c
-libpurple/protocols/silc10/chat.c
-libpurple/protocols/silc10/ft.c
-libpurple/protocols/silc10/ops.c
-libpurple/protocols/silc10/pk.c
-libpurple/protocols/silc10/silc.c
-libpurple/protocols/silc10/util.c
-libpurple/protocols/silc10/wb.c
 libpurple/protocols/simple/simple.c
 libpurple/protocols/yahoo/libyahoo.c
 libpurple/protocols/yahoo/libyahoojp.c
--- a/po/de.po	Mon Oct 31 01:22:26 2011 +0000
+++ b/po/de.po	Mon Oct 31 01:25:36 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-10-22 12:37+0200\n"
+"PO-Revision-Date: 2011-10-22 12:37+0200\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"
 
@@ -6307,16 +6369,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 +6460,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 +6730,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 +6953,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 +6979,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 +7104,10 @@
 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);
-#. }
-#.
+#, fuzzy
+msgid "DN"
+msgstr "DN"
+
 msgid "Full name"
 msgstr "Vollständiger Name"
 
@@ -8147,6 +8210,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 +8231,7 @@
 msgid "Position"
 msgstr "Position"
 
+#. TODO: Is it correct to pass info->email here...?
 msgid "Web Page"
 msgstr "Webseite"
 
@@ -8433,33 +8498,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 +8830,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 +9726,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 +10212,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 +10422,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 +11387,21 @@
 msgid "SSL Servers"
 msgstr "SSL-Server"
 
+msgid "Unsafe debugging is now disabled."
+msgstr ""
+
+msgid "Unsafe debugging is now enabled."
+msgstr ""
+
+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 +11436,6 @@
 msgid "Ignore"
 msgstr "Ignorieren"
 
-msgid "Get Away Message"
-msgstr "Neue Abwesenheitsnachricht abholen"
-
 msgid "Last Said"
 msgstr "Zuletzt gesagt"
 
@@ -12178,12 +12183,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."
@@ -13004,6 +13003,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 +13033,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:"