cpw.qulogic.gtk3: aa17fd91: A boring and large patch so I can merge ...

qulogic at pidgin.im qulogic at pidgin.im
Fri Dec 23 05:27:15 EST 2011


----------------------------------------------------------------------
Revision: aa17fd919c5b0e1d9405ceccffb4b2e83487d6aa
Parent:   87e04c3156d9966447eb61ea372fa7472a031c93
Author:   qulogic at pidgin.im
Date:     12/23/11 03:21:58
Branch:   im.pidgin.cpw.qulogic.gtk3
URL: http://d.pidgin.im/viewmtn/revision/info/aa17fd919c5b0e1d9405ceccffb4b2e83487d6aa

Changelog: 

A boring and large patch so I can merge heads.

Changes against parent 87e04c3156d9966447eb61ea372fa7472a031c93

  dropped  pidgin/gtkdocklet-gtk.c
  patched  COPYRIGHT
  patched  ChangeLog
  patched  ChangeLog.API
  patched  configure.ac
  patched  doc/account-signals.dox
  patched  doc/blist-signals.dox
  patched  doc/connection-signals.dox
  patched  doc/conversation-signals.dox
  patched  doc/gtkconv-signals.dox
  patched  doc/notify-signals.dox
  patched  finch/gntaccount.h
  patched  finch/gntblist.c
  patched  finch/gntblist.h
  patched  finch/gntconv.c
  patched  finch/gntconv.h
  patched  finch/gntft.c
  patched  finch/gntnotify.c
  patched  finch/gntrequest.c
  patched  finch/gntrequest.h
  patched  finch/gntroomlist.c
  patched  finch/gntsound.c
  patched  finch/gntsound.h
  patched  finch/libgnt/gntwm.c
  patched  finch/plugins/gntgf.c
  patched  finch/plugins/gnttinyurl.c
  patched  finch/plugins/grouping.c
  patched  finch/plugins/lastlog.c
  patched  libpurple/account.c
  patched  libpurple/account.h
  patched  libpurple/accountopt.c
  patched  libpurple/accountopt.h
  patched  libpurple/blist.c
  patched  libpurple/blist.h
  patched  libpurple/buddyicon.c
  patched  libpurple/buddyicon.h
  patched  libpurple/certificate.c
  patched  libpurple/certificate.h
  patched  libpurple/cmds.c
  patched  libpurple/cmds.h
  patched  libpurple/connection.c
  patched  libpurple/connection.h
  patched  libpurple/conversation.c
  patched  libpurple/conversation.h
  patched  libpurple/core.h
  patched  libpurple/dbus-analyze-functions.py
  patched  libpurple/dbus-bindings.h
  patched  libpurple/dbus-server.c
  patched  libpurple/dbus-server.h
  patched  libpurple/dbus-useful.c
  patched  libpurple/debug.c
  patched  libpurple/debug.h
  patched  libpurple/dnsquery.c
  patched  libpurple/dnsquery.h
  patched  libpurple/dnssrv.c
  patched  libpurple/dnssrv.h
  patched  libpurple/eventloop.h
  patched  libpurple/example/nullclient.c
  patched  libpurple/ft.c
  patched  libpurple/ft.h
  patched  libpurple/imgstore.h
  patched  libpurple/log.c
  patched  libpurple/log.h
  patched  libpurple/media/backend-fs2.h
  patched  libpurple/media/backend-iface.h
  patched  libpurple/media/candidate.h
  patched  libpurple/media/codec.h
  patched  libpurple/media/enum-types.h
  patched  libpurple/media-gst.h
  patched  libpurple/media.h
  patched  libpurple/mediamanager.h
  patched  libpurple/network.c
  patched  libpurple/network.h
  patched  libpurple/notify.c
  patched  libpurple/notify.h
  patched  libpurple/plugin.c
  patched  libpurple/plugin.h
  patched  libpurple/plugins/autoaccept.c
  patched  libpurple/plugins/log_reader.c
  patched  libpurple/plugins/perl/common/Account.xs
  patched  libpurple/plugins/perl/common/BuddyList.xs
  patched  libpurple/plugins/perl/common/Certificate.xs
  patched  libpurple/plugins/perl/common/Connection.xs
  patched  libpurple/plugins/perl/common/Conversation.xs
  patched  libpurple/plugins/perl/common/FT.xs
  patched  libpurple/plugins/perl/common/Network.xs
  patched  libpurple/plugins/perl/common/Request.xs
  patched  libpurple/plugins/perl/common/SSLConn.xs
  patched  libpurple/plugins/perl/common/Status.xs
  patched  libpurple/plugins/perl/common/Util.xs
  patched  libpurple/plugins/ssl/Makefile.am
  patched  libpurple/plugins/ssl/ssl-gnutls.c
  patched  libpurple/plugins/ssl/ssl-nss.c
  patched  libpurple/plugins/statenotify.c
  patched  libpurple/pounce.c
  patched  libpurple/pounce.h
  patched  libpurple/prefs.c
  patched  libpurple/prefs.h
  patched  libpurple/privacy.c
  patched  libpurple/protocols/Makefile.am
  patched  libpurple/protocols/bonjour/bonjour.c
  patched  libpurple/protocols/bonjour/bonjour_ft.c
  patched  libpurple/protocols/bonjour/jabber.c
  patched  libpurple/protocols/bonjour/jabber.h
  patched  libpurple/protocols/bonjour/mdns_avahi.c
  patched  libpurple/protocols/bonjour/mdns_common.c
  patched  libpurple/protocols/bonjour/mdns_win32.c
  patched  libpurple/protocols/gg/Makefile.am
  patched  libpurple/protocols/gg/Makefile.mingw
  patched  libpurple/protocols/gg/buddylist.c
  patched  libpurple/protocols/gg/confer.c
  patched  libpurple/protocols/gg/gg-utils.c
  patched  libpurple/protocols/gg/gg-utils.h
  patched  libpurple/protocols/gg/gg.c
  patched  libpurple/protocols/gg/gg.h
  patched  libpurple/protocols/gg/lib/common.c
  patched  libpurple/protocols/gg/lib/compat.h
  patched  libpurple/protocols/gg/lib/dcc.c
  patched  libpurple/protocols/gg/lib/dcc7.c
  patched  libpurple/protocols/gg/lib/events.c
  patched  libpurple/protocols/gg/lib/handlers.c
  patched  libpurple/protocols/gg/lib/http.c
  patched  libpurple/protocols/gg/lib/libgadu-config.h
  patched  libpurple/protocols/gg/lib/libgadu.c
  patched  libpurple/protocols/gg/lib/libgadu.h
  patched  libpurple/protocols/gg/lib/pubdir.c
  patched  libpurple/protocols/gg/lib/pubdir50.c
  patched  libpurple/protocols/gg/lib/resolver.c
  patched  libpurple/protocols/gg/lib/resolver.h
  patched  libpurple/protocols/gg/search.c
  patched  libpurple/protocols/irc/cmds.c
  patched  libpurple/protocols/irc/dcc_send.c
  patched  libpurple/protocols/irc/irc.c
  patched  libpurple/protocols/irc/irc.h
  patched  libpurple/protocols/irc/msgs.c
  patched  libpurple/protocols/irc/parse.c
  patched  libpurple/protocols/jabber/adhoccommands.c
  patched  libpurple/protocols/jabber/buddy.c
  patched  libpurple/protocols/jabber/caps.c
  patched  libpurple/protocols/jabber/chat.c
  patched  libpurple/protocols/jabber/disco.c
  patched  libpurple/protocols/jabber/google/gmail.c
  patched  libpurple/protocols/jabber/google/google_presence.c
  patched  libpurple/protocols/jabber/google/jingleinfo.c
  patched  libpurple/protocols/jabber/google/relay.c
  patched  libpurple/protocols/jabber/jabber.c
  patched  libpurple/protocols/jabber/jabber.h
  patched  libpurple/protocols/jabber/jingle/content.c
  patched  libpurple/protocols/jabber/jingle/iceudp.c
  patched  libpurple/protocols/jabber/jingle/jingle.c
  patched  libpurple/protocols/jabber/jingle/rawudp.c
  patched  libpurple/protocols/jabber/jingle/rtp.c
  patched  libpurple/protocols/jabber/jingle/session.c
  patched  libpurple/protocols/jabber/jingle/transport.c
  patched  libpurple/protocols/jabber/jutil.c
  patched  libpurple/protocols/jabber/libxmpp.c
  patched  libpurple/protocols/jabber/message.c
  patched  libpurple/protocols/jabber/oob.c
  patched  libpurple/protocols/jabber/presence.c
  patched  libpurple/protocols/jabber/presence.h
  patched  libpurple/protocols/jabber/roster.c
  patched  libpurple/protocols/jabber/roster.h
  patched  libpurple/protocols/jabber/si.c
  patched  libpurple/protocols/jabber/useravatar.c
  patched  libpurple/protocols/jabber/usermood.c
  patched  libpurple/protocols/jabber/usertune.c
  patched  libpurple/protocols/msn/contact.c
  patched  libpurple/protocols/msn/error.c
  patched  libpurple/protocols/msn/httpconn.c
  patched  libpurple/protocols/msn/msg.c
  patched  libpurple/protocols/msn/msn.c
  patched  libpurple/protocols/msn/nexus.c
  patched  libpurple/protocols/msn/notification.c
  patched  libpurple/protocols/msn/object.c
  patched  libpurple/protocols/msn/object.h
  patched  libpurple/protocols/msn/oim.c
  patched  libpurple/protocols/msn/sbconn.c
  patched  libpurple/protocols/msn/servconn.c
  patched  libpurple/protocols/msn/session.c
  patched  libpurple/protocols/msn/slp.c
  patched  libpurple/protocols/msn/slpcall.c
  patched  libpurple/protocols/msn/slplink.c
  patched  libpurple/protocols/msn/slpmsg.c
  patched  libpurple/protocols/msn/slpmsg.h
  patched  libpurple/protocols/msn/switchboard.c
  patched  libpurple/protocols/msn/user.c
  patched  libpurple/protocols/msn/userlist.c
  patched  libpurple/protocols/msn/xfer.c
  patched  libpurple/protocols/msn/xfer.h
  patched  libpurple/protocols/mxit/actions.c
  patched  libpurple/protocols/mxit/cipher.c
  patched  libpurple/protocols/mxit/filexfer.c
  patched  libpurple/protocols/mxit/formcmds.c
  patched  libpurple/protocols/mxit/login.c
  patched  libpurple/protocols/mxit/markup.c
  patched  libpurple/protocols/mxit/multimx.c
  patched  libpurple/protocols/mxit/mxit.c
  patched  libpurple/protocols/mxit/mxit.h
  patched  libpurple/protocols/mxit/profile.c
  patched  libpurple/protocols/mxit/protocol.c
  patched  libpurple/protocols/mxit/protocol.h
  patched  libpurple/protocols/mxit/roster.c
  patched  libpurple/protocols/mxit/splashscreen.c
  patched  libpurple/protocols/mxit/voicevideo.c
  patched  libpurple/protocols/myspace/myspace.c
  patched  libpurple/protocols/myspace/session.h
  patched  libpurple/protocols/myspace/user.c
  patched  libpurple/protocols/myspace/zap.c
  patched  libpurple/protocols/novell/novell.c
  patched  libpurple/protocols/null/nullprpl.c
  patched  libpurple/protocols/oscar/clientlogin.c
  patched  libpurple/protocols/oscar/family_feedbag.c
  patched  libpurple/protocols/oscar/family_icbm.c
  patched  libpurple/protocols/oscar/flap_connection.c
  patched  libpurple/protocols/oscar/libaim.c
  patched  libpurple/protocols/oscar/libicq.c
  patched  libpurple/protocols/oscar/oft.c
  patched  libpurple/protocols/oscar/oscar.c
  patched  libpurple/protocols/oscar/peer.c
  patched  libpurple/protocols/oscar/userinfo.c
  patched  libpurple/protocols/sametime/sametime.c
  patched  libpurple/protocols/silc/buddy.c
  patched  libpurple/protocols/silc/chat.c
  patched  libpurple/protocols/silc/ft.c
  patched  libpurple/protocols/silc/ops.c
  patched  libpurple/protocols/silc/pk.c
  patched  libpurple/protocols/silc/silc.c
  patched  libpurple/protocols/silc/silcpurple.h
  patched  libpurple/protocols/silc/util.c
  patched  libpurple/protocols/silc/wb.c
  patched  libpurple/protocols/simple/simple.c
  patched  libpurple/protocols/yahoo/libyahoo.c
  patched  libpurple/protocols/yahoo/libyahoojp.c
  patched  libpurple/protocols/yahoo/libymsg.c
  patched  libpurple/protocols/yahoo/libymsg.h
  patched  libpurple/protocols/yahoo/util.c
  patched  libpurple/protocols/yahoo/yahoo_aliases.c
  patched  libpurple/protocols/yahoo/yahoo_doodle.c
  patched  libpurple/protocols/yahoo/yahoo_filexfer.c
  patched  libpurple/protocols/yahoo/yahoo_friend.c
  patched  libpurple/protocols/yahoo/yahoo_picture.c
  patched  libpurple/protocols/yahoo/yahoo_profile.c
  patched  libpurple/protocols/yahoo/yahoochat.c
  patched  libpurple/protocols/yahoo/ycht.c
  patched  libpurple/protocols/zephyr/ZRetSubs.c
  patched  libpurple/protocols/zephyr/zephyr.c
  patched  libpurple/proxy.c
  patched  libpurple/proxy.h
  patched  libpurple/prpl.c
  patched  libpurple/prpl.h
  patched  libpurple/purple-3.pc.in
  patched  libpurple/purple.h.in
  patched  libpurple/request.c
  patched  libpurple/request.h
  patched  libpurple/roomlist.c
  patched  libpurple/roomlist.h
  patched  libpurple/savedstatuses.c
  patched  libpurple/server.c
  patched  libpurple/server.h
  patched  libpurple/smiley.h
  patched  libpurple/sound-theme.c
  patched  libpurple/sound-theme.h
  patched  libpurple/sslconn.c
  patched  libpurple/sslconn.h
  patched  libpurple/status.c
  patched  libpurple/status.h
  patched  libpurple/stun.c
  patched  libpurple/tests/test_xmlnode.c
  patched  libpurple/theme-loader.c
  patched  libpurple/theme-loader.h
  patched  libpurple/theme.c
  patched  libpurple/theme.h
  patched  libpurple/upnp.c
  patched  libpurple/util.c
  patched  libpurple/util.h
  patched  libpurple/value.c
  patched  libpurple/value.h
  patched  libpurple/version.h.in
  patched  libpurple/whiteboard.c
  patched  libpurple/whiteboard.h
  patched  libpurple/win32/libc_interface.c
  patched  libpurple/win32/libc_interface.h
  patched  libpurple/win32/libc_internal.h
  patched  libpurple/xmlnode.c
  patched  libpurple/xmlnode.h
  patched  pidgin/Makefile.am
  patched  pidgin/Makefile.mingw
  patched  pidgin/gtkaccount.c
  patched  pidgin/gtkblist-theme-loader.c
  patched  pidgin/gtkblist-theme.c
  patched  pidgin/gtkblist-theme.h
  patched  pidgin/gtkblist.c
  patched  pidgin/gtkblist.h
  patched  pidgin/gtkcellrendererexpander.c
  patched  pidgin/gtkcertmgr.c
  patched  pidgin/gtkconv.c
  patched  pidgin/gtkconv.h
  patched  pidgin/gtkconvwin.h
  patched  pidgin/gtkdebug.c
  patched  pidgin/gtkdialogs.c
  patched  pidgin/gtkdialogs.h
  patched  pidgin/gtkdnd-hints.c
  patched  pidgin/gtkdocklet.c
  patched  pidgin/gtkdocklet.h
  patched  pidgin/gtkft.c
  patched  pidgin/gtkicon-theme.c
  patched  pidgin/gtkicon-theme.h
  patched  pidgin/gtkidle.c
  patched  pidgin/gtkimhtml.c
  patched  pidgin/gtkimhtml.h
  patched  pidgin/gtkimhtmltoolbar.c
  patched  pidgin/gtkimhtmltoolbar.h
  patched  pidgin/gtklog.c
  patched  pidgin/gtklog.h
  patched  pidgin/gtkmedia.c
  patched  pidgin/gtkmenutray.c
  patched  pidgin/gtkmenutray.h
  patched  pidgin/gtknotify.c
  patched  pidgin/gtkplugin.c
  patched  pidgin/gtkpounce.c
  patched  pidgin/gtkprefs.c
  patched  pidgin/gtkprefs.h
  patched  pidgin/gtkprivacy.c
  patched  pidgin/gtkrequest.c
  patched  pidgin/gtkroomlist.c
  patched  pidgin/gtksavedstatuses.c
  patched  pidgin/gtkscrollbook.c
  patched  pidgin/gtksession.c
  patched  pidgin/gtksmiley.c
  patched  pidgin/gtksmiley.h
  patched  pidgin/gtksound.c
  patched  pidgin/gtksound.h
  patched  pidgin/gtksourceundomanager.c
  patched  pidgin/gtkstatusbox.c
  patched  pidgin/gtkthemes.c
  patched  pidgin/gtkthemes.h
  patched  pidgin/gtkutils.c
  patched  pidgin/gtkutils.h
  patched  pidgin/gtkwhiteboard.c
  patched  pidgin/gtkwhiteboard.h
  patched  pidgin/minidialog.c
  patched  pidgin/pidgin-3.pc.in
  patched  pidgin/pidginstock.c
  patched  pidgin/pidgintooltip.c
  patched  pidgin/pidgintooltip.h
  patched  pidgin/plugins/Makefile.am
  patched  pidgin/plugins/contact_priority.c
  patched  pidgin/plugins/convcolors.c
  patched  pidgin/plugins/disco/gtkdisco.c
  patched  pidgin/plugins/gestures/gestures.c
  patched  pidgin/plugins/gestures/stroke-draw.c
  patched  pidgin/plugins/gevolution/gevo-util.c
  patched  pidgin/plugins/history.c
  patched  pidgin/plugins/markerline.c
  patched  pidgin/plugins/musicmessaging/musicmessaging.c
  patched  pidgin/plugins/notify.c
  patched  pidgin/plugins/perl/common/GtkIMHtml.xs
  patched  pidgin/plugins/relnot.c
  patched  pidgin/plugins/themeedit.c
  patched  pidgin/plugins/ticker/gtkticker.c
  patched  pidgin/plugins/timestamp.c
  patched  pidgin/plugins/timestamp_format.c
  patched  pidgin/plugins/vvconfig.c
  patched  pidgin/plugins/xmppconsole.c
  patched  po/ChangeLog
  patched  po/de.po

-------------- next part --------------
============================================================
--- ChangeLog	6ea5f8fd319e6dc17aaeed7556050b0b26d0de91
+++ ChangeLog	b20412c77e8ea45a5f53560e7b70916369b64b81
@@ -1,11 +1,32 @@ version 3.0.0 (??/??/????):
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 3.0.0 (??/??/????):
+	libpurple:
+	* Support new connection states and signals for NetworkManager 0.9+.
+	  (Dan Williams) (#13859)
+
 	AIM and ICQ:
 	* Make buddy list management code more efficient. (Oliver) (#4816)
 	* Don't try to format ICQ usernames entered as email addresses.
 	  Gets rid of an "Unable to format username" error at login. (#13883)
 
+	Bonjour:
+	* Support file transfers up to ~9 EiB.
+
+	Gadu-Gadu:
+	* Possibility to require encryption. Also, using encryption when
+	  available is default option now. (Tomasz Wasilczyk)
+	* Show local time for incoming messages. (Tomasz Wasilczyk) (#4579)
+	* Fixed password change dialog and problems with connecting to accounts
+	  with non-ASCII passwords. (Tomasz Wasilczyk) (#14652)
+	* Option to show links from strangers. (Tomasz Wasilczyk) (#10591)
+	* Better handling of "invisible" and "chatty" statuses. (Tomasz
+	  Wasilczyk) (#13836)
+
+	MSN:
+	* Fix file transfer with older Mac MSN clients.
+	* Support file transfers up to ~9 EiB.
+
 	MXit:
 	* Remove all reference to Hidden Number.
 	* Fix decoding of font-size changes in the markup of received messages.
@@ -14,6 +35,55 @@ version 3.0.0 (??/??/????):
 	* 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.
+
+	Plugins:
+	* The Voice/Video Settings plugin supports using the sndio GStreamer
+	 backends. (Brad Smith) (#14414)
+
+version 2.10.1 (12/06/2011):
+	Finch:
+	* Fix compilation on OpenBSD.
+
+	AIM and ICQ:
+	* Fix remotely-triggerable crashes by validating strings in a few
+	  messages related to buddy list management.  Thanks to Evgeny Boger
+	  for reporting this!  (#14682)
+
+	Bonjour:
+	* IPv6 fixes (Linus L?ssing)
+
+	Gadu-Gadu:
+	* Fix problems linking against GnuTLS. (#14544)
+
+	IRC:
+	* Fix a memory leak when admitting UTF-8 text with a non-UTF-8 primary
+	  encoding.  (#14700)
+
+	Jabber:
+	* Fix crashes and memory leaks when receiving malformed voice
+	  and video requests.  Thanks to Thijs Alkemade for reporting this!
+
+	Sametime:
+	* Separate "username" and "server" when adding new Sametime accounts.
+	  (#14608)
+	* Fix compilation in Visual C++. (#14608)
+
+	SILC:
+	* Fix CVE-2011-3594, by UTF-8 validating incoming messages before
+	  passing them to glib or libpurple.  Identified by Diego Bauche
+	  Madero from IOActive.  (#14636)
+
+	Yahoo!:
+	* Fetch buddy icons in some cases where we previously weren't. (#13050)
+
+	Windows-Specific Changes:
+	* Fix compilation
+
 version 2.10.0 (08/18/2011):
 	Pidgin:
 	* Make the max size of incoming smileys a pref instead of hardcoding it.
============================================================
--- libpurple/prefs.c	29d1bfb642ae090250dbcee59fd2e1890cb195c3
+++ libpurple/prefs.c	17df0f4f211fa4bfef39b697369c37e86fc9499c
@@ -1357,6 +1357,7 @@ purple_prefs_update_old()
 	purple_prefs_remove("/purple/conversations/chat/show_leave");
 	purple_prefs_remove("/purple/conversations/combine_chat_im");
 	purple_prefs_remove("/purple/conversations/use_alias_for_title");
+	purple_prefs_remove("/purple/debug/timestamps");
 	purple_prefs_remove("/purple/logging/log_signon_signoff");
 	purple_prefs_remove("/purple/logging/log_idle_state");
 	purple_prefs_remove("/purple/logging/log_away_state");
============================================================
--- libpurple/proxy.c	7ca2ad373cd9aa3180f4011790775334b2971251
+++ libpurple/proxy.c	bc13e6231d02debf8c80298a98dae18150bbbfc3
@@ -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 @@ s4_canwrite(gpointer data, gint source, 
 
 		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);
 
@@ -2014,7 +2024,6 @@ s5_canwrite(gpointer data, gint source, 
 		return;
 	}
 
-	i = 0;
 	buf[0] = 0x05;		/* SOCKS version 5 */
 
 	if (purple_proxy_info_get_username(connect_data->gpi) != NULL) {
@@ -2088,7 +2097,7 @@ proxy_connect_socks5(PurpleProxyConnectD
 
 /**
  * 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 +2326,7 @@ purple_proxy_connect(void *handle, Purpl
 			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 +2394,7 @@ purple_proxy_connect_udp(void *handle, P
 			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 +2407,6 @@ purple_proxy_connect_udp(void *handle, P
 	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)
  */
============================================================
--- libpurple/proxy.h	6b4cdb7abdc305b7925e20b9eaef81d0217b8ceb
+++ libpurple/proxy.h	8accbffb37e646594884b153827cd44da9cc905b
@@ -47,17 +47,8 @@ typedef enum
 /**
  * Information on proxy settings.
  */
-typedef struct
-{
-	PurpleProxyType type;   /**< The proxy type.  */
+typedef struct _PurpleProxyInfo PurpleProxyInfo;
 
-	char *host;           /**< The host.        */
-	int   port;           /**< The port number. */
-	char *username;       /**< The username.    */
-	char *password;       /**< The password.    */
-
-} PurpleProxyInfo;
-
 typedef struct _PurpleProxyConnectData PurpleProxyConnectData;
 
 typedef void (*PurpleProxyConnectFunction)(gpointer data, gint source, const gchar *error_message);
@@ -191,7 +182,6 @@ PurpleProxyInfo *purple_global_proxy_get
  * Set purple's global proxy information.
  *
  * @param info     The proxy information.
- * @since 2.6.0
  */
 void purple_global_proxy_set_info(PurpleProxyInfo *info);
 
@@ -316,36 +306,7 @@ PurpleProxyConnectData *purple_proxy_con
 			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
  * performing the initial sign on.  Or when establishing a file
============================================================
--- libpurple/server.c	2b3ba919ea5bc2b9ec70760de3a2d49a1c13a074
+++ libpurple/server.c	d2b7e95a54a6e23bc975be73041c062543c35993
@@ -149,7 +149,7 @@ int serv_send_im(PurpleConnection *gc, c
 	 * 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,19 +325,7 @@ PurpleAttentionType *purple_get_attentio
 	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 @@ void serv_got_im(PurpleConnection *gc, c
 	 * 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 @@ void serv_got_im(PurpleConnection *gc, c
 
 	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 @@ void serv_got_im(PurpleConnection *gc, c
 	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 @@ void serv_got_im(PurpleConnection *gc, c
 	 *  - 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 @@ void serv_got_typing(PurpleConnection *g
 	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 @@ void serv_got_typing(PurpleConnection *g
 		{
 			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 @@ void serv_got_typing_stopped(PurpleConne
 	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 @@ void serv_got_typing_stopped(PurpleConne
 	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 @@ void serv_got_chat_in(PurpleConnection *
 
 	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 @@ void serv_got_chat_in(PurpleConnection *
 	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);
============================================================
--- libpurple/util.c	2c2e02bfc21ec20a99176958dc93bdd6a3394d4e
+++ libpurple/util.c	977b931ade073dfc289b500ab941741d7e97c1b8
@@ -73,6 +73,14 @@ struct _PurpleUtilFetchUrlData
 	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 @@ purple_menu_action_free(PurpleMenuAction
 	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)
 {
@@ -3267,9 +3331,9 @@ char *
 }
 
 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 @@ purple_str_size_to_units(size_t size)
 	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,19 +4167,7 @@ PurpleUtilFetchUrlData *
 }
 
 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(NULL, url, full,
-					     user_agent, http11,
-					     request, include_headers, -1,
-					     callback, user_data);
-}
-
-PurpleUtilFetchUrlData *
-purple_util_fetch_url_request_len(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)
@@ -4402,11 +4454,10 @@ purple_ipv6_address_is_valid(const gchar
 	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 */
@@ -4586,7 +4637,7 @@ purple_utf8_strip_unprintables(const gch
  * This function is copied from g_strerror() but changed to use
  * gai_strerror().
  */
-G_CONST_RETURN gchar *
+const gchar *
 purple_gai_strerror(gint errnum)
 {
 	static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
============================================================
--- libpurple/conversation.c	19aac10ceebae1ee28788b6f0c02bcfcff0c8803
+++ libpurple/conversation.c	0fc7ff23e489b82d43dacdacb3d292c0db7f8980
@@ -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 @@ send_typed_cb(gpointer data)
 
 	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 @@ common_send(PurpleConversation *conv, co
 		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 @@ add_message_to_history(PurpleConversatio
 		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 @@ purple_conversation_new(PurpleConversati
 	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 @@ purple_conversation_new(PurpleConversati
 
 		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_conversation_destroy(PurpleConver
 	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 *
 }
 
 PurpleConnection *
-purple_conversation_get_gc(const PurpleConversation *conv)
+purple_conversation_get_connection(const PurpleConversation *conv)
 {
 	PurpleAccount *account;
 
@@ -705,7 +830,7 @@ purple_conversation_get_gc(const PurpleC
 	if (account == NULL)
 		return NULL;
 
-	return account->gc;
+	return purple_account_get_connection(account);
 }
 
 void
@@ -990,7 +1115,7 @@ purple_conversation_write(PurpleConversa
 							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 *
 }
 
 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 @@ purple_conv_chat_write(PurpleConvChat *c
 	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 @@ purple_conv_chat_add_users(PurpleConvCha
 	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 @@ purple_conv_chat_add_users(PurpleConvCha
 				}
 			} 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 @@ purple_conv_chat_rename_user(PurpleConvC
 	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);
@@ -1780,12 +1895,12 @@ purple_conv_chat_rename_user(PurpleConvC
 			{
 				const char *display_name = purple_connection_get_display_name(gc);
 				if (display_name != NULL)
-					alias = display_name;
+					new_alias = display_name;
 			}
 		}
 	} else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 		PurpleBuddy *buddy;
-		if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL)
+		if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL)
 			new_alias = purple_buddy_get_contact_alias(buddy);
 	}
 
@@ -1834,9 +1949,9 @@ purple_conv_chat_rename_user(PurpleConvC
 			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 @@ purple_conv_chat_remove_users(PurpleConv
 
 	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 @@ purple_conv_chat_remove_users(PurpleConv
 			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 @@ purple_find_chat(const PurpleConnection 
 		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 @@ invite_user_to_chat(gpointer data, Purpl
 	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 @@ purple_conv_chat_cb_destroy(PurpleConvCh
 	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 @@ GList *purple_conversation_get_message_h
 	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)
============================================================
--- pidgin/plugins/notify.c	a7ef531d7e3eae4cb58fd6b6ebe9e75ad6568e13
+++ pidgin/plugins/notify.c	4b4cf31eb47b8e7e438262821407e0d2b590ad95
@@ -303,7 +303,7 @@ attach_signals(PurpleConversation *conv)
 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 @@ attach_signals(PurpleConversation *conv)
 		                      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 @@ attach_signals(PurpleConversation *conv)
 		                      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 @@ attach_signals(PurpleConversation *conv)
 		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 @@ detach_signals(PurpleConversation *conv)
 	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 @@ detach_signals(PurpleConversation *conv)
 
 	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);
 }
 
============================================================
--- po/de.po	b35a2f8ff955033d45e7db0286265cb38e68a0dd
+++ po/de.po	2c30f4594781778a117a68f7df572c1ea8bf210f
@@ -11,9 +11,9 @@ msgstr ""
 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 at cs.tu-berlin.de>\n"
+"POT-Creation-Date: 2011-12-11 10:41+0100\n"
+"PO-Revision-Date: 2011-12-11 10:40+0100\n"
+"Last-Translator: Jochen Kemnade <jochenkemnade at web.de>\n"
 "Language-Team: German <de at li.org>\n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
@@ -50,17 +50,6 @@ msgstr ""
 "  -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 "
-"gestossen. 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 @@ msgstr "Fehler beim Hinzuf?gen des Budd
 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 @@ msgstr "Mitschnitt anzeigen"
 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"
 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 @@ msgid "Call in progress."
 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 @@ msgstr "Typ"
 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 @@ msgstr "Typ"
 #. 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 mDN
 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 @@ msgstr "Bitte f?llen Sie die folgenden 
 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"
 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 @@ msgstr "Bitte geben Sie Ihre Suchkriteri
 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 "Change password for the Gadu-Gadu account"
+msgstr "?ndern des Passworts f?r dieses Gadu-Gadu-Konto"
 
-msgid "Your current password is different from the one that you specified."
-msgstr "Ihr aktuelles Passwort ist anders als das angegebene."
+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 "Change password for the Gadu-Gadu account"
-msgstr "?ndern des Passworts f?r dieses Gadu-Gadu-Konto"
+msgid "Fill in the fields."
+msgstr "F?llen Sie die Felder aus."
 
-msgid "Password was changed successfully!"
-msgstr "Das Passwort wurde erfolgreich ge?ndert!"
+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 @@ msgstr "Abwesend"
 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 @@ msgstr "Verbunden"
 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 @@ msgstr "Chat_name:"
 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 @@ msgstr "Nicht mit dem Server verbunden"
 msgid "Not connected to the server"
 msgstr "Nicht mit dem Server verbunden"
 
-msgid "Find buddies..."
-msgstr "Finde Buddys..."
-
 msgid "Change password..."
 msgstr "Passwort ?ndern..."
 
+msgid "Find buddies..."
+msgstr "Finde Buddys..."
+
 msgid "Upload buddylist to Server"
 msgstr "Buddy-Liste zum Server hochladen"
 
@@ -3367,25 +3429,24 @@ msgstr "Beliebter polnischer IM-Dienst"
 msgid "Polish popular IM"
 msgstr "Beliebter polnischer IM-Dienst"
 
-msgid "Gadu-Gadu User"
-msgstr "Gadu-Gadu-Benutzer"
-
 msgid "GG server"
 msgstr "GG-Server"
 
-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 "Don't use encryption"
+msgstr "Keine Verschl?sselung benutzen"
+
 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 @@ msgstr "IRC-Server und -Spitzname d?rfe
 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 @@ msgstr "Das IRC-Protokoll-Plugin mit wen
 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 @@ msgstr "Kann SSL-Verbindung nicht erstel
 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 @@ msgstr ""
 "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 @@ msgstr "Priorit?t"
 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 @@ msgstr ""
 "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 @@ msgstr "Nicht autorisiert"
 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 @@ msgstr "Syntaxfehler (wahrscheinlich ein
 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 @@ msgstr "Nicht angemeldet"
 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 @@ msgstr "Beruf"
 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 @@ msgstr "M?chten Sie diesen Buddy ausser
 msgid "Do you want to delete this buddy from your address book as well?"
 msgstr "M?chten Sie diesen Buddy ausserdem 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 @@ msgstr "Profil-Aktualisierungsfehler"
 
 #. no profile information yet, so we cannot update
 #. (reference: "libpurple/request.h")
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Profile"
 msgstr "Profil"
 
@@ -6187,6 +6249,8 @@ msgstr "?ber..."
 msgid "About..."
 msgstr "?ber..."
 
+#. we are trying to send a file to MXit
+#. need to reserve some space for packet headers
 #. the file is too big
 msgid "The file you are trying to send is too large!"
 msgstr "Die Datei, die Sie senden m?chten ist zu gross!"
@@ -6307,16 +6371,14 @@ msgstr "Lade das Men?..."
 msgid "Loading menu..."
 msgstr "Lade das Men?..."
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Status Message"
 msgstr "Status-Nachricht"
 
 msgid "Rejection Message"
 msgstr "Ablehnungsnachricht"
 
-#. hidden number
-msgid "Hidden Number"
-msgstr "Versteckte Nummer"
-
 msgid "No profile available"
 msgstr "Kein Profil verf?gbar"
 
@@ -6400,6 +6462,12 @@ msgstr "Nachrichtenfehler"
 msgid "Message Error"
 msgstr "Nachrichtenfehler"
 
+#. could not be decrypted
+msgid "An encrypted message was received which could not be decrypted."
+msgstr ""
+"Eine verschl?sselte Nachricht wurde empfangen und konnte nicht entschl?sselt "
+"werden."
+
 msgid "Cannot perform redirect using the specified protocol"
 msgstr "Kann die Umleitung nicht mit dem angegebenen Protokoll durchf?hren"
 
@@ -6664,18 +6732,26 @@ msgstr "Basis-Schriftgr?sse (Punkt)"
 msgid "Base font size (points)"
 msgstr "Basis-Schriftgr?sse (Punkt)"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "User"
 msgstr "Benutzer"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Headline"
 msgstr "?berschrift"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Song"
 msgstr "Lied"
 
 msgid "Total Friends"
 msgstr "Freunde insgesamt"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Client Version"
 msgstr "Client-Version"
 
@@ -6879,9 +6955,6 @@ msgstr "Passwort ist abgelaufen"
 msgid "Password has expired"
 msgstr "Passwort ist abgelaufen"
 
-msgid "Incorrect password"
-msgstr "Falsches Passwort"
-
 msgid "Account has been disabled"
 msgstr "Konto wurde deaktiviert"
 
@@ -6908,12 +6981,6 @@ msgstr ""
 "Konnte den Rechnernamen des Benutzers, den Sie eingegeben haben, nicht "
 "erkennen"
 
-msgid ""
-"Your account has been disabled because too many incorrect passwords were "
-"entered"
-msgstr ""
-"Ihr Konto wurde wegen zu vielen falsch eingegebenen Passworten gesperrt"
-
 msgid "You cannot add the same person twice to a conversation"
 msgstr "Sie k?nnen die selbe Person nicht zweimal zu einem Gespr?ch hinzuf?gen"
 
@@ -7039,12 +7106,9 @@ msgstr "Benutzer-ID"
 msgid "User ID"
 msgstr "Benutzer-ID"
 
-#. tag = _("DN");
-#. value = nm_user_record_get_dn(user_record);
-#. if (value) {
-#. purple_notify_user_info_add_pair(user_info, tag, value);
-#. }
-#.
+msgid "DN"
+msgstr "DN"
+
 msgid "Full name"
 msgstr "Vollst?ndiger Name"
 
@@ -8147,6 +8211,7 @@ msgstr "Handynummer"
 msgid "Mobile Phone"
 msgstr "Handynummer"
 
+#. TODO: Is it correct to pass info->email here...?
 msgid "Personal Web Page"
 msgstr "Pers?nliche Webseite"
 
@@ -8167,6 +8232,7 @@ msgstr "Position"
 msgid "Position"
 msgstr "Position"
 
+#. TODO: Is it correct to pass info->email here...?
 msgid "Web Page"
 msgstr "Webseite"
 
@@ -8433,33 +8499,16 @@ msgstr "Thema:"
 msgid "Topic:"
 msgstr "Thema:"
 
-msgid "No Sametime Community Server specified"
-msgstr "Kein Sametime-Community Server angegeben"
+msgid "A server is required to connect this account"
+msgstr "Es wird ein Server ben?tigt um dieses Konto zu verbinden."
 
-#, 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 "Last Known Client"
+msgstr "Letzter bekannter Client"
 
-msgid "Meanwhile Connection Setup"
-msgstr "Meanwhile-Verbindungseinstellungen"
-
-msgid "No Sametime Community Server Specified"
-msgstr "Kein Sametime-Community Server angegeben"
-
-msgid "Connect"
-msgstr "Verbinden"
-
 #, c-format
 msgid "Unknown (0x%04x)<br>"
 msgstr "Unbekannt (0x%04x)<br>"
 
-msgid "Last Known Client"
-msgstr "Letzter bekannter Client"
-
 msgid "User Name"
 msgstr "Benutzername"
 
@@ -8782,21 +8831,33 @@ msgstr "Robot"
 msgid "Robot"
 msgstr "Robot"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "User Modes"
 msgstr "Benutzermodi"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Preferred Contact"
 msgstr "Bevorzugter Kontakt"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Preferred Language"
 msgstr "Bevorzugte Sprache"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Device"
 msgstr "Ger?t"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Timezone"
 msgstr "Zeitzone"
 
+#. TODO: Check whether it's correct to call add_pair_html,
+#. or if we should be using add_pair_plaintext
 msgid "Geolocation"
 msgstr "Geographische Koordinaten"
 
@@ -9666,78 +9727,12 @@ msgstr "Whiteboard"
 msgid "Whiteboard"
 msgstr "Whiteboard"
 
-msgid "No server statistics available"
-msgstr "Keine Serverstatistik verf?gbar"
-
-msgid "Error during connecting to SILC Server"
-msgstr "Fehler beim Verbinden mit dem SILC-Server"
-
-#, c-format
-msgid "Failure: Version mismatch, upgrade your client"
-msgstr "Fehler: Unterschiedliche Version, aktualisieren Sie Ihren Client"
-
-#, c-format
-msgid "Failure: Remote does not trust/support your public key"
-msgstr ""
-"Fehler: Die entfernte Seite vertraut Ihrem ?ffentlichen Schl?ssel nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed KE group"
-msgstr ""
-"Fehler: Entferntes Programm unterst?tzt nicht die vorgeschlagen KE-Gruppe"
-
-#, c-format
-msgid "Failure: Remote does not support proposed cipher"
-msgstr ""
-"Fehler: Entferntes Programm unterst?tzt die vorgeschlagene Chiffre nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed PKCS"
-msgstr "Fehler: Entferntes Programm unterst?tzt die vorgeschlagene PKCS nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed hash function"
-msgstr ""
-"Fehler: Entferntes Programm unterst?tzt die vorgeschlagen Hashfunktion nicht"
-
-#, c-format
-msgid "Failure: Remote does not support proposed HMAC"
-msgstr "Fehler: Entferntes Programm unterst?tzt das vorgeschlagene HMAC nicht"
-
-#, c-format
-msgid "Failure: Incorrect signature"
-msgstr "Fehler: Falsche Signatur"
-
-#, c-format
-msgid "Failure: Invalid cookie"
-msgstr "Fehler: Ung?ltiger Cookie"
-
-#, c-format
-msgid "Failure: Authentication failed"
-msgstr "Fehler: Authentifizierung fehlgeschlagen"
-
-msgid "Unable to initialize SILC Client connection"
-msgstr "SILC-Client-Verbindung konnte nicht hergestellt werden"
-
-msgid "John Noname"
-msgstr "Max Mustermann"
-
-#, c-format
-msgid "Unable to load SILC key pair: %s"
-msgstr "SILC-Schl?sselpaar konnte nicht geladen werden: %s"
-
-msgid "Unable to create connection"
-msgstr "Kann Verbindung nicht erstellen"
-
 msgid "Unknown server response"
 msgstr "Unbekannte Serverantwort"
 
 msgid "Unable to create listen socket"
 msgstr "Lauschender Socket konnte nicht erstellt werden"
 
-msgid "Unable to resolve hostname"
-msgstr "Hostname konnte nicht aufgel?st werden"
-
 msgid "SIP usernames may not contain whitespaces or @ symbols"
 msgstr "SIP-Benutzernamen d?rfen keine Leerzeichen oder @-Symbole enthalten"
 
@@ -10218,6 +10213,8 @@ msgstr "Versteckt oder nicht angemeldet"
 msgid "Hidden or not logged-in"
 msgstr "Versteckt oder nicht angemeldet"
 
+#. TODO: Need to escape locs.host and locs.time?
+#. TODO: Need to escape the two strings that make up tmp?
 #, c-format
 msgid "<br>At %s since %s"
 msgstr "<br>Bei %s seit %s"
@@ -10426,9 +10423,6 @@ msgstr "Gespeichertes Bild. (Das muss er
 msgid "Stored Image. (that'll have to do for now)"
 msgstr "Gespeichertes Bild. (Das muss erstmal reichen)"
 
-msgid "SSL Connection Failed"
-msgstr "SSL-Verbindung gescheitert"
-
 msgid "SSL Handshake Failed"
 msgstr "SSL-Verhandlung gescheitert"
 
@@ -11394,6 +11388,21 @@ msgstr "SSL-Server"
 msgid "SSL Servers"
 msgstr "SSL-Server"
 
+msgid "Unsafe debugging is now disabled."
+msgstr "Unsicheres Debugging ist nun deaktiviert."
+
+msgid "Unsafe debugging is now enabled."
+msgstr "Unsicheres Debugging ist nun aktiviert."
+
+msgid "Verbose debugging is now disabled."
+msgstr "Ausf?hrliches Debugging ist nun deaktiviert."
+
+msgid "Verbose debugging is now enabled."
+msgstr "Ausf?hrliches Debugging ist nun aktiviert."
+
+msgid "Supported debug options are: plugins version unsafe verbose"
+msgstr "Unterst?tzte Debug-Optionen sind: plugins version unsafe verbose"
+
 msgid "Unknown command."
 msgstr "Unbekanntes Kommando."
 
@@ -11428,9 +11437,6 @@ msgstr "Ignorieren"
 msgid "Ignore"
 msgstr "Ignorieren"
 
-msgid "Get Away Message"
-msgstr "Neue Abwesenheitsnachricht abholen"
-
 msgid "Last Said"
 msgstr "Zuletzt gesagt"
 
@@ -12178,12 +12184,6 @@ msgstr "Benutzer-Mitschnitt anzeigen"
 msgid "View User Log"
 msgstr "Benutzer-Mitschnitt anzeigen"
 
-msgid "Alias Contact"
-msgstr "Kontakt-Alias"
-
-msgid "Enter an alias for this contact."
-msgstr "Geben Sie einen Alias f?r diesen Kontakt ein."
-
 #, c-format
 msgid "Enter an alias for %s."
 msgstr "Geben Sie einen Alias %s ein."
@@ -12779,9 +12779,18 @@ msgstr "Eingehender Anruf"
 msgid "Incoming Call"
 msgstr "Eingehender Anruf"
 
+msgid "_Hold"
+msgstr "_Halten"
+
 msgid "_Pause"
 msgstr "_Pause"
 
+msgid "_Mute"
+msgstr "Stu_mmschalten"
+
+msgid "Call in progress"
+msgstr "Anruf im Gange"
+
 #, c-format
 msgid "%s has %d new message."
 msgid_plural "%s has %d new messages."
@@ -13004,6 +13013,9 @@ msgstr "Das Standard-Buddy-Listen-Thema 
 msgid "The default Pidgin buddy list theme"
 msgstr "Das Standard-Buddy-Listen-Thema f?r Pidgin"
 
+msgid "The default Pidgin conversation theme"
+msgstr "Das Standard-Thema f?r Pidgin-Unterhaltungen"
+
 msgid "The default Pidgin status icon theme"
 msgstr "Das Standard-Status-Icon-Thema f?r Pidgin"
 
@@ -13031,6 +13043,13 @@ msgstr "Buddy-Listen-Thema:"
 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:"
 
============================================================
--- libpurple/prpl.c	3fe7a8aa8d3ecfdc96d639823a86c3be483e2305
+++ libpurple/prpl.c	44f9efbeb20854cd6d5d250281f92af6c57c9fe6
@@ -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 @@ purple_prpl_send_attention(PurpleConnect
 	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 @@ purple_prpl_send_attention(PurpleConnect
 	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 @@ got_attention(PurpleConnection *gc, int 
 
 	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;
============================================================
--- libpurple/prpl.h	00ddff21fbb760369b95f999cb7ead428862bfb2
+++ libpurple/prpl.h	c4fa00ba5df1000f637df6e40b8d764dd2436b94
@@ -31,7 +31,10 @@ typedef struct _PurplePluginProtocolInfo
 #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 @@ struct proto_chat_entry {
 	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 @@ typedef enum
 	/**
 	 * 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
  */
 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 @@ struct _PurplePluginProtocolInfo
 	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 @@ struct _PurplePluginProtocolInfo
 	 * 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 @@ struct _PurplePluginProtocolInfo
 	 * @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 @@ struct _PurplePluginProtocolInfo
 	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 @@ struct _PurplePluginProtocolInfo
 	/**
 	 * 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 @@ struct _PurplePluginProtocolInfo
 	 * @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 @@ struct _PurplePluginProtocolInfo
 	 * @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 @@ extern "C" {
  *             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 @@ PurpleAttentionType *purple_attention_ty
  * @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 @@ void purple_attention_type_set_name(Purp
  *
  * @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 @@ void purple_attention_type_set_incoming_
  *
  * @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 @@ void purple_attention_type_set_outgoing_
  * @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 @@ void purple_attention_type_set_icon_name
  * @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 @@ void purple_attention_type_set_unlocaliz
  * 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 @@ const char *purple_attention_type_get_na
  *
  * @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 @@ const char *purple_attention_type_get_in
  *
  * @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 @@ const char *purple_attention_type_get_ou
  * @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 @@ const char *purple_attention_type_get_ic
  *
  * @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 @@ void purple_prpl_got_account_status(Purp
  * @param account   The account.
  *
  * @see account-actions-changed
- * @since 2.6.0
  */
 void purple_prpl_got_account_actions(PurpleAccount *account);
 
@@ -927,8 +877,6 @@ GList *purple_prpl_get_statuses(PurpleAc
  *
  * 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 @@ void purple_prpl_send_attention(PurpleCo
  * @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 @@ void purple_prpl_got_attention(PurpleCon
  * @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 @@ gboolean purple_prpl_initiate_media(Purp
  *
  * @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);
 
============================================================
--- pidgin/gtkimhtml.c	18308b4f2c7e90808ec355dc40b1e7283d87cbcd
+++ pidgin/gtkimhtml.c	c89758f4458c27732c0c2241726cdd17dbbf7316
@@ -65,6 +65,16 @@
 
 #define TOOLTIP_TIMEOUT 500
 
+#if !GTK_CHECK_VERSION(2,20,0)
+#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x)
+
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x)
+#define gtk_widget_get_state(x) GTK_WIDGET_STATE(x)
+#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x)
+#endif
+#endif
+
 static GtkTextViewClass *parent_class = NULL;
 
 struct scalable_data {
@@ -83,6 +93,36 @@ struct im_image_data {
 	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 +130,13 @@ struct _GtkIMHtmlLink
 	GtkTextTag *tag;
 };
 
-typedef struct _GtkIMHtmlProtocol
-{
+struct _GtkSmileyTree {
+	GString *values;
+	GtkSmileyTree **children;
+	GtkIMHtmlSmiley *image;
+};
+
+typedef struct {
 	char *name;
 	int length;
 
@@ -99,7 +144,8 @@ typedef struct _GtkIMHtmlProtocol
 	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;
@@ -511,20 +557,18 @@ gtk_imhtml_tip_paint (GtkIMHtml *imhtml)
 gtk_imhtml_tip_paint (GtkIMHtml *imhtml)
 {
 	PangoLayout *layout;
-	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(imhtml->tip_window));
 
 	g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE);
 
 	layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip);
 
-	gtk_paint_flat_box (gtk_widget_get_style(imhtml->tip_window), cr,
-		GTK_STATE_NORMAL, GTK_SHADOW_OUT, imhtml->tip_window, "tooltip",
-		0, 0, -1, -1);
+	gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window,
+						GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window,
+						"tooltip", 0, 0, -1, -1);
 
-	gtk_paint_layout (gtk_widget_get_style(imhtml->tip_window), cr,
-		GTK_STATE_NORMAL, TRUE, imhtml->tip_window, NULL, 4, 4, layout);
+	gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL,
+					  FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout);
 
-	cairo_destroy(cr);
 	g_object_unref(layout);
 	return FALSE;
 }
@@ -536,15 +580,12 @@ gtk_imhtml_tip (gpointer data)
 	PangoFontMetrics *font_metrics;
 	PangoLayout *layout;
 	PangoFont *font;
-	GtkStyle *style = gtk_widget_get_style(imhtml->tip_window);
-	GtkAllocation allocation;
+
 	gint gap, x, y, h, w, scr_w, baseline_skip;
 
 	g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE);
 
-	gtk_widget_get_allocation(GTK_WIDGET(imhtml), &allocation);
-
-	if (!imhtml->tip || !gtk_widget_is_drawable(GTK_WIDGET(imhtml))) {
+	if (!imhtml->tip || !gtk_widget_is_drawable (GTK_WIDGET(imhtml))) {
 		imhtml->tip_timer = 0;
 		return FALSE;
 	}
@@ -568,10 +609,11 @@ gtk_imhtml_tip (gpointer data)
 	gtk_widget_ensure_style (imhtml->tip_window);
 	layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip);
 	font = pango_context_load_font(pango_layout_get_context(layout),
-	                               style->font_desc);
+			      imhtml->tip_window->style->font_desc);
 
 	if (font == NULL) {
-		char *tmp = pango_font_description_to_string(style->font_desc);
+		char *tmp = pango_font_description_to_string(
+					imhtml->tip_window->style->font_desc);
 
 		purple_debug(PURPLE_DEBUG_ERROR, "gtk_imhtml_tip",
 			"pango_context_load_font() couldn't load font: '%s'\n",
@@ -596,8 +638,8 @@ gtk_imhtml_tip (gpointer data)
 	h = 8 + baseline_skip;
 
 	gdk_window_get_pointer (NULL, &x, &y, NULL);
-	if ((!gtk_widget_get_has_window(GTK_WIDGET(imhtml))))
-		y += allocation.y;
+	if (!gtk_widget_get_has_window (GTK_WIDGET(imhtml)))
+		y += GTK_WIDGET(imhtml)->allocation.y;
 
 	scr_w = gdk_screen_width();
 
@@ -637,7 +679,7 @@ gtk_motion_event_notify(GtkWidget *imhtm
 
 	oldprelit_tag = GTK_IMHTML(imhtml)->prelit_tag;
 
-	gdk_window_get_pointer(gtk_widget_get_window(GTK_WIDGET(imhtml)), NULL, NULL, NULL);
+	gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL);
 	gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET,
 	                                      event->x, event->y, &x, &y);
 	gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y);
@@ -765,8 +807,6 @@ gtk_leave_event_notify(GtkWidget *imhtml
 	return FALSE;
 }
 
-/* TODO: I think this can be removed for GTK+ 3.0... */
-#if 0
 static gint
 gtk_imhtml_expose_event (GtkWidget      *widget,
 			 GdkEventExpose *event)
@@ -794,8 +834,7 @@ gtk_imhtml_expose_event (GtkWidget      
 			gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor);
 			gdk_cairo_set_source_color(cr, &gcolor);
 		} else {
-			gdk_cairo_set_source_color(cr,
-				&(gtk_widget_get_style(widget)->base[gtk_widget_get_state(widget)]));
+			gdk_cairo_set_source_color(cr, &(widget->style->base[gtk_widget_get_state(widget)]));
 		}
 
 		cairo_rectangle(cr,
@@ -901,7 +940,6 @@ gtk_imhtml_expose_event (GtkWidget      
 
 	return FALSE;
 }
-#endif
 
 
 static void paste_unformatted_cb(GtkMenuItem *menu, GtkIMHtml *imhtml)
@@ -1073,7 +1111,7 @@ static void gtk_imhtml_clipboard_get(Gtk
 	}
 	if (primary) /* This was allocated here */
 		g_free(text);
-}
+ }
 
 static void gtk_imhtml_primary_clipboard_clear(GtkClipboard *clipboard, GtkIMHtml *imhtml)
 {
@@ -1178,12 +1216,11 @@ static void paste_received_cb (GtkClipbo
 {
 	char *text;
 	GtkIMHtml *imhtml = data;
-	gint length = gtk_selection_data_get_length(selection_data);
 
 	if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml)))
 		return;
 
-	if (imhtml->wbfo || length <= 0) {
+	if (imhtml->wbfo || selection_data->length <= 0) {
 		gtk_clipboard_request_text(clipboard, paste_plaintext_received_cb, imhtml);
 		return;
 	} else {
@@ -1207,13 +1244,13 @@ static void paste_received_cb (GtkClipbo
 		}
 #endif
 
-		text = g_malloc(length + 1);
-		memcpy(text, gtk_selection_data_get_data(selection_data), length);
+		text = g_malloc(selection_data->length + 1);
+		memcpy(text, selection_data->data, selection_data->length);
 		/* Make sure the paste data is null-terminated.  Given that
 		 * we're passed length (but assume later that it is
 		 * null-terminated), this seems sensible to me.
 		 */
-		text[length] = '\0';
+		text[selection_data->length] = '\0';
 	}
 
 #ifdef _WIN32
@@ -1224,10 +1261,10 @@ static void paste_received_cb (GtkClipbo
 	}
 #endif
 
-	if (length >= 2 &&
+	if (selection_data->length >= 2 &&
 		(*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe)) {
 		/* This is UTF-16 */
-		char *utf8 = utf16_to_utf8_with_bom_check(text, length);
+		char *utf8 = utf16_to_utf8_with_bom_check(text, selection_data->length);
 		g_free(text);
 		text = utf8;
 		if (!text) {
@@ -1342,7 +1379,7 @@ static gboolean gtk_imhtml_button_press_
 				       paste_received_cb, imhtml);
 
 		return TRUE;
-	}
+        }
 
 	return FALSE;
 }
@@ -1588,8 +1625,7 @@ static void gtk_imhtml_class_init (GtkIM
 
 	gobject_class->finalize = gtk_imhtml_finalize;
 	widget_class->drag_motion = gtk_text_view_drag_motion;
-	/* TODO: I _think_ this should be removed for GTK+ 3.0 */
-	/*widget_class->expose_event = gtk_imhtml_expose_event;*/
+	widget_class->expose_event = gtk_imhtml_expose_event;
 	parent_size_allocate = widget_class->size_allocate;
 	widget_class->size_allocate = gtk_imhtml_size_allocate;
 	parent_style_set = widget_class->style_set;
@@ -1651,20 +1687,20 @@ static void gtk_imhtml_class_init (GtkIM
 	                                        TRUE, G_PARAM_READABLE));
 
 	binding_set = gtk_binding_set_by_class (parent_class);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK);
+	gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD);
+	gtk_binding_entry_add_signal (binding_set, GDK_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC);
+	gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE);
+	gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW);
+	gtk_binding_entry_add_signal (binding_set, GDK_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW);
+	gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK);
 	binding_set = gtk_binding_set_by_class(klass);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_r, GDK_CONTROL_MASK, "format_function_clear", 0);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "message_send", 0);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "message_send", 0);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_z, GDK_CONTROL_MASK, "undo", 0);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0);
-	gtk_binding_entry_add_signal (binding_set, GDK_KEY_F14, 0, "undo", 0);
-	gtk_binding_entry_add_signal(binding_set, GDK_KEY_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text");
+	gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0);
+	gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0);
+	gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0);
+	gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0);
+	gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0);
+	gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0);
+	gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text");
 }
 
 static void gtk_imhtml_init (GtkIMHtml *imhtml)
@@ -1891,23 +1927,23 @@ gtk_text_view_drag_motion (GtkWidget    
 		/* can't accept any of the offered targets */
 	} else {
 		GtkWidget *source_widget;
-		suggested_action = gdk_drag_context_get_suggested_action(context);
+		suggested_action = context->suggested_action;
 		source_widget = gtk_drag_get_source_widget (context);
 		if (source_widget == widget) {
 			/* Default to MOVE, unless the user has
 			 * pressed ctrl or alt to affect available actions
 			 */
-			if ((gdk_drag_context_get_actions(context) & GDK_ACTION_MOVE) != 0)
+			if ((context->actions & GDK_ACTION_MOVE) != 0)
 				suggested_action = GDK_ACTION_MOVE;
 		}
 	}
 
 	gdk_drag_status (context, suggested_action, time);
 
-	/* TRUE return means don't propagate the drag motion to parent
-	 * widgets that may also be drop sites.
-	 */
-	return TRUE;
+  /* TRUE return means don't propagate the drag motion to parent
+   * widgets that may also be drop sites.
+   */
+  return TRUE;
 }
 
 static void
@@ -1929,22 +1965,21 @@ gtk_imhtml_link_drag_rcv_cb(GtkWidget *w
 {
 	gchar **links;
 	gchar *link;
-	char *text = (char *) gtk_selection_data_get_data(sd);
+	char *text = (char *)sd->data;
 	GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer);
 	GtkTextIter iter;
 	gint i = 0;
-	gint length = gtk_selection_data_get_length(sd);
 
 	gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark);
 
-	if (gtk_imhtml_get_editable(imhtml) && text) {
+	if(gtk_imhtml_get_editable(imhtml) && sd->data){
 		switch (info) {
 		case GTK_IMHTML_DRAG_URL:
 			/* TODO: Is it really ok to change sd->data...? */
-			purple_str_strip_char(text, '\r');
+			purple_str_strip_char((char *)sd->data, '\r');
 
-			links = g_strsplit(text, "\n", 0);
-			while ((link = links[i]) != NULL) {
+			links = g_strsplit((char *)sd->data, "\n", 0);
+			while((link = links[i]) != NULL){
 				if (gtk_imhtml_is_protocol(link)) {
 					gchar *label;
 
@@ -1966,7 +2001,7 @@ gtk_imhtml_link_drag_rcv_cb(GtkWidget *w
 
 				i++;
 			}
-			g_strfreev(links);
+            g_strfreev(links);
 			break;
 		case GTK_IMHTML_DRAG_HTML:
 			{
@@ -1982,8 +2017,8 @@ gtk_imhtml_link_drag_rcv_cb(GtkWidget *w
 			 * See also the comment on text/html here:
 			 * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html
 			 */
-			if (length >= 2 && !g_utf8_validate(text, length - 1, NULL)) {
-				utf8 = utf16_to_utf8_with_bom_check(text, length);
+			if (sd->length >= 2 && !g_utf8_validate(text, sd->length - 1, NULL)) {
+				utf8 = utf16_to_utf8_with_bom_check(text, sd->length);
 
 				if (!utf8) {
 					purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in drag_rcv_cb\n");
@@ -2012,8 +2047,7 @@ gtk_imhtml_link_drag_rcv_cb(GtkWidget *w
 			gtk_drag_finish(dc, FALSE, FALSE, t);
 			return;
 		}
-		gtk_drag_finish(dc, TRUE,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	} else {
 		gtk_drag_finish(dc, FALSE, FALSE, t);
 	}
@@ -2544,8 +2578,8 @@ static gboolean smooth_scroll_cb(gpointe
 static gboolean smooth_scroll_cb(gpointer data)
 {
 	GtkIMHtml *imhtml = data;
-	GtkAdjustment *adj = gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(imhtml));
-	gdouble max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj);
+	GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment;
+	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(imhtml->scroll_time != NULL, FALSE);
@@ -2568,10 +2602,9 @@ static gboolean scroll_idle_cb(gpointer 
 static gboolean scroll_idle_cb(gpointer data)
 {
 	GtkIMHtml *imhtml = data;
-	GtkAdjustment *adj = gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(imhtml));
-	if (adj) {
-		gtk_adjustment_set_value(adj, gtk_adjustment_get_upper(adj) -
-		                              gtk_adjustment_get_page_size(adj));
+	GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment;
+	if(adj) {
+		gtk_adjustment_set_value(adj, adj->upper - adj->page_size);
 	}
 	imhtml->scroll_src = 0;
 	return FALSE;
@@ -3606,127 +3639,40 @@ void gtk_imhtml_page_down (GtkIMHtml *im
 	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)
+/**
+ * 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 *im_image = g_malloc(sizeof(GtkIMHtmlImage));
+	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
 
-	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);
+	g_object_unref(image->pixbuf);
+	g_free(image->filename);
+	if (image->filesel)
+		gtk_widget_destroy(image->filesel);
+	g_free(scale);
 }
 
-static gboolean
-animate_image_cb(gpointer data)
+/**
+ * Destroys and frees a GTK+ IM/HTML scalable animation.
+ *
+ * @param scale The GTK+ IM/HTML scalable.
+ */
+static void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale)
 {
-	GtkIMHtmlImage *im_image;
-	int width, height;
-	int delay;
+	GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale;
 
-	im_image = data;
+	if (animation->timer > 0)
+		g_source_remove(animation->timer);
+	if (animation->iter != NULL)
+		g_object_unref(animation->iter);
+	g_object_unref(animation->anim);
 
-	/* 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;
+	gtk_imhtml_image_free(scale);
 }
 
-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));
-	}
-}
-
 static void
 image_save_yes_cb(GtkIMHtmlImageSave *save, const char *filename)
 {
@@ -3931,55 +3877,51 @@ static gboolean gtk_imhtml_image_clicked
 
 }
 
-static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
+/**
+ * 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)
 {
-	GdkPixbufAnimation *anim = NULL;
-	GtkIMHtmlImageSave *save = NULL;
-	gboolean ret;
+	GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
 
-	if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
-		return FALSE;
+	if (im_image->width > width || im_image->height > height) {
+		double ratio_w, ratio_h, ratio;
+		int new_h, new_w;
+		GdkPixbuf *new_image = NULL;
 
-	anim = gtk_smiley_get_image(smiley);
-	if (!anim)
-		return FALSE;
+		ratio_w = ((double)width - 2) / im_image->width;
+		ratio_h = ((double)height - 2) / im_image->height;
 
-	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;
-}
+		ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
 
-void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
-{
-	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
+		new_w = (int)(im_image->width * ratio);
+		new_h = (int)(im_image->height * ratio);
 
-	g_object_unref(image->pixbuf);
-	g_free(image->filename);
-	if (image->filesel)
-		gtk_widget_destroy(image->filesel);
-	g_free(scale);
-}
+		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;
 
-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);
+		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));
+	}
 }
 
-void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
+/**
+ * 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();
@@ -4007,6 +3949,121 @@ void gtk_imhtml_image_add_to(GtkIMHtmlSc
 	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));
@@ -4229,14 +4286,9 @@ static void remove_tag_by_prefix(GtkIMHt
 
 	for (l = tags; l; l = l->next) {
 		GtkTextTag *tag = l->data;
-		gchar *name = NULL;
 
-		g_object_get(G_OBJECT(tag), "name", &name, NULL);
-
-		if (name && !strncmp(name, prefix, len))
+		if (tag->name && !strncmp(tag->name, prefix, len))
 			gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e);
-
-		g_free(name);
 	}
 
 	g_slist_free(tags);
@@ -4252,14 +4304,9 @@ static void remove_tag_by_prefix(GtkIMHt
 
 			for (l = tags; l; l = l->next) {
 				GtkTextTag *tag = l->data;
-				gchar *name = NULL;
 
-				g_object_get(G_OBJECT(tag), "name", &name, NULL);
-
-				if (name && !strncmp(name, prefix, len))
+				if (tag->name && !strncmp(tag->name, prefix, len))
 					gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e);
-
-				g_free(name);
 			}
 
 			g_slist_free(tags);
@@ -4380,16 +4427,11 @@ static void delete_cb(GtkTextBuffer *buf
 				gtk_text_iter_begins_tag(start, tag) &&			/* the tag starts with the selection */
 				(!gtk_text_iter_has_tag(end, tag) ||			/* the tag ends within the selection */
 					gtk_text_iter_ends_tag(end, tag))) {
-			gchar *name = NULL;
-
-			g_object_get(G_OBJECT(tag), "name", &name, NULL);
 			gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, start, end);
-
-			if (name && strncmp(name, "LINK ", 5) == 0 && imhtml->edit.link) {
+			if (tag->name &&
+					strncmp(tag->name, "LINK ", 5) == 0 && imhtml->edit.link) {
 				gtk_imhtml_toggle_link(imhtml, NULL);
 			}
-
-			g_free(name);
 		}
 	}
 	g_slist_free(tags);
@@ -4611,32 +4653,27 @@ static void mark_set_cb(GtkTextBuffer *b
 
 	for (l = tags; l != NULL; l = l->next) {
 		GtkTextTag *tag = GTK_TEXT_TAG(l->data);
-		gchar *name = NULL;
 
-		g_object_get(G_OBJECT(tag), "name", &name, NULL);
-
-		if (name) {
-			if (strcmp(name, "BOLD") == 0)
+		if (tag->name) {
+			if (strcmp(tag->name, "BOLD") == 0)
 				imhtml->edit.bold = TRUE;
-			else if (strcmp(name, "ITALICS") == 0)
+			else if (strcmp(tag->name, "ITALICS") == 0)
 				imhtml->edit.italic = TRUE;
-			else if (strcmp(name, "UNDERLINE") == 0)
+			else if (strcmp(tag->name, "UNDERLINE") == 0)
 				imhtml->edit.underline = TRUE;
-			else if (strcmp(name, "STRIKE") == 0)
+			else if (strcmp(tag->name, "STRIKE") == 0)
 				imhtml->edit.strike = TRUE;
-			else if (strncmp(name, "FORECOLOR ", 10) == 0)
-				imhtml->edit.forecolor = g_strdup(&(name)[10]);
-			else if (strncmp(name, "BACKCOLOR ", 10) == 0)
-				imhtml->edit.backcolor = g_strdup(&(name)[10]);
-			else if (strncmp(name, "FONT FACE ", 10) == 0)
-				imhtml->edit.fontface = g_strdup(&(name)[10]);
-			else if (strncmp(name, "FONT SIZE ", 10) == 0)
-				imhtml->edit.fontsize = strtol(&(name)[10], NULL, 10);
-			else if ((strncmp(name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter))
+			else if (strncmp(tag->name, "FORECOLOR ", 10) == 0)
+				imhtml->edit.forecolor = g_strdup(&(tag->name)[10]);
+			else if (strncmp(tag->name, "BACKCOLOR ", 10) == 0)
+				imhtml->edit.backcolor = g_strdup(&(tag->name)[10]);
+			else if (strncmp(tag->name, "FONT FACE ", 10) == 0)
+				imhtml->edit.fontface = g_strdup(&(tag->name)[10]);
+			else if (strncmp(tag->name, "FONT SIZE ", 10) == 0)
+				imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10);
+			else if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter))
 				imhtml->edit.link = tag;
 		}
-
-		g_free(name);
 	}
 
 	g_slist_free(tags);
@@ -4927,8 +4964,6 @@ void gtk_imhtml_insert_smiley(GtkIMHtml 
 	gtk_text_buffer_end_user_action(imhtml->text_buffer);
 }
 
-/* TODO: I think this can be removed for GTK+ 3.0... */
-#if 0
 static gboolean
 image_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
 {
@@ -4936,10 +4971,9 @@ image_expose(GtkWidget *widget, GdkEvent
 
 	return TRUE;
 }
-#endif
 
 /* In case the smiley gets removed from the imhtml before it gets removed from the queue */
-static void animated_smiley_destroy_cb(GtkWidget *widget, GtkIMHtml *imhtml)
+static void animated_smiley_destroy_cb(GtkObject *widget, GtkIMHtml *imhtml)
 {
 	GList *l = imhtml->animations->head;
 	while (l) {
@@ -4954,6 +4988,30 @@ static void animated_smiley_destroy_cb(G
 	}
 }
 
+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;
@@ -5010,7 +5068,7 @@ void gtk_imhtml_insert_smiley_at_iter(Gt
 						}
 					}
 				} else {
-					imhtml->num_animations++;
+ 					imhtml->num_animations++;
 				}
 				g_signal_connect(G_OBJECT(icon), "destroy", G_CALLBACK(animated_smiley_destroy_cb), imhtml);
 				g_queue_push_tail(imhtml->animations, icon);
@@ -5034,9 +5092,7 @@ void gtk_imhtml_insert_smiley_at_iter(Gt
 		 * images, and ensures that they are handled by the image
 		 * itself, without propagating to the textview and causing
 		 * a complete refresh */
-		/* TODO: I think this should be removed for GTK+ 3.0?
 		g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL);
-		*/
 
 		gtk_widget_show(icon);
 		if (ebox)
@@ -5130,29 +5186,22 @@ static const gchar *tag_to_html_start(Gt
 
 static const gchar *tag_to_html_start(GtkTextTag *tag)
 {
+	const gchar *name;
 	static gchar buf[1024];
-	gchar *name = NULL;
 
+	name = tag->name;
 	g_return_val_if_fail(name != NULL, "");
-	g_object_get(G_OBJECT(tag), "name", &name, NULL);
 
 	if (strcmp(name, "BOLD") == 0) {
-		g_free(name);
 		return "<b>";
 	} else if (strcmp(name, "ITALICS") == 0) {
-		g_free(name);
 		return "<i>";
 	} else if (strcmp(name, "UNDERLINE") == 0) {
-		g_free(name);
 		return "<u>";
 	} else if (strcmp(name, "STRIKE") == 0) {
-		g_free(name);
 		return "<s>";
 	} else if (strncmp(name, "LINK ", 5) == 0) {
 		char *tmp = g_object_get_data(G_OBJECT(tag), "link_url");
-
-		g_free(name);
-
 		if (tmp) {
 			g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp);
 			buf[sizeof(buf)-1] = '\0';
@@ -5162,29 +5211,18 @@ static const gchar *tag_to_html_start(Gt
 		}
 	} else if (strncmp(name, "FORECOLOR ", 10) == 0) {
 		g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]);
-
-		g_free(name);
-
 		return buf;
 	} else if (strncmp(name, "BACKCOLOR ", 10) == 0) {
 		g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]);
-		g_free(name);
-
 		return buf;
 	} else if (strncmp(name, "BACKGROUND ", 10) == 0) {
 		g_snprintf(buf, sizeof(buf), "<body bgcolor=\"%s\">", &name[11]);
-		g_free(name);
-
 		return buf;
 	} else if (strncmp(name, "FONT FACE ", 10) == 0) {
 		g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]);
-		g_free(name);
-
 		return buf;
 	} else if (strncmp(name, "FONT SIZE ", 10) == 0) {
 		g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]);
-		g_free(name);
-
 		return buf;
 	} else {
 		char *str = buf;
@@ -5247,7 +5285,6 @@ static const gchar *tag_to_html_start(Gt
 		}
 
 		g_snprintf(str, sizeof(buf) - (str - buf), "'>");
-		g_free(name);
 
 		return (empty ? "" : buf);
 	}
@@ -5255,40 +5292,30 @@ static const gchar *tag_to_html_end(GtkT
 
 static const gchar *tag_to_html_end(GtkTextTag *tag)
 {
-	gchar *name;
+	const gchar *name;
 
+	name = tag->name;
 	g_return_val_if_fail(name != NULL, "");
-	g_object_get(G_OBJECT(tag), "name", &name, NULL);
 
 	if (strcmp(name, "BOLD") == 0) {
-		g_free(name);
 		return "</b>";
 	} else if (strcmp(name, "ITALICS") == 0) {
-		g_free(name);
 		return "</i>";
 	} else if (strcmp(name, "UNDERLINE") == 0) {
-		g_free(name);
 		return "</u>";
 	} else if (strcmp(name, "STRIKE") == 0) {
-		g_free(name);
 		return "</s>";
 	} else if (strncmp(name, "LINK ", 5) == 0) {
-		g_free(name);
 		return "</a>";
 	} else if (strncmp(name, "FORECOLOR ", 10) == 0) {
-		g_free(name);
 		return "</font>";
 	} else if (strncmp(name, "BACKCOLOR ", 10) == 0) {
-		g_free(name);
 		return "</font>";
 	} else if (strncmp(name, "BACKGROUND ", 10) == 0) {
-		g_free(name);
 		return "</body>";
 	} else if (strncmp(name, "FONT FACE ", 10) == 0) {
-		g_free(name);
 		return "</font>";
 	} else if (strncmp(name, "FONT SIZE ", 10) == 0) {
-		g_free(name);
 		return "</font>";
 	} else {
 		const char *props[] = {"weight-set", "foreground-set", "background-set",
@@ -5301,8 +5328,6 @@ static const gchar *tag_to_html_end(GtkT
 				return "</span>";
 		}
 
-		g_free(name);
-
 		return "";
 	}
 }
============================================================
--- pidgin/gtkimhtml.h	4c0f77043b177d4ffe7c251776e62939e1c8322f
+++ pidgin/gtkimhtml.h	6ca6531f1c7563ea5eb7f80a943f4ebd4651cf46
@@ -50,9 +50,6 @@ typedef struct _GtkIMHtmlClass		GtkIMHtm
 
 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 _GtkIMHtmlFuncs		GtkIMHtm
 typedef struct _GtkIMHtmlHr			GtkIMHtmlHr;
 typedef struct _GtkIMHtmlFuncs		GtkIMHtmlFuncs;
 
-/**
- * @since 2.6.0
- */
 typedef struct _GtkIMHtmlLink       GtkIMHtmlLink;
 
 typedef enum {
@@ -81,7 +75,7 @@ typedef enum {
 	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;
@@ -154,12 +148,6 @@ struct _GtkIMHtmlClass {
 	GList *protocols; /* List of GtkIMHtmlProtocol's */
 };
 
-struct _GtkSmileyTree {
-	GString *values;
-	GtkSmileyTree **children;
-	GtkIMHtmlSmiley *image;
-};
-
 struct _GtkIMHtmlSmiley {
 	gchar *smile;
 	gchar *file;
@@ -169,40 +157,10 @@ struct _GtkIMHtmlSmiley {
 	GSList *anchors;
 	GtkIMHtmlSmileyFlags flags;
 	GtkIMHtml *imhtml;
-	gpointer data;       /** @since 2.6.0 */
-	gsize datasize;      /** @since 2.6.0 */
+	gpointer data;
+	gsize datasize;
 };
 
-struct _GtkIMHtmlScalable {
-	void (*scale)(struct _GtkIMHtmlScalable *, int, int);
-	void (*add_to)(struct _GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *);
-	void (*free)(struct _GtkIMHtmlScalable *);
-};
-
-struct _GtkIMHtmlImage {
-	GtkIMHtmlScalable scalable;
-	GtkImage *image; /**< Contains the scaled version of this pixbuf. */
-	GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */
-	GtkTextMark *mark;
-	gchar *filename;
-	int width;
-	int height;
-	int id;
-	GtkWidget *filesel;
-};
-
-struct _GtkIMHtmlAnimation {
-	GtkIMHtmlImage imhtmlimage;
-	GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */
-	GdkPixbufAnimationIter *iter;
-	guint timer;
-};
-
-struct _GtkIMHtmlHr {
-	GtkIMHtmlScalable scalable;
-	GtkWidget *sep;
-};
-
 typedef enum {
 	GTK_IMHTML_NO_COLOURS          = 1 << 0,
 	GTK_IMHTML_NO_FONTS            = 1 << 1,
@@ -419,73 +377,6 @@ GtkIMHtmlScalable *gtk_imhtml_scalable_n
 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.
@@ -836,8 +727,6 @@ char *gtk_imhtml_get_text(GtkIMHtml *imh
  *
  * @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);
 
@@ -850,7 +739,6 @@ void gtk_imhtml_setup_entry(GtkIMHtml *i
  * @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);
@@ -859,8 +747,6 @@ GtkIMHtmlSmiley *gtk_imhtml_smiley_creat
  * Reload the image data for the smiley.
  *
  * @param smiley   The smiley to reload
- *
- * @since 2.5.0
  */
 void gtk_imhtml_smiley_reload(GtkIMHtmlSmiley *smiley);
 
@@ -868,8 +754,6 @@ void gtk_imhtml_smiley_reload(GtkIMHtmlS
  * Destroy a GtkIMHtmlSmiley.
  *
  * @param smiley   The smiley to destroy
- *
- * @since 2.5.0
  */
 void gtk_imhtml_smiley_destroy(GtkIMHtmlSmiley *smiley);
 
@@ -888,8 +772,6 @@ void gtk_imhtml_smiley_destroy(GtkIMHtml
  *                      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),
@@ -901,8 +783,6 @@ gboolean gtk_imhtml_class_register_proto
  * @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);
 
@@ -912,8 +792,6 @@ const char *gtk_imhtml_link_get_url(GtkI
  * @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);
 
@@ -924,8 +802,6 @@ const GtkTextTag *gtk_imhtml_link_get_te
  * @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);
 
============================================================
--- libpurple/protocols/Makefile.am	a1ab1fb5f8aec812d7956d21ec8c99b5242030c2
+++ libpurple/protocols/Makefile.am	6e607fb32c9aa449718de1200aee297944bcb3b7
@@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw
 EXTRA_DIST = Makefile.mingw
 
-DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc 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)
============================================================
--- libpurple/protocols/irc/irc.c	2711e8001a672aebc7b00a5e18a167ff0a4372f6
+++ libpurple/protocols/irc/irc.c	8ae06611592ef145d1f0bc5f2825d24fb7a76c2c
@@ -70,11 +70,11 @@ static void irc_view_motd(PurplePluginAc
 	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
 
 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);
 	}
@@ -356,7 +356,7 @@ static void irc_login(PurpleAccount *acc
 	const char *username = purple_account_get_username(account);
 
 	gc = purple_account_get_connection(account);
-	gc->flags |= PURPLE_CONNECTION_NO_NEWLINES;
+	purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_NEWLINES);
 
 	if (strpbrk(username, " \t\v\r\n") != NULL) {
 		purple_connection_error (gc,
@@ -365,7 +365,8 @@ static void irc_login(PurpleAccount *acc
 		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);
@@ -415,7 +416,7 @@ static gboolean do_login(PurpleConnectio
 	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,7 +486,7 @@ static void irc_login_cb(gpointer data, 
 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"),
@@ -499,7 +500,7 @@ static void irc_login_cb(gpointer data, 
 	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 @@ irc_ssl_connect_failure(PurpleSslConnect
 		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 *
 
 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 @@ static void irc_close(PurpleConnection *
 	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 
 
 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(PurpleConnectio
 
 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 @@ static void irc_set_status(PurpleAccount
 	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_set_status(PurpleAccount
 	}
 }
 
-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(PurpleConne
 
 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 *
 
 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 @@ static void irc_input_cb_ssl(gpointer da
 {
 
 	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)) {
@@ -716,7 +720,7 @@ static void irc_input_cb(gpointer data, 
 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) {
@@ -746,7 +750,7 @@ static void irc_chat_join (PurpleConnect
 
 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(PurpleConnec
 
 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 (PurpleConnec
 
 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(PurpleConnectio
 
 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 @@ static int irc_chat_send(PurpleConnectio
 	}
 #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 @@ static void irc_chat_set_topic(PurpleCon
 	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 @@ static PurpleRoomlist *irc_roomlist_get_
 	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(PurpleRo
 
 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(PurpleConnecti
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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) {
============================================================
--- libpurple/protocols/jabber/jabber.c	1273648d9cc2187cae93e7b66a7aad403236d818
+++ libpurple/protocols/jabber/jabber.c	6af9f2854e3229d956ff808b18167eb71dfd48fc
@@ -440,7 +440,7 @@ static gboolean do_jabber_send_raw(Jabbe
 		 * we're disconnecting, don't generate (possibly another) error that
 		 * (for some UIs) would mask the first.
 		 */
-		if (!account->disconnecting) {
+		if (!purple_account_is_disconnecting(account)) {
 			gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
 					g_strerror(errno));
 			purple_connection_error(js->gc,
@@ -616,7 +616,7 @@ static gboolean jabber_keepalive_timeout
 
 static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					_("Ping timed out"));
 	js->keepalive_timeout = 0;
@@ -642,7 +642,7 @@ jabber_recv_cb_ssl(gpointer data, Purple
 		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 @@ jabber_recv_cb_ssl(gpointer data, Purple
 	}
 
 	while((len = purple_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) {
-		gc->last_received = time(NULL);
+		purple_connection_update_last_received(gc);
 		buf[len] = '\0';
 		purple_debug_info("jabber", "Recv (ssl)(%d): %s\n", len, buf);
 		jabber_parser_process(js, buf, len);
@@ -687,7 +687,7 @@ jabber_recv_cb(gpointer data, gint sourc
 	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;
@@ -747,7 +747,7 @@ jabber_login_callback_ssl(gpointer data,
 		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);
@@ -813,7 +813,7 @@ jabber_login_callback(gpointer data, gin
 			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_login_callback(gpointer data, gin
 		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 @@ jabber_ssl_connect_failure(PurpleSslConn
 	/* 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)
 
 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;
@@ -928,7 +928,8 @@ jabber_stream_new(PurpleAccount *account
 	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;
 
@@ -1073,7 +1074,7 @@ jabber_stream_connect(JabberStream *js)
 		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 @@ jabber_login(PurpleAccount *account)
 	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;
@@ -1144,8 +1144,7 @@ jabber_registration_result_cb(JabberStre
 		if(js->registration) {
 			buf = g_strdup_printf(_("Registration of %s@%s successful"),
 					js->user->node, js->user->domain);
-			if(account->registration_cb)
-				(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+			purple_account_register_completed(account, TRUE);
 		} else {
 			g_return_if_fail(to != NULL);
 			buf = g_strdup_printf(_("Registration to %s successful"),
@@ -1163,8 +1162,7 @@ jabber_registration_result_cb(JabberStre
 		purple_notify_error(NULL, _("Registration Failed"),
 				_("Registration Failed"), msg);
 		g_free(msg);
-		if(account->registration_cb)
-			(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+		purple_account_register_completed(account, FALSE);
 	}
 	g_free(to);
 	if(js->registration)
@@ -1264,7 +1262,7 @@ jabber_register_cb(JabberRegisterCBData 
 					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 +1271,7 @@ jabber_register_cb(JabberRegisterCBData 
 		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);
 	}
 
@@ -1288,8 +1286,7 @@ jabber_register_cancel_cb(JabberRegister
 {
 	PurpleAccount *account = purple_connection_get_account(cbdata->js->gc);
 	if(account && cbdata->js->registration) {
-		if(account->registration_cb)
-			(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+		purple_account_register_completed(account, FALSE);
 		jabber_connection_schedule_close(cbdata->js);
 	}
 	g_free(cbdata->who);
@@ -1358,8 +1355,7 @@ void jabber_register_parse(JabberStream 
 		if(js->registration) {
 			purple_notify_error(NULL, _("Already Registered"),
 								_("Already Registered"), NULL);
-			if(account->registration_cb)
-				(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+			purple_account_register_completed(account, FALSE);
 			jabber_connection_schedule_close(js);
 			return;
 		}
@@ -1380,8 +1376,8 @@ void jabber_register_parse(JabberStream 
 
 				if(js->registration) {
 					js->gc->wants_to_die = TRUE;
-					if(account->registration_cb) /* succeeded, but we have no login info */
-						(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+					/* succeeded, but we have no login info */
+					purple_account_register_completed(account, TRUE);
 					jabber_connection_schedule_close(js);
 				}
 				return;
@@ -1422,7 +1418,7 @@ void jabber_register_parse(JabberStream 
 	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 +1552,17 @@ void jabber_unregister_account(PurpleAcc
 	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 +1594,15 @@ void jabber_close(PurpleConnection *gc)
 		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 +1724,7 @@ void jabber_close(PurpleConnection *gc)
 
 	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 +1778,7 @@ void jabber_idle_set(PurpleConnection *g
 
 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 +1869,7 @@ static void jabber_blocklist_parse(Jabbe
 		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 +2130,7 @@ const char* jabber_list_emblem(PurpleBud
 	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 +2171,8 @@ char *jabber_status_text(PurpleBuddy *b)
 	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"));
@@ -2250,6 +2247,7 @@ void jabber_tooltip_text(PurpleBuddy *b,
 	JabberBuddy *jb;
 	PurpleAccount *account;
 	PurpleConnection *gc;
+	JabberStream *js;
 
 	g_return_if_fail(b != NULL);
 
@@ -2258,10 +2256,12 @@ void jabber_tooltip_text(PurpleBuddy *b,
 
 	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;
 		PurplePresence *presence = purple_buddy_get_presence(b);
@@ -2484,7 +2484,7 @@ jabber_password_change_result_cb(JabberS
 		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 +2531,7 @@ static void jabber_password_change(Purpl
 {
 
 	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 +2563,7 @@ GList *jabber_actions(PurplePlugin *plug
 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 +2634,7 @@ void jabber_convo_closed(PurpleConnectio
 
 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 +2739,8 @@ char *jabber_parse_error(JabberStream *j
 		} 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 +2997,7 @@ static PurpleCmdRet jabber_cmd_chat_invi
 	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 +3044,7 @@ static PurpleCmdRet jabber_cmd_chat_join
 	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 +3078,7 @@ static PurpleCmdRet jabber_cmd_chat_msg(
 
 	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 +3159,14 @@ static PurpleCmdRet jabber_cmd_buzz(Purp
 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 +3179,7 @@ static PurpleCmdRet jabber_cmd_buzz(Purp
 		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 +3207,7 @@ gboolean jabber_send_attention(PurpleCon
 
 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 +3290,8 @@ jabber_initiate_media(PurpleAccount *acc
 		      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 +3302,6 @@ jabber_initiate_media(PurpleAccount *acc
 		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 +3432,8 @@ PurpleMediaCaps jabber_get_media_caps(Pu
 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 +3521,7 @@ gboolean jabber_can_receive_file(PurpleC
 
 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 +3571,8 @@ jabber_cmd_mood(PurpleConversation *conv
 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 +3756,7 @@ jabber_ipc_contact_has_feature(PurpleAcc
 
 	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)) ||
============================================================
--- libpurple/protocols/jabber/jabber.h	4886d45526932fb189a96ac9ce60e4268952b8de
+++ libpurple/protocols/jabber/jabber.h	452f6ce82096071496c24639ffa4a7f41c0964bc
@@ -99,6 +99,7 @@ struct _JabberStream
 struct _JabberStream
 {
 	int fd;
+	guint inpa;
 
 	PurpleSrvTxtQueryData *srv_query_data;
 
============================================================
--- libpurple/protocols/jabber/jutil.c	9fc4123aa40107476fdf19d2066be9592bd4c532
+++ libpurple/protocols/jabber/jutil.c	fb2f14727f8fb8c945f41c8faa6ee1bd6447f0fa
@@ -583,11 +583,16 @@ const char *jabber_normalize(const Purpl
 
 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;
============================================================
--- libpurple/protocols/msn/msn.c	8ba865c149b31ccdbcc97a49bf8f6bf24dfc40ba
+++ libpurple/protocols/msn/msn.c	e54e15d2ba9a286511cc469133e98d2aa15a27ec
@@ -119,7 +119,7 @@ msn_send_attention(PurpleConnection *gc,
 	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 @@ msn_set_prp(PurpleConnection *gc, const 
 	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 @@ send_to_mobile(PurpleConnection *gc, con
 	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 @@ msn_show_set_home_phone(PurplePluginActi
 	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 @@ msn_show_set_work_phone(PurplePluginActi
 	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 @@ msn_show_set_mobile_phone(PurplePluginAc
 	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 @@ msn_show_blocked_text(PurplePluginAction
 	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 @@ msn_show_hotmail_inbox(PurplePluginActio
 	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 @@ msn_send_privacy(PurpleConnection *gc)
 	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 @@ initiate_chat_cb(PurpleBlistNode *node, 
 	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 @@ t_msn_xfer_cancel_send(PurpleXfer *xfer)
 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 @@ msn_new_xfer(PurpleConnection *gc, const
 	MsnSession *session;
 	PurpleXfer *xfer;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
-	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+	xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
 
 	g_return_val_if_fail(xfer != NULL, NULL);
 
-	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 @@ msn_can_receive_file(PurpleConnection *g
 	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) {
@@ -1101,8 +1101,6 @@ msn_tooltip_text(PurpleBuddy *buddy, Pur
 		}
 
 		if (currentmedia) {
-			/* 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, mediatype, currentmedia);
 			g_free(currentmedia);
 		}
@@ -1129,23 +1127,17 @@ msn_tooltip_text(PurpleBuddy *buddy, Pur
 
 		phone = msn_user_get_home_phone(user);
 		if (phone != 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, _("Home Phone Number"), phone);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), phone);
 		}
 
 		phone = msn_user_get_work_phone(user);
 		if (phone != 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, _("Work Phone Number"), phone);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), phone);
 		}
 
 		phone = msn_user_get_mobile_phone(user);
 		if (phone != 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, _("Mobile Phone Number"), phone);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), phone);
 		}
 	}
 }
@@ -1224,7 +1216,7 @@ msn_actions(PurplePlugin *plugin, gpoint
 	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);
@@ -1361,9 +1353,10 @@ msn_login(PurpleAccount *account)
 
 	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);
 
@@ -1395,13 +1388,13 @@ msn_close(PurpleConnection *gc)
 {
 	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
@@ -1461,7 +1454,7 @@ static void msn_emoticon_destroy(MsnEmot
 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);
 }
@@ -1534,7 +1527,7 @@ msn_send_im(PurpleConnection *gc, const 
 			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;
@@ -1547,7 +1540,7 @@ msn_send_im(PurpleConnection *gc, const 
 	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)) {
@@ -1651,7 +1644,7 @@ msn_send_im(PurpleConnection *gc, const 
 
 		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);
@@ -1674,7 +1667,7 @@ msn_send_typing(PurpleConnection *gc, co
 	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)"
@@ -1723,7 +1716,7 @@ msn_set_status(PurpleAccount *account, P
 
 	if (gc != NULL)
 	{
-		session = gc->proto_data;
+		session = purple_connection_get_protocol_data(gc);
 		msn_change_status(session);
 	}
 }
@@ -1733,7 +1726,7 @@ msn_set_idle(PurpleConnection *gc, int i
 {
 	MsnSession *session;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	msn_change_status(session);
 }
@@ -1863,7 +1856,7 @@ msn_rem_buddy(PurpleConnection *gc, Purp
 	MsnSession *session;
 	MsnUserList *userlist;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	if (!session->logged_in)
@@ -1880,7 +1873,7 @@ msn_add_permit(PurpleConnection *gc, con
 	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);
 
@@ -1908,7 +1901,7 @@ msn_add_deny(PurpleConnection *gc, const
 	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);
 
@@ -1935,7 +1928,7 @@ msn_rem_permit(PurpleConnection *gc, con
 	MsnUserList *userlist;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	if (!session->logged_in)
@@ -1958,7 +1951,7 @@ msn_rem_deny(PurpleConnection *gc, const
 	MsnUserList *userlist;
 	MsnUser *user;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 	userlist = session->userlist;
 
 	if (!session->logged_in)
@@ -1987,7 +1980,7 @@ msn_chat_invite(PurpleConnection *gc, in
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_session_find_swboard_with_id(session, id);
 
@@ -2012,7 +2005,7 @@ msn_chat_leave(PurpleConnection *gc, int
 	MsnSwitchBoard *swboard;
 	PurpleConversation *conv;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_session_find_swboard_with_id(session, id);
 
@@ -2049,7 +2042,7 @@ msn_chat_send(PurpleConnection *gc, int 
 	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);
 
@@ -2115,7 +2108,7 @@ msn_keepalive(PurpleConnection *gc)
 	MsnSession *session;
 	MsnTransaction *trans;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	if (!session->http_method)
 	{
@@ -2133,7 +2126,7 @@ static void msn_alias_buddy(PurpleConnec
 {
 	MsnSession *session;
 
-	session = pc->proto_data;
+	session = purple_connection_get_protocol_data(pc);
 
 	msn_update_contact(session, name, MSN_UPDATE_ALIAS, alias);
 }
@@ -2145,7 +2138,7 @@ msn_group_buddy(PurpleConnection *gc, co
 	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);
@@ -2158,7 +2151,7 @@ msn_rename_group(PurpleConnection *gc, c
 	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);
@@ -2182,7 +2175,7 @@ msn_convo_closed(PurpleConnection *gc, c
 	MsnSwitchBoard *swboard;
 	PurpleConversation *conv;
 
-	session = gc->proto_data;
+	session = purple_connection_get_protocol_data(gc);
 
 	swboard = msn_session_find_swboard(session, who);
 
@@ -2218,7 +2211,7 @@ msn_set_buddy_icon(PurpleConnection *gc,
 	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);
@@ -2232,7 +2225,7 @@ msn_remove_group(PurpleConnection *gc, P
 	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);
@@ -2750,7 +2743,7 @@ msn_got_info(PurpleUtilFetchUrlData *url
 	/* 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);
@@ -2849,7 +2842,7 @@ msn_get_info(PurpleConnection *gc, const
 
 	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);
@@ -2938,6 +2931,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),	/* struct_size */
 	OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE,
 	NULL,                               /* user_splits */
 	NULL,                               /* protocol_options */
@@ -2959,7 +2953,7 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
@@ -2978,7 +2972,6 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
@@ -3003,15 +2996,12 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- libpurple/protocols/oscar/oscar.c	f88b38ac26f0cdb2d3bcd81cd3627c784e516579
+++ libpurple/protocols/oscar/oscar.c	9f34f275fd267361362b7d748c45f417935c6d67
@@ -655,6 +655,7 @@ oscar_login(PurpleAccount *account)
 	GList *sorted_handlers;
 	GList *cur;
 	GString *msg = g_string_new("");
+	PurpleConnectionFlags flags;
 
 	gc = purple_account_get_connection(account);
 	od = oscar_data_new();
@@ -740,18 +741,20 @@ oscar_login(PurpleAccount *account)
 		return;
 	}
 
-	gc->flags |= PURPLE_CONNECTION_HTML;
+	flags = PURPLE_CONNECTION_HTML;
 	if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) {
 		od->icq = TRUE;
 	} else {
-		gc->flags |= PURPLE_CONNECTION_AUTO_RESP;
+		flags |= PURPLE_CONNECTION_AUTO_RESP;
 	}
 
 	/* Set this flag based on the protocol_id rather than the username,
 	   because that is what's tied to the get_moods prpl callback. */
 	if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq"))
-		gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS;
+		flags |= PURPLE_CONNECTION_SUPPORT_MOODS;
 
+	purple_connection_set_flags(gc, flags);
+
 	od->default_port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT);
 
 	encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
@@ -1000,7 +1003,7 @@ static int purple_memrequest(OscarData *
 	pos->len = len;
 	pos->modname = g_strdup(modname);
 
-	if (purple_proxy_connect(pos->gc, pos->gc->account, "pidgin.im", 80,
+	if (purple_proxy_connect(pos->gc, purple_connection_get_account(pos->gc), "pidgin.im", 80,
 			straight_to_hell, pos) == NULL)
 	{
 		char buf[256];
@@ -1547,7 +1550,7 @@ static int purple_parse_offgoing(OscarDa
 
 	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;
 }
@@ -2816,7 +2819,7 @@ static int purple_parse_locaterights(Osc
 	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;
@@ -3176,9 +3179,9 @@ oscar_send_typing(PurpleConnection *gc, 
 	else {
 		/* Don't send if this turkey is in our deny list */
 		GSList *list;
-		for (list=gc->account->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next);
+		for (list=purple_connection_get_account(gc)->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next);
 		if (!list) {
-			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(gc->account, name));
+			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), name));
 			if (bi && bi->typingnot) {
 				if (state == PURPLE_TYPING)
 					aim_im_sendmtn(od, 0x0001, name, 0x0002);
@@ -3478,13 +3481,11 @@ oscar_get_extended_status(PurpleConnecti
 static guint32
 oscar_get_extended_status(PurpleConnection *gc)
 {
-	OscarData *od;
 	PurpleAccount *account;
 	PurpleStatus *status;
 	const gchar *status_id;
 	guint32 data = 0x00000000;
 
-	od = purple_connection_get_protocol_data(gc);
 	account = purple_connection_get_account(gc);
 	status = purple_account_get_active_status(account);
 	status_id = purple_status_get_id(status);
@@ -3806,7 +3807,7 @@ void oscar_rename_group(PurpleConnection
 			}
 
 			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);
@@ -4032,9 +4033,9 @@ static int purple_ssi_parselist(OscarDat
 					gname = groupitem ? groupitem->name : NULL;
 					gname_utf8 = oscar_utf8_try_convert(account, od, gname);
 
-					g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans"));
+					g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies"));
 					if (g == NULL) {
-						g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+						g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies"));
 						purple_blist_add_group(g, NULL);
 					}
 
@@ -4108,11 +4109,11 @@ static int purple_ssi_parselist(OscarDat
 				 */
 				if (!od->icq && curitem->data) {
 					guint8 perm_deny = aim_ssi_getpermdeny(&od->ssi.local);
-					if (perm_deny != 0 && perm_deny != account->perm_deny)
+					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;
@@ -4258,13 +4259,13 @@ purple_ssi_parseaddmod(OscarData *od, Fl
 		 */
 		b = purple_buddy_new(account, name, alias_utf8);
 
-		if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
-			g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+		if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies")))) {
+			g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies"));
 			purple_blist_add_group(g, NULL);
 		}
 
 		purple_debug_info("oscar",
-				   "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans"));
+				   "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Buddies"));
 		purple_blist_add_buddy(b, NULL, g, NULL);
 
 		/* Mobile users should always be online */
@@ -4616,7 +4617,6 @@ const char *oscar_list_emblem(PurpleBudd
 	PurpleAccount *account = NULL;
 	PurplePresence *presence;
 	PurpleStatus *status;
-	const char *status_id;
 	aim_userinfo_t *userinfo = NULL;
 	const char *name;
 
@@ -4631,7 +4631,6 @@ const char *oscar_list_emblem(PurpleBudd
 
 	presence = purple_buddy_get_presence(b);
 	status = purple_presence_get_active_status(presence);
-	status_id = purple_status_get_id(status);
 
 	if (purple_presence_is_online(presence) == FALSE) {
 		char *gname;
@@ -4690,7 +4689,6 @@ char *oscar_status_text(PurpleBuddy *b)
 	OscarData *od;
 	const PurplePresence *presence;
 	const PurpleStatus *status;
-	const char *id;
 	const char *message;
 	gchar *ret = NULL;
 
@@ -4699,7 +4697,6 @@ char *oscar_status_text(PurpleBuddy *b)
 	od = purple_connection_get_protocol_data(gc);
 	presence = purple_buddy_get_presence(b);
 	status = purple_presence_get_active_status(presence);
-	id = purple_status_get_id(status);
 
 	if ((od != NULL) && !purple_presence_is_online(presence))
 	{
@@ -4741,7 +4738,7 @@ void oscar_set_aim_permdeny(PurpleConnec
 	 * 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) {
@@ -5040,7 +5037,7 @@ oscar_close_directim(gpointer object, gp
 	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)
@@ -5476,7 +5473,7 @@ oscar_new_xfer(PurpleConnection *gc, con
 		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;
============================================================
--- libpurple/protocols/zephyr/ZRetSubs.c	b6c6c255d2f68f39352d607b5f0f771b913016f6
+++ libpurple/protocols/zephyr/ZRetSubs.c	bf94a5ad9f51ef6496f629dc8aada60b8b8df160
@@ -132,6 +132,11 @@ static Code_t Z_RetSubs(notice, nsubs, a
 
 		__subscriptions_num = __subscriptions_num / 3;
 
+		if (!__subscriptions_num) {
+			ZFreeNotice(&retnotice);
+			continue;
+		}
+
 		__subscriptions_list = (ZSubscription_t *)
 			malloc((unsigned)(__subscriptions_num*
 					  sizeof(ZSubscription_t)));
============================================================
--- libpurple/protocols/zephyr/zephyr.c	c5a870d8b26f8fef962ffd6d41fa2cb4310e8116
+++ libpurple/protocols/zephyr/zephyr.c	a3f40fb592600b8e01f75bf7c12226d4c9b9194a
@@ -347,7 +347,7 @@ static gchar *zephyr_recv_convert(Purple
 {
 	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(PurpleConnect
 
 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 @@ static void handle_message(PurpleConnect
 			if (ZParseLocations(&notice, NULL, &nlocs, &user) != ZERR_NONE)
 				return;
 
-			if ((b = purple_find_buddy(gc->account, user)) == NULL) {
+			if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) {
 				char* stripped_user = zephyr_strip_local_realm(zephyr,user);
-				b = purple_find_buddy(gc->account,stripped_user);
+				b = purple_find_buddy(purple_connection_get_account(gc),stripped_user);
 				g_free(stripped_user);
 			}
 
@@ -815,9 +815,9 @@ static void handle_message(PurpleConnect
 				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);
@@ -872,7 +872,7 @@ static void handle_message(PurpleConnect
 		} 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) {
@@ -900,7 +900,7 @@ static void handle_message(PurpleConnect
 			}
 
 			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
@@ -1109,7 +1109,7 @@ static gint check_notify_tzc(gpointer da
 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;
@@ -1156,9 +1156,9 @@ static gint check_notify_tzc(gpointer da
 				gchar *locval;
 				user = tree_child(find_node(newparsetree,"user"),2)->contents;
 
-				if ((b = purple_find_buddy(gc->account, user)) == NULL) {
+				if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) {
 					gchar *stripped_user = zephyr_strip_local_realm(zephyr,user);
-					b = purple_find_buddy(gc->account, stripped_user);
+					b = purple_find_buddy(purple_connection_get_account(gc), stripped_user);
 					g_free(stripped_user);
 				}
 				locations = find_node(newparsetree,"locations");
@@ -1200,9 +1200,9 @@ static gint check_notify_tzc(gpointer da
 					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)) {
@@ -1265,7 +1265,7 @@ static gint check_loc(gpointer data)
 	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;
@@ -1296,7 +1296,7 @@ static gint check_loc(gpointer data)
 	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)) {
@@ -1521,11 +1521,11 @@ static void process_anyone(PurpleConnect
 		while (fgets(buff, BUFSIZ, fd)) {
 			strip_comments(buff);
 			if (buff[0]) {
-				if (!(b = purple_find_buddy(gc->account, buff))) {
+				if (!(b = purple_find_buddy(purple_connection_get_account(gc), buff))) {
 					char *stripped_user = zephyr_strip_local_realm(zephyr,buff);
 					purple_debug_info("zephyr","stripped_user %s\n",stripped_user);
-					if (!(b = purple_find_buddy(gc->account,stripped_user))){
-						b = purple_buddy_new(gc->account, stripped_user, NULL);
+					if (!(b = purple_find_buddy(purple_connection_get_account(gc),stripped_user))){
+						b = purple_buddy_new(purple_connection_get_account(gc), stripped_user, NULL);
 						purple_blist_add_buddy(b, NULL, g, NULL);
 					}
 					g_free(stripped_user);
@@ -1564,28 +1564,29 @@ static void zephyr_login(PurpleAccount *
 	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 */
@@ -1606,7 +1607,7 @@ static void zephyr_login(PurpleAccount *
 		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);
 			}
@@ -1778,7 +1779,7 @@ static void zephyr_login(PurpleAccount *
 						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";
 							}
@@ -1815,7 +1816,7 @@ static void zephyr_login(PurpleAccount *
 		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();
 		}
@@ -1841,7 +1842,7 @@ static void zephyr_login(PurpleAccount *
 	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;
 	}
@@ -1961,7 +1962,7 @@ static void zephyr_close(PurpleConnectio
 {
 	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;
@@ -1971,10 +1972,10 @@ static void zephyr_close(PurpleConnectio
 	}
 	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;
@@ -2036,7 +2037,7 @@ static int zephyr_chat_send(PurpleConnec
 	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)
@@ -2046,7 +2047,7 @@ static int zephyr_chat_send(PurpleConnec
 	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)))
@@ -2065,7 +2066,7 @@ static int zephyr_send_im(PurpleConnecti
 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 {
@@ -2234,7 +2235,7 @@ static const char *zephyr_normalize(cons
 	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);
@@ -2250,7 +2251,7 @@ static void zephyr_zloc(PurpleConnection
 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)) {
@@ -2277,7 +2278,8 @@ static void zephyr_set_status(PurpleAcco
 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) {
@@ -2411,7 +2413,7 @@ static void zephyr_join_chat(PurpleConne
 	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");
@@ -2474,7 +2476,7 @@ static void zephyr_chat_leave(PurpleConn
 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) {
@@ -2524,7 +2526,7 @@ static unsigned int zephyr_send_typing(P
 
 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;
 
@@ -2566,7 +2568,7 @@ static void zephyr_chat_set_topic(Purple
 	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);
@@ -2574,7 +2576,7 @@ static void zephyr_chat_set_topic(Purple
 	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);
@@ -2589,7 +2591,8 @@ static PurpleCmdRet zephyr_purple_cmd_ms
 				      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
@@ -2607,7 +2610,7 @@ static PurpleCmdRet zephyr_purple_cmd_zl
 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;
 }
 
@@ -2619,9 +2622,8 @@ static PurpleCmdRet zephyr_purple_cmd_in
 	 * 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;
 }
 
@@ -2633,7 +2635,7 @@ static PurpleCmdRet zephyr_purple_cmd_jo
 	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;
 }
 
@@ -2641,7 +2643,8 @@ static PurpleCmdRet zephyr_purple_cmd_zi
 				     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
@@ -2652,7 +2655,8 @@ static PurpleCmdRet zephyr_purple_cmd_zc
 				      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
@@ -2663,7 +2667,8 @@ static PurpleCmdRet zephyr_purple_cmd_zc
 				       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
@@ -2674,7 +2679,8 @@ static PurpleCmdRet zephyr_purple_cmd_zi
 				      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
@@ -2685,7 +2691,8 @@ static PurpleCmdRet zephyr_purple_cmd_zc
 				     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
@@ -2766,7 +2773,7 @@ static int zephyr_resubscribe(PurpleConn
 {
 	/* 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) {
@@ -2791,7 +2798,7 @@ static void zephyr_action_get_subs_from_
 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;
@@ -2845,6 +2852,7 @@ static PurplePluginProtocolInfo prpl_inf
 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 */
@@ -2885,7 +2893,6 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
@@ -2911,15 +2918,12 @@ static PurplePluginProtocolInfo prpl_inf
 	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 = {
============================================================
--- configure.ac	302b4849879e431ea4ba7abbc11ca1b04b84369d
+++ configure.ac	146e991fb67000dc69168ef834a34418d93738d8
@@ -202,6 +202,12 @@ AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHEC
 dnl FreeBSD doesn't have libdl, dlopen is provided by libc
 AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")])
 
+dnl Windows and Haiku do not use libm for the math functions, they are part
+dnl of the C library
+AC_SEARCH_LIBS([ceil], [m], [], [
+  AC_MSG_ERROR([unable to find the ceil() function])
+])
+
 AC_MSG_CHECKING(for fileno())
 AC_RUN_IFELSE([AC_LANG_SOURCE([[
 #include <stdio.h>
@@ -401,6 +407,10 @@ AC_ARG_ENABLE(gestures,
 	[AC_HELP_STRING([--disable-gestures],
 		[compile without the gestures plugin])],
 	enable_gestures="$enableval", enable_gestures="yes")
+AC_ARG_ENABLE(gcr,
+	[AC_HELP_STRING([--enable-gcr],
+		[compile with GCR certificate widgets])],
+	enable_gcr="$enableval", enable_gcr="no")
 
 AC_PATH_XTRA
 # We can't assume that $x_libraries will be set, because autoconf does not
@@ -418,11 +428,11 @@ if test "x$enable_gtkui" = "xyes" ; then
 fi
 
 if test "x$enable_gtkui" = "xyes" ; then
-	PKG_CHECK_MODULES(GTK, [gtk+-3.0 >= 3.0.0], , [
+	PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.10.0], , [
 		AC_MSG_RESULT(no)
 		AC_MSG_ERROR([
 
-You must have GTK+ 2.91.5 or newer development headers installed to compile
+You must have GTK+ 2.10.0 or newer development headers installed to compile
 Pidgin.  If you want to build only Finch then specify --disable-gtkui when
 running configure.
 ])])
@@ -434,6 +444,16 @@ running configure.
 	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 #######################################################################
@@ -545,8 +565,6 @@ Use --disable-sm if you do not need sess
 	dnl #######################################################################
 	dnl # Check for GtkSpell
 	dnl #######################################################################
-	dnl GtkSpell is not GTK+3 compatible yet
-	enable_gtkspell="no"
 	if test "x$enable_gtkspell" = "xyes" ; then
 		PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, , [
 			AC_MSG_RESULT(no)
@@ -606,9 +624,26 @@ Use --disable-cap if you do not need the
 ])
 			fi])
 	fi
-        
 
+	dnl #######################################################################
+	dnl # Check for GCR for its certificate widgets
+	dnl #######################################################################
+	if test "x$enable_gcr" = "xyes"; then
+		PKG_CHECK_MODULES(GCR, gcr-0, [
+			AC_DEFINE(ENABLE_GCR, 1, [Define to 1 if GCR is found.])], [
+			AC_MSG_RESULT(no)
+			enable_gcr="no"
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
+GCR development headers not found.
+Use --disable-gcr if you do not need GCR certificate widgets.
+])
+			fi])
+	fi
+
+
 else # GTK
+	enable_gcr=no
 	enable_cap=no
 	enable_gevolution=no
 	enable_gtkspell=no
@@ -621,6 +656,7 @@ AM_CONDITIONAL(ENABLE_GESTURES, test "x$
 AM_CONDITIONAL(BUILD_GEVOLUTION, test "x$enable_gevolution" = "xyes")
 AM_CONDITIONAL(ENABLE_CAP, test "x$enable_cap" = "xyes")
 AM_CONDITIONAL(ENABLE_GESTURES, test "x$enable_gestures" = "xyes")
+AM_CONDITIONAL(ENABLE_GCR, test "x$enable_gcr" = "xyes")
 
 
 dnl #######################################################################
@@ -1072,7 +1108,7 @@ if test "x$STATIC_PRPLS" = "xall" ; then
 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//'`
@@ -1117,8 +1153,8 @@ for i in $STATIC_PRPLS ; do
 		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 ;;
@@ -1136,8 +1172,8 @@ AM_CONDITIONAL(STATIC_MSN, test "x$stati
 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")
@@ -1151,7 +1187,7 @@ if test "x$DYNAMIC_PRPLS" = "xall" ; the
 
 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//'`
@@ -1170,8 +1206,8 @@ for i in $DYNAMIC_PRPLS ; do
 		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 ;;
@@ -2496,6 +2532,7 @@ AC_CONFIG_FILES([Makefile
 		   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
@@ -2579,6 +2616,7 @@ echo Build with GtkSpell support... : $e
 echo Use X Session Management...... : $enable_sm
 echo Use startup notification...... : $enable_startup_notification
 echo Build with GtkSpell support... : $enable_gtkspell
+echo Build with GCR widgets........ : $enable_gcr
 echo
 echo Build with plugin support..... : $enable_plugins
 echo Build with Mono support....... : $enable_mono
============================================================
--- libpurple/protocols/gg/Makefile.am	6cbbf3fb73d1fdb01e5a3f67751765f7d9d55655
+++ libpurple/protocols/gg/Makefile.am	055399a717b226355a566bf0361871637cefec72
@@ -1,5 +1,7 @@ EXTRA_DIST = \
 EXTRA_DIST = \
 	Makefile.mingw \
+	win32-resolver.c \
+	win32-resolver.h \
 	lib/common.c \
 	lib/compat.h \
 	lib/COPYING \
@@ -61,13 +63,13 @@ INTGG_CFLAGS = -I$(top_srcdir)/libpurple
 	lib/sha1.c
 
 INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED -DUSE_INTERNAL_LIBGADU
+endif
 
 if USE_GNUTLS
 GADU_LIBS += $(GNUTLS_LIBS)
+GADU_CFLAGS += $(GNUTLS_CFLAGS)
 endif
 
-endif
-
 GGSOURCES = \
 	$(INTGGSOURCES) \
 	gg-utils.h \
============================================================
--- libpurple/protocols/gg/gg.c	b6b618b409796ef134a291cb0a34801a92fdfab6
+++ libpurple/protocols/gg/gg.c	97da098a6852b937c89a9359b8f6da860422c8a1
@@ -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(gpoi
 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 @@ static void ggp_token_request(PurpleConn
 	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(Pur
 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(Pur
 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(
 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 @@ static void ggp_callback_register_accoun
 					     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;
@@ -389,8 +391,8 @@ static void ggp_callback_register_accoun
 	purple_notify_info(NULL, _("New Gadu-Gadu Account Registered"),
 			 _("Registration completed successfully!"), NULL);
 
-	if(account->registration_cb)
-		(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+	purple_account_register_completed(account, TRUE);
+
 	/* TODO: the currently open Accounts Window will not be updated withthe
 	 * new username and etc, we need to somehow have it refresh at this
 	 * point
@@ -400,8 +402,7 @@ exit_err:
 	purple_account_disconnect(account);
 
 exit_err:
-	if(account->registration_cb)
-		(account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+	purple_account_register_completed(account, FALSE);
 
 	gg_register_free(h);
 	g_free(email);
@@ -415,10 +416,10 @@ static void ggp_callback_register_accoun
 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 +434,7 @@ static void ggp_register_user_dialog(Pur
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
 
-	GGPInfo *info = gc->proto_data;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	GGPToken *token = info->token;
 
 
@@ -483,7 +484,7 @@ static void ggp_callback_show_next(Purpl
 
 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 +521,7 @@ static void ggp_callback_find_buddies(Pu
 
 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 +617,137 @@ static void ggp_find_buddies(PurplePlugi
 		gc);
 }
 
-/* ----- CHANGE PASSWORD ------------------------------------------------ */
+/* ----- CHANGE PASSWORD ---------------------------------------------------- */
 
-static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields)
+typedef struct
 {
+	guint inpa;
+	struct gg_http *http_req;
+	gchar *new_password;
 	PurpleAccount *account;
-	GGPInfo *info = gc->proto_data;
+} ggp_change_passwd_request;
+
+static void ggp_callback_change_passwd_handler(gpointer _req, gint fd,
+	PurpleInputCondition cond)
+{
+	ggp_change_passwd_request *req = _req;
+	const char *messagesTitle =
+		_("Change password for the Gadu-Gadu account");
+
+	purple_input_remove(req->inpa);
+
+	if (gg_change_passwd_watch_fd(req->http_req) == -1 ||
+		req->http_req->state == GG_STATE_ERROR)
+		goto exit_error;
+
+	if (req->http_req->state != GG_STATE_DONE)
+	{
+		req->inpa = ggp_http_input_add(req->http_req,
+			ggp_callback_change_passwd_handler, req);
+		return;
+	}
+
+	if (req->http_req->data != NULL &&
+		((struct gg_pubdir*)req->http_req->data)->success == 1)
+	{
+		purple_account_set_password(req->account, req->new_password);
+		purple_notify_info(req->account, messagesTitle,
+			_("Password was changed successfully!"), NULL);
+		goto exit_cleanup;
+	}
+
+exit_error:
+	purple_notify_error(req->account, messagesTitle,
+		_("Unable to change password. Error occurred.\n"), NULL);
+
+exit_cleanup:
+	gg_change_passwd_free(req->http_req);
+	g_free(req->new_password);
+	g_free(req);
+}
+
+static void ggp_callback_change_passwd_ok(PurpleConnection *gc,
+	PurpleRequestFields *fields)
+{
+	PurpleAccount *account;
+	GGPInfo *info = purple_connection_get_protocol_data(gc);
 	struct gg_http *h;
-	gchar *cur, *p1, *p2, *t;
+	gchar *cur, *p1, *p2, *t, *mail;
+	const char *messagesTitle =
+		_("Change password for the Gadu-Gadu account");
 
-	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");
+	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 (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."),
+	if (strlen(p1) > 15) {
+		purple_notify_error(account, messagesTitle,
+			_("New password should be at most 15 characters long."),
 			NULL);
 		goto exit_err;
 	}
 
-	purple_debug_info("gg", "Changing password\n");
+	if (g_utf8_collate(cur, purple_account_get_password(account)) != 0) {
+		purple_notify_error(account, messagesTitle,
+			_("Your current password is different from the one that"
+			" you specified."), NULL);
+		goto exit_err;
+	}
 
-	/* XXX: this email should be a pref... */
-	h = gg_change_passwd4(ggp_get_uin(account),
-			      "user at example.net", purple_account_get_password(account),
-			      p1, info->token->id, t, 0);
-
-	if (h == NULL) {
-		purple_notify_error(account, NULL,
-			_("Unable to change password. Error occurred.\n"),
-			NULL);
+	if (!purple_email_is_valid(mail)) {
+		purple_notify_error(account, messagesTitle,
+			_("Invalid email address"), NULL);
 		goto exit_err;
 	}
 
-	purple_account_set_password(account, p1);
+	purple_debug_info("gg", "Changing password with email \"%s\"...\n",
+		mail);
 
-	gg_change_passwd_free(h);
+	h = gg_change_passwd4(ggp_get_uin(account), mail,
+		purple_account_get_password(account), p1, info->token->id, t,
+		1);
 
-	purple_notify_info(account, _("Change password for the Gadu-Gadu account"),
-			 _("Password was changed successfully!"), NULL);
-
+	if (h == NULL)
+		purple_notify_error(account, messagesTitle,
+			_("Unable to change password. Error occurred.\n"),
+			NULL);
+	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);
+	}
+	
 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 +759,11 @@ static void ggp_change_passwd_dialog(Pur
 	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 +783,11 @@ static void ggp_change_passwd_dialog(Pur
 	purple_request_field_string_set_masked(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
+	field = purple_request_field_string_new("email",
+			_("Email Address"), "", FALSE);
+	purple_request_field_string_set_masked(field, FALSE);
+	purple_request_field_group_add_field(group, field);
+
 	field = purple_request_field_string_new("token",
 			_("Enter current token"), "", FALSE);
 	purple_request_field_string_set_masked(field, FALSE);
@@ -732,8 +799,8 @@ static void ggp_change_passwd_dialog(Pur
 	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 +825,7 @@ static void ggp_action_change_status_bro
 
 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 +845,7 @@ static void ggp_action_change_status_bro
 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 +915,7 @@ static void ggp_bmenu_add_to_chat(Purple
 
 	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 +924,7 @@ static void ggp_bmenu_add_to_chat(Purple
 	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 +946,7 @@ static void ggp_add_deny(PurpleConnectio
 
 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 +957,7 @@ static void ggp_rem_deny(PurpleConnectio
 
 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 +1091,8 @@ static void gg_get_avatar_url_cb(PurpleU
 
 				purple_debug_info("gg", "gg_get_avatar_url_cb: "
 					"requesting avatar for %s\n", uin);
-				url_data = purple_util_fetch_url_request_len(account,
+				/* FIXME: This should be cancelled somewhere if not needed. */
+				url_data = purple_util_fetch_url_request(account,
 						bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)",
 						FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data);
 			}
@@ -1052,7 +1120,8 @@ static void ggp_update_buddy_avatar(Purp
 
 	avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin);
 
-	url_data = purple_util_fetch_url_request_len(
+	/* FIXME: This should be cancelled somewhere if not needed. */
+	url_data = purple_util_fetch_url_request(
 			purple_connection_get_account(gc), avatarurl, TRUE,
 			"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
 			gg_get_avatar_url_cb, gc);
@@ -1086,7 +1155,7 @@ static void ggp_generic_status_handler(P
 			break;
 		case GG_STATUS_FFC:
 		case GG_STATUS_FFC_DESCR:
-			st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
+			st = "freeforchat";
 			break;
 		case GG_STATUS_AVAIL:
 		case GG_STATUS_AVAIL_DESCR:
@@ -1096,6 +1165,10 @@ static void ggp_generic_status_handler(P
 		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);
@@ -1349,7 +1422,7 @@ static void ggp_pubdir_reply_handler(Pur
 
 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;
@@ -1391,7 +1464,7 @@ static void ggp_recv_image_handler(Purpl
 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);
 
@@ -1439,11 +1512,12 @@ static void ggp_recv_message_handler(Pur
  */
 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)
 	{
@@ -1572,8 +1646,13 @@ static void ggp_recv_message_handler(Pur
 			from, msg, ev->event.msg.msgclass,
 			ev->event.msg.recipients_count);
 
+	if (ev->event.msg.msgclass & GG_CLASS_QUEUED)
+		mtime = ev->event.msg.time;
+	else
+		mtime = time(NULL);
+
 	if (ev->event.msg.recipients_count == 0) {
-		serv_got_im(gc, from, msg, 0, ev->event.msg.time);
+		serv_got_im(gc, from, msg, 0, mtime);
 	} else {
 		const char *chat_name;
 		int chat_id;
@@ -1599,7 +1678,7 @@ static void ggp_recv_message_handler(Pur
 
 		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);
@@ -1608,7 +1687,7 @@ static void ggp_send_image_handler(Purpl
 
 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)));
 
@@ -1714,7 +1793,7 @@ static void ggp_callback_recv(gpointer _
 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;
 
@@ -1849,7 +1928,7 @@ static void ggp_async_login_handler(gpoi
 
 	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);
@@ -1896,11 +1975,12 @@ static void ggp_async_login_handler(gpoi
 	purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
 			info->session->check, info->session->state);
 
-	purple_input_remove(gc->inpa);
+	purple_input_remove(info->inpa);
+	info->inpa = 0;
 
 	/** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */
 	if (info->session->fd >= 0)
-		gc->inpa = purple_input_add(info->session->fd,
+		info->inpa = purple_input_add(info->session->fd,
 			(info->session->check == 1) ? PURPLE_INPUT_WRITE :
 				PURPLE_INPUT_READ,
 			ggp_async_login_handler, gc);
@@ -1913,8 +1993,8 @@ static void ggp_async_login_handler(gpoi
 		case GG_EVENT_CONN_SUCCESS:
 			{
 				purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n");
-				purple_input_remove(gc->inpa);
-				gc->inpa = purple_input_add(info->session->fd,
+				purple_input_remove(info->inpa);
+				info->inpa = purple_input_add(info->session->fd,
 							  PURPLE_INPUT_READ,
 							  ggp_callback_recv, gc);
 
@@ -1924,17 +2004,69 @@ static void ggp_async_login_handler(gpoi
 			}
 			break;
 		case GG_EVENT_CONN_FAILED:
-			purple_input_remove(gc->inpa);
-			gc->inpa = 0;
-			purple_connection_error (gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-				_("Connection failed"));
+			purple_input_remove(info->inpa);
+			info->inpa = 0;
+			purple_debug_info("gg", "Connection failure: %d\n",
+				ev->event.failure);
+			switch (ev->event.failure) {
+				case GG_FAILURE_RESOLVING:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Unable to resolve "
+						"hostname"));
+					break;
+				case GG_FAILURE_PASSWORD:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+						_("Incorrect password"));
+					break;
+				case GG_FAILURE_TLS:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
+						_("SSL Connection Failed"));
+					break;
+				case GG_FAILURE_INTRUDER:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+						_("Your account has been "
+						"disabled because too many "
+						"incorrect passwords were "
+						"entered"));
+					break;
+				case GG_FAILURE_UNAVAILABLE:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Service temporarily "
+						"unavailable"));
+					break;
+				case GG_FAILURE_PROXY:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Error connecting to proxy "
+						"server"));
+					break;
+				case GG_FAILURE_HUB:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Error connecting to master "
+						"server"));
+					break;
+				default:
+					purple_connection_error(gc,
+						PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+						_("Connection failed"));
+			}
 			break;
 		case GG_EVENT_MSG:
 			if (ev->event.msg.sender == 0)
+			{
+				if (ev->event.msg.message == NULL)
+					break;
+
 				/* system messages are mostly ads */
 				purple_debug_info("gg", "System message:\n%s\n",
 					ev->event.msg.message);
+			}
 			else
 				purple_debug_warning("gg", "GG_EVENT_MSG: message from user %u "
 					"unexpected while connecting:\n%s\n",
@@ -1958,6 +2090,19 @@ static const char *ggp_list_icon(PurpleA
 	return "gadu-gadu";
 }
 
+static const char *ggp_normalize(const PurpleAccount *account, const char *who)
+{
+	static char normalized[21]; /* maximum unsigned long long int size */
+
+	uin_t uin = ggp_str_to_uin(who);
+	if (uin <= 0)
+		return NULL;
+
+	g_snprintf(normalized, sizeof(normalized), "%u", uin);
+
+	return normalized;
+}
+
 static char *ggp_status_text(PurpleBuddy *b)
 {
 	PurpleStatus *status;
@@ -2013,50 +2158,60 @@ static GList *ggp_status_types(PurpleAcc
 	PurpleStatusType *type;
 	GList *types = NULL;
 
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	/*
-	 * Without this selecting Invisible as own status doesn't
-	 * work. It's not used and not needed to show status of buddies.
+	 * New status for GG 8.0: PoGGadaj ze mna (chatty).
+	 * NOTE: at this time, this is used only to set our own status.
 	 */
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+		"freeforchat", _("Chatty"), TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	/*
-	 * New statuses for GG 8.0 like PoGGadaj ze mna (not yet because
-	 * libpurple can't support Chatty status) and Nie przeszkadzac
+	 * New status for GG 8.0: Nie przeszkadzac (do not disturb).
 	 */
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	/*
+	 * It's used on buddy list if and only if it's showing our own
+	 * (invisible) status.
+	 */
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
+	types = g_list_append(types, type);
+
+	/*
 	 * This status is necessary to display guys who are blocking *us*.
 	 */
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_INVISIBLE, "blocked", _("Blocked"), TRUE, FALSE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
+		"blocked", _("Blocked"), TRUE, FALSE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
-	type = purple_status_type_new_with_attrs(
-			PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE,
-			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			NULL);
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE,
+		NULL, NULL, TRUE, TRUE, FALSE,
+		"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+		NULL);
 	types = g_list_append(types, type);
 
 	return types;
@@ -2067,13 +2222,15 @@ static GList *ggp_blist_node_menu(Purple
 	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),
@@ -2125,12 +2282,26 @@ static void ggp_login(PurpleAccount *acc
 	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);
 
@@ -2141,13 +2312,26 @@ static void ggp_login(PurpleAccount *acc
 	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;
@@ -2183,24 +2367,25 @@ static void ggp_login(PurpleAccount *acc
 		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;
+	account = purple_connection_get_account(gc);
+	info = purple_connection_get_protocol_data(gc);
 
-		status = purple_account_get_active_status(account);
+	if (info) {
+		PurpleStatus *status = purple_account_get_active_status(account);
 
 		if (info->session != NULL) {
 			ggp_set_status(account, status);
@@ -2218,20 +2403,21 @@ static void ggp_close(PurpleConnection *
 		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];
@@ -2349,6 +2535,7 @@ static unsigned int ggp_send_typing(Purp
 
 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
@@ -2360,7 +2547,7 @@ static unsigned int ggp_send_typing(Purp
 		dummy_length = 0;
 	
 	gg_typing_notification(
-		((GGPInfo*)gc->proto_data)->session,
+		info->session,
 		ggp_str_to_uin(name),
 		dummy_length); 
 	
@@ -2369,7 +2556,7 @@ static void ggp_get_info(PurpleConnectio
 
 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;
 
@@ -2397,6 +2584,9 @@ static int ggp_to_gg_status(PurpleStatus
 	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;
@@ -2445,7 +2635,7 @@ static void ggp_set_status(PurpleAccount
 		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);
 
@@ -2463,10 +2653,10 @@ static void ggp_set_status(PurpleAccount
 
 }
 
-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));
@@ -2480,14 +2670,14 @@ static void ggp_remove_buddy(PurpleConne
 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;
@@ -2525,7 +2715,7 @@ static int ggp_chat_send(PurpleConnectio
 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; */
@@ -2539,7 +2729,7 @@ static int ggp_chat_send(PurpleConnectio
 	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;
 		}
 
@@ -2580,7 +2770,7 @@ static void ggp_keepalive(PurpleConnecti
 
 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"); */
 
@@ -2605,14 +2795,16 @@ static GList *ggp_actions(PurplePlugin *
 	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);
@@ -2637,10 +2829,6 @@ static GList *ggp_actions(PurplePlugin *
 				     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;
 }
 
@@ -2651,6 +2839,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE,
 	NULL,				/* user_splits */
 	NULL,				/* protocol_options */
@@ -2691,13 +2880,12 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
@@ -2716,15 +2904,12 @@ static PurplePluginProtocolInfo prpl_inf
 	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 = {
@@ -2790,11 +2975,6 @@ static void init_plugin(PurplePlugin *pl
 	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,
@@ -2807,22 +2987,29 @@ static void init_plugin(PurplePlugin *pl
 	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);
============================================================
--- libpurple/core.h	a97aec8abae23b87c688a59c430035017d6a8600
+++ libpurple/core.h	2bdddafcdbb28a23fad8695496d96d5b08686fbb
@@ -163,8 +163,6 @@ PurpleCoreUiOps *purple_core_get_ui_ops(
  *
  * @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);
 
@@ -196,8 +194,6 @@ gboolean purple_core_ensure_single_insta
  * @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);
 
============================================================
--- libpurple/protocols/yahoo/libymsg.c	75d3e1b021db1b40a78a28e1000061180dcd65e7
+++ libpurple/protocols/yahoo/libymsg.c	afd8ec7a4457d6c35be7a00b3fc3e50c83b416f2
@@ -337,12 +337,12 @@ static void yahoo_process_status(PurpleC
 			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 @@ static void yahoo_process_list_15(Purple
 	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 @@ static void yahoo_process_list_15(Purple
 						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);
 				}
 
@@ -634,11 +634,10 @@ static void yahoo_process_list(PurpleCon
 static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
 	GSList *l = pkt->hash;
-	gboolean export = FALSE;
 	gboolean got_serv_list = FALSE;
 	YahooFriend *f = NULL;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 	GHashTable *ht;
 
 	char **lines;
@@ -712,7 +711,6 @@ static void yahoo_process_list(PurpleCon
 					}
 					b = purple_buddy_new(account, norm_bud, NULL);
 					purple_blist_add_buddy(b, NULL, g, NULL);
-					export = TRUE;
 				}
 
 				yahoo_do_group_check(account, ht, norm_bud, grp);
@@ -748,13 +746,13 @@ static void yahoo_process_list(PurpleCon
 	}
 
 	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 +761,7 @@ static void yahoo_process_list(PurpleCon
 			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 +785,7 @@ static void yahoo_process_notify(PurpleC
 	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 +897,7 @@ static void yahoo_process_sms_message(Pu
 	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 +958,7 @@ static void yahoo_process_message(Purple
 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 +1059,7 @@ static void yahoo_process_message(Purple
 							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 +1200,7 @@ yahoo_buddy_add_authorize_cb(gpointer da
 {
 	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 +1231,7 @@ yahoo_buddy_add_deny_cb(struct yahoo_add
 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 +1293,7 @@ static void yahoo_buddy_denied_our_add(P
 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 +1623,7 @@ static void yahoo_process_mail(PurpleCon
 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 +1707,7 @@ static void yahoo_auth16_stage3(PurpleCo
 
 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;
@@ -2014,7 +2012,7 @@ static void yahoo_auth16_stage1_cb(Purpl
 			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(
+			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)
@@ -2055,7 +2053,7 @@ static void yahoo_auth16_stage1(PurpleCo
 	g_free(encoded_password);
 	g_free(encoded_username);
 
-	url_data = purple_util_fetch_url_request_len(
+	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 +2178,12 @@ static void yahoo_process_ignore(PurpleC
 							  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 +2205,14 @@ static void yahoo_process_authresp(Purpl
 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 +2242,12 @@ static void yahoo_process_authresp(Purpl
 			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;
@@ -2300,7 +2300,7 @@ static void yahoo_process_addbuddy(Purpl
 	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 +2394,7 @@ static void yahoo_p2p_keepalive_cb(gpoin
 	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 +2413,7 @@ static gboolean yahoo_p2p_keepalive(gpoi
 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 +2460,7 @@ static void yahoo_p2p_process_p2pfilexfe
 	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 +2545,7 @@ static void yahoo_p2p_read_pkt_cb(gpoint
 
 	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 +2617,7 @@ static void yahoo_p2p_server_send_connec
 
 	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 +2657,7 @@ static gboolean yahoo_cancel_p2p_server_
 	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 +2678,7 @@ static void yahoo_p2p_server_listen_cb(i
 	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 +2706,7 @@ void yahoo_send_p2p_pkt(PurpleConnection
 	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 +2770,7 @@ void yahoo_send_p2p_pkt(PurpleConnection
 	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 +2787,7 @@ static void yahoo_p2p_init_cb(gpointer d
 	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 +3132,7 @@ static void yahoo_pending(gpointer data,
 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;
 
@@ -3155,7 +3155,7 @@ static void yahoo_pending(gpointer data,
 				_("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;
@@ -3240,15 +3240,15 @@ static void yahoo_got_connected(gpointer
 		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
@@ -3266,26 +3266,26 @@ static void yahoo_got_web_connected(gpoi
 		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;
@@ -3342,7 +3342,8 @@ static void yahoo_web_pending(gpointer d
 	}
 
 	yd->auth = g_string_free(s, FALSE);
-	purple_input_remove(gc->inpa);
+	purple_input_remove(yd->inpa);
+	yd->inpa = 0;
 	close(source);
 	g_free(yd->rxqueue);
 	yd->rxqueue = NULL;
@@ -3359,13 +3360,10 @@ static void yahoo_got_cookies_send_cb(gp
 
 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,9 +3373,10 @@ static void yahoo_got_cookies_send_cb(gp
 		gchar *tmp;
 		g_free(yd->auth);
 		yd->auth = NULL;
-		if (gc->inpa)
-			purple_input_remove(gc->inpa);
-		gc->inpa = 0;
+		if (yd->inpa) {
+			purple_input_remove(yd->inpa);
+			yd->inpa = 0;
+		}
 		tmp = g_strdup_printf(_("Lost connection with %s: %s"),
 				"login.yahoo.com:80", g_strerror(errno));
 		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
@@ -3393,13 +3392,14 @@ static void yahoo_got_cookies_send_cb(gp
 	g_free(yd->auth);
 	yd->auth = NULL;
 	yd->auth_written = 0;
-	purple_input_remove(gc->inpa);
-	gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
+	purple_input_remove(yd->inpa);
+	yd->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
 }
 
 static void yahoo_got_cookies(gpointer data, gint source, const gchar *error_message)
 {
 	PurpleConnection *gc = data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
 		gchar *tmp;
@@ -3410,9 +3410,9 @@ static void yahoo_got_cookies(gpointer d
 		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 +3474,7 @@ yahoo_login_page_cb(PurpleUtilFetchUrlDa
 {
 	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);
@@ -3671,13 +3671,14 @@ void yahoo_login(PurpleAccount *account)
 
 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 +3709,7 @@ void yahoo_login(PurpleAccount *account)
 
 	/* 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(
+	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 +3722,13 @@ void yahoo_close(PurpleConnection *gc) {
 }
 
 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 +3813,7 @@ void yahoo_close(PurpleConnection *gc) {
 	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 +3830,7 @@ const char *yahoo_list_emblem(PurpleBudd
 
 	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 +3895,7 @@ static void yahoo_initiate_conference(Pu
 
 	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);
@@ -4055,7 +4058,7 @@ static void yahoo_addbuddyfrommenu_cb(Pu
 	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);
 }
 
 
@@ -4075,7 +4078,7 @@ static GList *build_presence_submenu(Yah
 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) {
@@ -4135,7 +4138,7 @@ static GList *yahoo_buddy_menu(PurpleBud
 	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;
 
@@ -4218,7 +4221,7 @@ static void yahoo_act_id(PurpleConnectio
 
 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);
@@ -4235,7 +4238,7 @@ yahoo_get_inbox_token_cb(PurpleUtilFetch
 	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));
 
@@ -4271,7 +4274,7 @@ static void yahoo_show_inbox(PurplePlugi
 	/* 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";
@@ -4286,7 +4289,7 @@ static void yahoo_show_inbox(PurplePlugi
 		use_whole_url ? base_url : "",
 		yd->cookie_t, yd->cookie_y);
 
-	url_data = purple_util_fetch_url_request_len(
+	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);
@@ -4385,7 +4388,7 @@ static void yahoo_get_sms_carrier_cb(Pur
 {
 	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);
@@ -4440,7 +4443,7 @@ static void yahoo_get_sms_carrier(Purple
 
 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;
@@ -4475,10 +4478,10 @@ static void yahoo_get_sms_carrier(Purple
 		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(
+	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);
@@ -4500,7 +4503,7 @@ int yahoo_send_im(PurpleConnection *gc, 
 
 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;
@@ -4611,7 +4614,7 @@ int yahoo_send_im(PurpleConnection *gc, 
 	 *
 	 * 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
@@ -4657,7 +4660,7 @@ unsigned int yahoo_send_typing(PurpleCon
 
 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;
@@ -4728,7 +4731,7 @@ void yahoo_set_status(PurpleAccount *acc
 
 	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);
@@ -4794,7 +4797,7 @@ void yahoo_set_idle(PurpleConnection *gc
 
 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;
@@ -4913,7 +4916,7 @@ void yahoo_keepalive(PurpleConnection *g
 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 */
@@ -4944,9 +4947,9 @@ void yahoo_keepalive(PurpleConnection *g
 
 }
 
-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;
@@ -5009,7 +5012,7 @@ void yahoo_remove_buddy(PurpleConnection
 
 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;
@@ -5065,7 +5068,7 @@ void yahoo_add_deny(PurpleConnection *gc
 }
 
 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;
 
@@ -5088,7 +5091,7 @@ void yahoo_rem_deny(PurpleConnection *gc
 }
 
 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;
 
@@ -5116,7 +5119,7 @@ void yahoo_set_permit_deny(PurpleConnect
 
 	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)
@@ -5136,7 +5139,7 @@ void yahoo_change_buddys_group(PurpleCon
 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);
@@ -5183,7 +5186,7 @@ void yahoo_rename_group(PurpleConnection
 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;
 
@@ -5212,7 +5215,7 @@ yahoopurple_cmd_buzz(PurpleConversation 
 	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;
 }
@@ -5227,7 +5230,7 @@ yahoopurple_cmd_chat_join(PurpleConversa
 	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);
@@ -5261,12 +5264,12 @@ gboolean yahoo_send_attention(PurpleConn
 	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;
============================================================
--- pidgin/plugins/ticker/gtkticker.c	e8c3b98d6fd774a9772b5e3441fc96f66c7eabf4
+++ pidgin/plugins/ticker/gtkticker.c	8be613ae4205334fe7b52d01b2e1c86c5c45a317
@@ -128,7 +128,7 @@ static void gtk_ticker_class_init (GtkTi
 
 	widget_class->map = gtk_ticker_map;
 	widget_class->realize = gtk_ticker_realize;
-	/*widget_class->size_request = gtk_ticker_size_request;*/
+	widget_class->size_request = gtk_ticker_size_request;
 	widget_class->size_allocate = gtk_ticker_size_allocate;
 
 	container_class->add = gtk_ticker_add_real;
@@ -178,7 +178,7 @@ static void gtk_ticker_put (GtkTicker *t
 
 	ticker->children = g_list_append (ticker->children, child_info);
 
-	if (gtk_widget_get_realized (GTK_WIDGET(ticker)))
+	if (gtk_widget_get_realized (GTK_WIDGET (ticker)))
 		gtk_widget_realize (widget);
 
 	if (gtk_widget_get_visible (GTK_WIDGET (ticker)) &&
@@ -332,11 +332,11 @@ static void gtk_ticker_realize (GtkWidge
 #endif
 	attributes.wclass = GDK_INPUT_OUTPUT;
 	attributes.visual = gtk_widget_get_visual (widget);
-	/*attributes.colormap = gtk_widget_get_colormap (widget);*/
+	attributes.colormap = gtk_widget_get_colormap (widget);
 	attributes.event_mask = gtk_widget_get_events (widget);
 	attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
 
-	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL /*| GDK_WA_COLORMAP*/;
+	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
 	window = gdk_window_new (gtk_widget_get_parent_window (widget),
 			&attributes, attributes_mask);
============================================================
--- po/ChangeLog	1770e6b10b247173ed2c0849a520248ce6e5d223
+++ po/ChangeLog	83e7087e33079b7550f2dc0254a3f6abd9061b1d
@@ -1,5 +1,8 @@ Pidgin and Finch: The Pimpin' Penguin IM
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.10.1
+	* No changes
+
 version 2.10.0
 	* Afrikaans translation updated (Friedel Wolff)
 	* Albanian translation updated (Besnik Bleta)
============================================================
--- pidgin/plugins/history.c	651d7f4b1f6c8ac7691e335a36e7d7616ddd2916
+++ pidgin/plugins/history.c	226088f0698685f604cad0bec6e1a41544e24850
@@ -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 @@ static void historize(PurpleConversation
 	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 @@ static void historize(PurpleConversation
 
 	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 @@ static void historize(PurpleConversation
 		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);
============================================================
--- pidgin/plugins/timestamp.c	8492d27680aa9690bb1c4a20a1f4b7c25e4c0d3b
+++ pidgin/plugins/timestamp.c	2a0ae636289f7ec0629804d31b76a4a0872cab68
@@ -134,7 +134,7 @@ get_config_frame(PurplePlugin *plugin)
 	GtkWidget *ret;
 	GtkWidget *frame, *label;
 	GtkWidget *vbox, *hbox;
-	GtkAdjustment *adj;
+	GtkObject *adj;
 	GtkWidget *spinner;
 
 	ret = gtk_vbox_new(FALSE, 18);
============================================================
--- libpurple/ft.c	54b6b4e5e9a6c2cff6167d246b15cebe94d02a2f
+++ libpurple/ft.c	84f8ec34b8984ee4362a89a68d32d439b73d318c
@@ -220,7 +220,7 @@ purple_xfer_unref(PurpleXfer *xfer)
 		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)
 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_request_denied(PurpleXfer *x
 	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 @@ purple_xfer_get_status(const PurpleXfer 
 	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 @@ purple_xfer_get_local_filename(const Pur
 	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 @@ purple_xfer_get_bytes_sent(const PurpleX
 	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 @@ purple_xfer_get_bytes_remaining(const Pu
 	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 @@ purple_xfer_get_end_time(const PurpleXfe
 	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
 }
 
 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,10 +974,18 @@ void
 }
 
 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);
+
 	xfer->bytes_sent = bytes_sent;
 	xfer->bytes_remaining = purple_xfer_get_size(xfer) - bytes_sent;
 }
@@ -1404,13 +1439,6 @@ purple_xfer_start(PurpleXfer *xfer, int 
 
 	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 @@ purple_xfer_prepare_thumbnail(PurpleXfer
 	}
 }
 
+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
  **************************************************************************/
============================================================
--- libpurple/protocols/gg/Makefile.mingw	6365006701bdfeffbbb9264afc22116fd3cb23cf
+++ libpurple/protocols/gg/Makefile.mingw	fb7eb47e39a124fb8c47c34856471d014f66eda2
@@ -60,7 +60,8 @@ C_SRC =	\
 	confer.c \
 	gg.c \
 	search.c \
-	gg-utils.c
+	gg-utils.c \
+	win32-resolver.c
 
 OBJECTS = $(C_SRC:%.c=%.o)
 
============================================================
--- libpurple/win32/libc_interface.c	e853652c1abfe43443299a471b799dc2ef162958
+++ libpurple/win32/libc_interface.c	da214268a94bc48a444ae3b27df6fc81e9b84b59
@@ -300,7 +300,51 @@ wpurple_inet_ntop (int af, const void *s
   return (const char *) dst;
 }
 
+int
+wpurple_inet_pton(int af, const char *src, void *dst)
+{
+	/* struct sockaddr can't accomodate struct sockaddr_in6. */
+	union {
+		struct sockaddr_in6 sin6;
+		struct sockaddr_in sin;
+	} sa;
+	size_t srcsize;
+	
+	switch(af)
+	{
+		case AF_INET:
+			sa.sin.sin_family = AF_INET;
+			srcsize = sizeof (sa.sin);
+		break;
+		case AF_INET6:
+			sa.sin6.sin6_family = AF_INET6;
+			srcsize = sizeof (sa.sin6);
+		break;
+		default:
+			errno = WSAEPFNOSUPPORT;
+			return -1;
+	}
+	
+	if (WSAStringToAddress(src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
+	{
+		errno = WSAGetLastError();
+		return -1;
+	}
+	
+	switch(af)
+	{
+		case AF_INET:
+			memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
+		break;
+		case AF_INET6:
+			memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
+		break;
+	}
+	
+	return 1;
+}
 
+
 /* netdb.h */
 struct hostent* wpurple_gethostbyname(const char *name) {
 	struct hostent *hp;
@@ -467,12 +511,6 @@ int wpurple_gettimeofday(struct timeval 
 	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 +1085,3 @@ wpurple_get_timezone_abbreviation(const 
 	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);
-}
-
-
============================================================
--- libpurple/win32/libc_interface.h	ea23c9702eec172f10e3e17347b8bdea325e60a2
+++ libpurple/win32/libc_interface.h	ae6fd1cf4698f048125cc18f1a2b91367da5c54a
@@ -89,6 +89,9 @@ wpurple_inet_ntop( af, src, dst, cnt )
 #define inet_ntop( af, src, dst, cnt ) \
 wpurple_inet_ntop( af, src, dst, cnt )
 
+#define inet_pton( af, src, dst ) \
+wpurple_inet_pton( af, src, dst )
+
 /* netdb.h */
 #define gethostbyname( name ) \
 wpurple_gethostbyname( name )
@@ -135,7 +138,7 @@ wpurple_gettimeofday( timeval, timezone 
 #define vsnprintf _vsnprintf
 
 #define rename( oldname, newname ) \
-wpurple_rename( oldname, newname )
+g_rename( oldname, newname )
 
 /* sys/stat.h */
 #define fchmod(a,b)
============================================================
--- libpurple/win32/libc_internal.h	baffee0cc7987bf2a86f9e4e8df3c77f7bc31167
+++ libpurple/win32/libc_internal.h	4dffd4fa4c37f51957cd9e920a7a92812670a31f
@@ -48,6 +48,7 @@ wpurple_inet_ntop (int af, const void *s
 int wpurple_inet_aton(const char *name, struct in_addr *addr);
 const char *
 wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt);
+int wpurple_inet_pton(int af, const char *src, void *dst);
 
 /* netdb.h */
 struct hostent* wpurple_gethostbyname(const char *name);
@@ -141,9 +142,6 @@ int wpurple_gethostname(char *name, size
 int wpurple_gethostname(char *name, size_t size);
 
 
-/* stdio.h */
-int wpurple_rename(const char *oldname, const char *newname);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
============================================================
--- libpurple/log.c	0c3f25c46b130043aaa4f84bfcc5adf8156e6b2e
+++ libpurple/log.c	a057ec1242e6d2db2d339caa7fa716b412df62aa
@@ -1103,7 +1103,7 @@ static void log_get_log_sets_common(GHas
 			/* 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;
 				}
============================================================
--- libpurple/conversation.h	ee3ba57ce65309287c60fa7d3f0d504418cfe2e7
+++ libpurple/conversation.h	b0f0a42820a06953a73980cbf1734e3034f56fce
@@ -125,7 +125,7 @@ typedef enum
 	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 @@ typedef enum
 	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 @@ struct _PurpleConversationUiOps
 	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 at 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 @@ PurpleAccount *purple_conversation_get_a
 /**
  * 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 @@ void purple_conversation_foreach(void (*
  * @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 @@ GList *purple_conversation_get_message_h
  * 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 @@ void purple_conversation_clear_message_h
  * @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 @@ const char *purple_conversation_message_
  * @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 @@ const char *purple_conversation_message_
  * @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,11 +671,46 @@ PurpleMessageFlags purple_conversation_m
  * @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
  */
-time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg);
+const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg);
 
+/**
+ * Get the conversation associated with the PurpleConvMessage
+ *
+ * @param msg   A PurpleConvMessage
+ *
+ * @return   The conversation
+ */
+PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg);
+
+/**
+ * Set the UI data associated with this conversation.
+ *
+ * @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
 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 @@ void purple_conv_chat_left(PurpleConvCha
  * @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,15 +1291,61 @@ PurpleConvChatBuddy *purple_conv_chat_cb
 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
  *
  * @param cb The chat buddy to destroy
@@ -1423,8 +1360,6 @@ void purple_conv_chat_cb_destroy(PurpleC
  * @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 @@ GList * purple_conversation_get_extended
  *                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);
 
============================================================
--- pidgin/gtkconv.c	737af88b5130c059af3a24d838d6ff82dc97a49d
+++ pidgin/gtkconv.c	fadb73bdbd7fd93cf49d5dce25c822c9cc8d94da
@@ -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,55 @@
 #include "gtkprivacy.h"
 #include "gtkthemes.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 #include "pidginstock.h"
 #include "pidgintooltip.h"
+#include "smileyparser.h"
 
 #include "gtknickcolors.h"
 
+#if !GTK_CHECK_VERSION(2,20,0)
+#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x)
+
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
+#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x)
+#endif
+#endif
+
+/**
+ * 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 "<AUTO-REPLY> : "
@@ -175,7 +223,7 @@ static const GdkColor *get_nick_color(Pi
 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];
@@ -195,15 +243,16 @@ get_conversation_blist_node(PurpleConver
 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;
@@ -275,7 +324,7 @@ default_formatize(PidginConversation *c)
 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
@@ -355,8 +404,32 @@ debug_command_cb(PurpleConversation *con
 		}
 
 		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;
 	}
@@ -378,8 +451,9 @@ static void clear_conversation_scrollbac
 	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
@@ -497,8 +571,8 @@ check_for_and_do_command(PurpleConversat
 					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;
@@ -590,7 +664,7 @@ send_cb(GtkWidget *widget, PidginConvers
 		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;
 
@@ -656,7 +730,7 @@ static void chat_do_info(PidginConversat
 	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)));
 	}
 }
@@ -668,7 +742,7 @@ info_cb(GtkWidget *widget, PidginConvers
 	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) {
@@ -756,7 +830,7 @@ do_invite(GtkWidget *w, int resp, Invite
 		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);
 	}
@@ -774,17 +848,15 @@ invite_dnd_recv(GtkWidget *widget, GdkDr
 	InviteBuddyInfo *info = (InviteBuddyInfo *)data;
 	const char *convprotocol;
 	gboolean success = TRUE;
-	GdkAtom target = gtk_selection_data_get_target(sd);
 
 	convprotocol = purple_account_get_protocol_id(purple_conversation_get_account(info->conv));
 
-	if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
+	if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
 	{
 		PurpleBlistNode *node = NULL;
 		PurpleBuddy *buddy;
-		const guchar *data = gtk_selection_data_get_data(sd);
 
-		memcpy(&node, data, sizeof(node));
+		memcpy(&node, sd->data, sizeof(node));
 
 		if (PURPLE_BLIST_NODE_IS_CONTACT(node))
 			buddy = purple_contact_get_priority_buddy((PurpleContact *)node);
@@ -793,7 +865,7 @@ invite_dnd_recv(GtkWidget *widget, GdkDr
 		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 "
@@ -803,16 +875,15 @@ invite_dnd_recv(GtkWidget *widget, GdkDr
 		else
 			gtk_entry_set_text(GTK_ENTRY(info->entry), purple_buddy_get_name(buddy));
 
-		gtk_drag_finish(dc, success,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, success, (dc->action == GDK_ACTION_MOVE), t);
 	}
-	else if (target == gdk_atom_intern("application/x-im-contact", FALSE))
+	else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
 	{
 		char *protocol = NULL;
 		char *username = NULL;
 		PurpleAccount *account;
 
-		if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account,
+		if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account,
 										&protocol, &username, NULL))
 		{
 			if (account == NULL)
@@ -837,8 +908,7 @@ invite_dnd_recv(GtkWidget *widget, GdkDr
 		g_free(username);
 		g_free(protocol);
 
-		gtk_drag_finish(dc, success,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, success, (dc->action == GDK_ACTION_MOVE), t);
 	}
 }
 
@@ -880,15 +950,14 @@ invite_cb(GtkWidget *widget, PidginConve
 		                                GTK_RESPONSE_OK);
 		gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE);
 		gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE);
-		/* TODO: set no separator using GTK+ 3.0 */
-#if 0
+#if !GTK_CHECK_VERSION(2,22,0)
 		gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE);
 #endif
 
 		info->window = GTK_WIDGET(invite_dialog);
 
 		/* Setup the outside spacing. */
-		vbox = gtk_dialog_get_content_area(GTK_DIALOG(invite_dialog));
+		vbox = GTK_DIALOG(invite_dialog)->vbox;
 
 		gtk_box_set_spacing(GTK_BOX(vbox), PIDGIN_HIG_BORDER);
 		gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BOX_SPACE);
@@ -986,7 +1055,7 @@ static void
 }
 
 static void
-menu_join_chat_cb(gpointer data, guint action, GtkWidget *widget)
+menu_join_chat_cb(GtkAction *action, gpointer data)
 {
 	pidgin_blist_joinchat_show();
 }
@@ -994,6 +1063,8 @@ savelog_writefile_cb(void *user_data, co
 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;
@@ -1020,6 +1091,7 @@ savelog_writefile_cb(void *user_data, co
 
 	fprintf(fp, "\n</body>\n</html>\n");
 	fclose(fp);
+#endif /* if 0 */
 }
 
 /*
@@ -1031,7 +1103,8 @@ menu_save_as_cb(GtkAction *action, gpoin
 {
 	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;
@@ -1039,7 +1112,7 @@ menu_save_as_cb(GtkAction *action, gpoin
 	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++)
@@ -1081,12 +1154,9 @@ menu_view_log_cb(GtkAction *action, gpoi
 	gtkblist = pidgin_blist_get_default_gtk_blist();
 
 	cursor = gdk_cursor_new(GDK_WATCH);
-	gdk_window_set_cursor(gtk_widget_get_window(gtkblist->window), cursor);
-	gdk_window_set_cursor(gtk_widget_get_window(win->window), cursor);
+	gdk_window_set_cursor(gtkblist->window->window, cursor);
+	gdk_window_set_cursor(win->window->window, cursor);
 	gdk_cursor_unref(cursor);
-#if GTK_CHECK_VERSION(2,4,0) && !GTK_CHECK_VERSION(2,6,0) //FIXME: What?
-	gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
-#endif
 
 	name = purple_conversation_get_name(conv);
 	account = purple_conversation_get_account(conv);
@@ -1099,8 +1169,8 @@ menu_view_log_cb(GtkAction *action, gpoi
 		{
 			pidgin_log_show_contact((PurpleContact *)node->parent);
 			g_slist_free(buddies);
-			gdk_window_set_cursor(gtk_widget_get_window(gtkblist->window), NULL);
-			gdk_window_set_cursor(gtk_widget_get_window(win->window), NULL);
+			gdk_window_set_cursor(gtkblist->window->window, NULL);
+			gdk_window_set_cursor(win->window->window, NULL);
 			return;
 		}
 	}
@@ -1108,8 +1178,8 @@ menu_view_log_cb(GtkAction *action, gpoi
 
 	pidgin_log_show(type, name, account);
 
-	gdk_window_set_cursor(gtk_widget_get_window(gtkblist->window), NULL);
-	gdk_window_set_cursor(gtk_widget_get_window(win->window), NULL);
+	gdk_window_set_cursor(gtkblist->window->window, NULL);
+	gdk_window_set_cursor(win->window->window, NULL);
 }
 
 static void
@@ -1155,20 +1225,25 @@ menu_send_file_cb(GtkAction *action, gpo
 	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);
 	}
 
 }
 
 static void
-menu_get_attention_cb(GtkAction *ation, gpointer data)
+menu_get_attention_cb(GObject *obj, gpointer data)
 {
 	PidginWindow *win = data;
 	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 ((GtkAction *)obj == win->menu.get_attention)
+			index = 0;
+		else
+			index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "index"));
+		purple_prpl_send_attention(purple_conversation_get_connection(conv),
+			purple_conversation_get_name(conv), index);
 	}
 }
 
@@ -1364,16 +1439,14 @@ menu_logging_cb(GtkAction *action, gpoin
 
 		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. */
@@ -1381,7 +1454,7 @@ menu_logging_cb(GtkAction *action, gpoin
 	}
 
 	/* 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"))
@@ -1453,7 +1526,7 @@ chat_do_im(PidginConversation *gtkconv, 
 	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,
@@ -1504,12 +1577,12 @@ menu_chat_send_file_cb(GtkWidget *w, Pid
 	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,
@@ -1530,32 +1603,6 @@ static void
 }
 
 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;
@@ -1578,7 +1625,7 @@ get_mark_for_user(PidginConversation *gt
 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);
 
@@ -1589,6 +1636,8 @@ menu_last_said_cb(GtkWidget *w, PidginCo
 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;
 
@@ -1599,6 +1648,7 @@ menu_last_said_cb(GtkWidget *w, PidginCo
 		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 *
@@ -1607,12 +1657,13 @@ create_chat_menu(PurpleConversation *con
 	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,
@@ -1621,7 +1672,7 @@ create_chat_menu(PurpleConversation *con
 	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();
@@ -1686,18 +1737,8 @@ create_chat_menu(PurpleConversation *con
 			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
@@ -1718,8 +1759,8 @@ create_chat_menu(PurpleConversation *con
 
 	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);
@@ -1745,7 +1786,7 @@ gtkconv_chat_popup_menu_cb(GtkWidget *wi
 	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));
 
@@ -1781,7 +1822,7 @@ right_click_chat_cb(GtkWidget *widget, G
 
 	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));
 
@@ -1813,10 +1854,13 @@ right_click_chat_cb(GtkWidget *widget, G
 		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,
@@ -1893,8 +1937,8 @@ gtkconv_cycle_focus(PidginConversation *
 		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;
@@ -1932,8 +1976,8 @@ conv_keypress_common(PidginConversation 
 	/* If CTRL was held down... */
 	if (event->state & GDK_CONTROL_MASK) {
 		switch (event->keyval) {
-			case GDK_KEY_Page_Down:
-			case GDK_KEY_KP_Page_Down:
+			case GDK_Page_Down:
+ 			case GDK_KP_Page_Down:
 			case ']':
 				if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv + 1))
 					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0);
@@ -1942,8 +1986,8 @@ conv_keypress_common(PidginConversation 
 				return TRUE;
 				break;
 
-			case GDK_KEY_Page_Up:
-			case GDK_KEY_KP_Page_Up:
+			case GDK_Page_Up:
+ 			case GDK_KP_Page_Up:
 			case '[':
 				if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv - 1))
 					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1);
@@ -1952,9 +1996,9 @@ conv_keypress_common(PidginConversation 
 				return TRUE;
 				break;
 
-			case GDK_KEY_Tab:
-			case GDK_KEY_KP_Tab:
-			case GDK_KEY_ISO_Left_Tab:
+			case GDK_Tab:
+			case GDK_KP_Tab:
+			case GDK_ISO_Left_Tab:
 				if (event->state & GDK_SHIFT_MASK) {
 					move_to_next_unread_tab(gtkconv, FALSE);
 				} else {
@@ -1964,20 +2008,20 @@ conv_keypress_common(PidginConversation 
 				return TRUE;
 				break;
 
-			case GDK_KEY_comma:
+			case GDK_comma:
 				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
 						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
 						curconv - 1);
 				return TRUE;
 				break;
 
-			case GDK_KEY_period:
+			case GDK_period:
 				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
 						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
 						(curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook)));
 				return TRUE;
 				break;
-			case GDK_KEY_F6:
+			case GDK_F6:
 				if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD))
 					return TRUE;
 				break;
@@ -2001,13 +2045,13 @@ conv_keypress_common(PidginConversation 
 	else
 	{
 		switch (event->keyval) {
-		case GDK_KEY_F2:
+		case GDK_F2:
 			if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) {
 				infopane_entry_activate(gtkconv);
 				return TRUE;
 			}
 			break;
-		case GDK_KEY_F6:
+		case GDK_F6:
 			if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD))
 				return TRUE;
 			break;
@@ -2031,7 +2075,7 @@ entry_key_press_cb(GtkWidget *entry, Gdk
 	/* If CTRL was held down... */
 	if (event->state & GDK_CONTROL_MASK) {
 		switch (event->keyval) {
-			case GDK_KEY_Up:
+			case GDK_Up:
 				if (!gtkconv->send_history)
 					break;
 
@@ -2082,7 +2126,7 @@ entry_key_press_cb(GtkWidget *entry, Gdk
 				return TRUE;
 				break;
 
-			case GDK_KEY_Down:
+			case GDK_Down:
 				if (!gtkconv->send_history)
 					break;
 
@@ -2135,9 +2179,9 @@ entry_key_press_cb(GtkWidget *entry, Gdk
 	/* If neither CTRL nor ALT were held down... */
 	else {
 		switch (event->keyval) {
-		case GDK_KEY_Tab:
-		case GDK_KEY_KP_Tab:
-		case GDK_KEY_ISO_Left_Tab:
+		case GDK_Tab:
+		case GDK_KP_Tab:
+		case GDK_ISO_Left_Tab:
 			if (gtkconv->entry != entry)
 				break;
 			{
@@ -2149,15 +2193,21 @@ entry_key_press_cb(GtkWidget *entry, Gdk
 			}
 			break;
 
-		case GDK_KEY_Page_Up:
-		case GDK_KEY_KP_Page_Up:
+		case GDK_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_KEY_Page_Down:
-		case GDK_KEY_KP_Page_Down:
+		case GDK_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;
 
@@ -2200,26 +2250,26 @@ refocus_entry_cb(GtkWidget *widget, GdkE
 
 	/* If we have a valid key for the conversation display, then exit */
 	if ((event->state & GDK_CONTROL_MASK) ||
-		(event->keyval == GDK_KEY_F6) ||
-		(event->keyval == GDK_KEY_F10) ||
-		(event->keyval == GDK_KEY_Shift_L) ||
-		(event->keyval == GDK_KEY_Shift_R) ||
-		(event->keyval == GDK_KEY_Control_L) ||
-		(event->keyval == GDK_KEY_Control_R) ||
-		(event->keyval == GDK_KEY_Escape) ||
-		(event->keyval == GDK_KEY_Up) ||
-		(event->keyval == GDK_KEY_Down) ||
-		(event->keyval == GDK_KEY_Left) ||
-		(event->keyval == GDK_KEY_Right) ||
-		(event->keyval == GDK_KEY_Page_Up) ||
-		(event->keyval == GDK_KEY_KP_Page_Up) ||
-		(event->keyval == GDK_KEY_Page_Down) ||
-		(event->keyval == GDK_KEY_KP_Page_Down) ||
-		(event->keyval == GDK_KEY_Home) ||
-		(event->keyval == GDK_KEY_End) ||
-		(event->keyval == GDK_KEY_Tab) ||
-		(event->keyval == GDK_KEY_KP_Tab) ||
-		(event->keyval == GDK_KEY_ISO_Left_Tab))
+		(event->keyval == GDK_F6) ||
+		(event->keyval == GDK_F10) ||
+		(event->keyval == GDK_Shift_L) ||
+		(event->keyval == GDK_Shift_R) ||
+		(event->keyval == GDK_Control_L) ||
+		(event->keyval == GDK_Control_R) ||
+		(event->keyval == GDK_Escape) ||
+		(event->keyval == GDK_Up) ||
+		(event->keyval == GDK_Down) ||
+		(event->keyval == GDK_Left) ||
+		(event->keyval == GDK_Right) ||
+		(event->keyval == GDK_Page_Up) ||
+		(event->keyval == GDK_KP_Page_Up) ||
+		(event->keyval == GDK_Page_Down) ||
+		(event->keyval == GDK_KP_Page_Down) ||
+		(event->keyval == GDK_Home) ||
+		(event->keyval == GDK_End) ||
+		(event->keyval == GDK_Tab) ||
+		(event->keyval == GDK_KP_Tab) ||
+		(event->keyval == GDK_ISO_Left_Tab))
 	{
 		if (event->type == GDK_KEY_PRESS)
 			return conv_keypress_common(gtkconv, event);
@@ -2244,6 +2294,7 @@ pidgin_conv_switch_active_conversation(P
 	PurpleConversation *old_conv;
 	GtkIMHtml *entry;
 	const char *protocol_name;
+	PurpleConnectionFlags features;
 
 	g_return_if_fail(conv != NULL);
 
@@ -2265,14 +2316,15 @@ pidgin_conv_switch_active_conversation(P
 		gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(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);
+	/* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */
 
-	if (!(conv->features & PURPLE_CONNECTION_HTML))
+	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
@@ -2312,12 +2364,12 @@ pidgin_conv_switch_active_conversation(P
 
 		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);
@@ -2335,7 +2387,7 @@ pidgin_conv_switch_active_conversation(P
 		 * 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);
@@ -2400,7 +2452,7 @@ delete_text_cb(GtkTextBuffer *textbuffer
 		/* 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);
 	}
@@ -2450,7 +2502,8 @@ pidgin_conv_get_tab_icons(PurpleConversa
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
 		PurpleBuddy *b = purple_find_buddy(account, name);
 		if (b != NULL) {
-			PurplePresence *p = purple_buddy_get_presence(b);
+			PurplePresence *p;
+			p = purple_buddy_get_presence(b);
 			if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY))
 				return away_list;
 			if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE))
@@ -2564,7 +2617,7 @@ update_tab_icon(PurpleConversation *conv
 	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);
 	}
@@ -2585,7 +2638,7 @@ update_tab_icon(PurpleConversation *conv
 		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;
 	}
@@ -2641,7 +2694,7 @@ redraw_icon(gpointer data)
 	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;
 	}
@@ -2686,7 +2739,7 @@ static void
 }
 
 static void
-start_anim(GtkWidget *widget, PidginConversation *gtkconv)
+start_anim(GtkObject *obj, PidginConversation *gtkconv)
 {
 	int delay;
 
@@ -2848,18 +2901,18 @@ icon_menu_save_cb(GtkWidget *widget, Pid
 
 	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);
 }
 
 static void
-stop_anim(GtkWidget *widget, PidginConversation *gtkconv)
+stop_anim(GtkObject *obj, PidginConversation *gtkconv)
 {
 	if (gtkconv->u.im->icon_timer != 0)
 		g_source_remove(gtkconv->u.im->icon_timer);
@@ -2881,7 +2934,7 @@ static gboolean
 }
 
 static gboolean
-icon_menu(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv)
+icon_menu(GtkObject *obj, GdkEventButton *e, PidginConversation *gtkconv)
 {
 	static GtkWidget *menu = NULL;
 	PurpleConversation *conv;
@@ -3075,14 +3128,13 @@ pidgin_conv_get_window(PidginConversatio
 	return gtkconv->win;
 }
 
-#if 1
-
 static GtkActionEntry menu_entries[] =
 /* TODO: fill out tooltips... */
 {
 	/* Conversation menu */
 	{ "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL },
 	{ "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, G_CALLBACK(menu_new_conv_cb) },
+	{ "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), NULL, NULL, G_CALLBACK(menu_join_chat_cb) },
 	{ "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) },
 	{ "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) },
 	{ "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) },
@@ -3127,6 +3179,7 @@ static const char *conversation_menu =
 	"<menubar name='Conversation'>"
 		"<menu action='ConversationMenu'>"
 			"<menuitem action='NewInstantMessage'/>"
+			"<menuitem action='JoinAChat'/>"
 			"<separator/>"
 			"<menuitem action='Find'/>"
 			"<menuitem action='ViewLog'/>"
@@ -3168,86 +3221,6 @@ static const char *conversation_menu =
 	"</menubar>"
 "</ui>";
 
-#else
-
-static GtkItemFactoryEntry menu_items[] =
-{
-	/* Conversation menu */
-	{ N_("/_Conversation"), NULL, NULL, 0, "<Branch>", NULL },
-
-	{ N_("/Conversation/New Instant _Message..."), "<CTL>M", menu_new_conv_cb,
-			0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW },
-	{ N_("/Conversation/Join a _Chat..."), NULL, menu_join_chat_cb,
-			0, "<StockItem>", PIDGIN_STOCK_CHAT },
-
-	{ "/Conversation/sep0", NULL, NULL, 0, "<Separator>", NULL },
-
-	{ N_("/Conversation/_Find..."), NULL, menu_find_cb, 0,
-			"<StockItem>", GTK_STOCK_FIND },
-	{ N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "<Item>", NULL },
-	{ N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0,
-			"<StockItem>", GTK_STOCK_SAVE_AS },
-	{ N_("/Conversation/Clea_r Scrollback"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR },
-
-	{ "/Conversation/sep1", NULL, NULL, 0, "<Separator>", NULL },
-
-#ifdef USE_VV
-	{ N_("/Conversation/M_edia"), NULL, NULL, 0, "<Branch>", NULL },
-
-	{ N_("/Conversation/Media/_Audio Call"), NULL, menu_initiate_media_call_cb, 0,
-		"<StockItem>", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL },
-	{ N_("/Conversation/Media/_Video Call"), NULL, menu_initiate_media_call_cb, 1,
-		"<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
-	{ N_("/Conversation/Media/Audio\\/Video _Call"), NULL, menu_initiate_media_call_cb, 2,
-		"<StockItem>", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL },
-#endif
-
-	{ N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_FILE },
-	{ N_("/Conversation/Get _Attention"), NULL, menu_get_attention_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION },
-	{ N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb,
-			0, "<Item>", NULL },
-	{ N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0,
-			"<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO },
-	{ N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0,
-			"<Item>", NULL },
-	{ N_("/Conversation/M_ore"), NULL, NULL, 0, "<Branch>", NULL },
-
-	{ "/Conversation/sep2", NULL, NULL, 0, "<Separator>", NULL },
-
-	{ N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0,
-			"<Item>", NULL },
-	{ N_("/Conversation/_Block..."), NULL, menu_block_cb, 0,
-			"<StockItem>", PIDGIN_STOCK_TOOLBAR_BLOCK },
-	{ N_("/Conversation/_Unblock..."), NULL, menu_unblock_cb, 0,
-			"<StockItem>", PIDGIN_STOCK_TOOLBAR_UNBLOCK },
-	{ N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0,
-			"<StockItem>", GTK_STOCK_ADD },
-	{ N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0,
-			"<StockItem>", GTK_STOCK_REMOVE },
-
-	{ "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL },
-
-	{ N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0,
-		"<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_LINK },
-	{ N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0,
-		"<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE },
-
-	{ "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL },
-
-
-	{ N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0,
-			"<StockItem>", GTK_STOCK_CLOSE },
-
-	/* Options */
-	{ N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>", NULL },
-	{ N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>", NULL },
-	{ "/Options/sep0", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>", NULL },
-	{ N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "<CheckItem>", NULL },
-};
-#endif
-
 static void
 sound_method_pref_changed_cb(const char *name, PurplePrefType type,
 							 gconstpointer value, gpointer data)
@@ -3278,21 +3251,23 @@ populate_menu_with_options(GtkWidget *me
 {
 	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);
+		chat = purple_blist_find_chat(account, purple_conversation_get_name(conv));
 
-		if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
-			chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat");
+		if ((chat == NULL) && (gtkconv->webview != NULL)) {
+			chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat");
 		}
 
-		if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
+		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));
@@ -3307,30 +3282,30 @@ populate_menu_with_options(GtkWidget *me
 				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);
 			}
 		}
@@ -3349,8 +3324,8 @@ populate_menu_with_options(GtkWidget *me
 			/* 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);
 	}
 
@@ -3402,7 +3377,7 @@ regenerate_media_items(PidginWindow *win
 		gtk_action_set_sensitive(win->video_call,
 				caps & PURPLE_MEDIA_CAPS_VIDEO
 				? TRUE : FALSE);
-		gtk_action_set_sensitive(win->audio_video_call,
+		gtk_action_set_sensitive(win->audio_video_call, 
 				caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO
 				? TRUE : FALSE);
 	} else if (purple_conversation_get_type(conv)
@@ -3420,12 +3395,65 @@ static void
 }
 
 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;
 	PidginConversation *gtkconv;
 	GList *list;
-#if GTK_CHECK_VERSION(2,6,0)
 	GtkWidget *more_menu;
 
 	gtkconv = pidgin_conv_window_get_active_gtkconv(win);
@@ -3433,10 +3461,6 @@ regenerate_options_items(PidginWindow *w
 	                                      "/Conversation/ConversationMenu/MoreMenu");
 	gtk_widget_show(more_menu);
 	menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(more_menu));
-#else
-	gtkconv = pidgin_conv_window_get_active_gtkconv(win);
-	menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More"));
-#endif
 
 	/* Remove the previous entries */
 	for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; )
@@ -3492,12 +3516,8 @@ regenerate_plugins_items(PidginWindow *w
 		action_items = g_list_delete_link(action_items, action_items);
 	}
 
-#if GTK_CHECK_VERSION(2,6,0)
 	item = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/OptionsMenu");
 	menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
-#else
-	menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options"));
-#endif
 
 	list = purple_conversation_get_extended_menu(conv);
 	if (list) {
@@ -3521,6 +3541,7 @@ static void menubar_activated(GtkWidget 
 	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. */
@@ -3606,9 +3627,9 @@ setup_menubar(PidginWindow *win)
 		gtk_ui_manager_get_action(win->menu.ui,
 		                          "/Conversation/ConversationMenu/SendFile");
 
-	g_object_set_data(G_OBJECT(win->window), "get_attention",
+	win->menu.get_attention =
 		gtk_ui_manager_get_action(win->menu.ui,
-			"/Conversation/ConversationMenu/GetAttention"));
+		                          "/Conversation/ConversationMenu/GetAttention");
 
 	win->menu.add_pounce =
 		gtk_ui_manager_get_action(win->menu.ui,
@@ -3718,7 +3739,7 @@ got_typing_keypress(PidginConversation *
 				  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);
@@ -3754,10 +3775,10 @@ typing_animation(gpointer data) {
 		break;
 	}
 	if (gtkwin->menu.typing_icon == NULL) {
-		gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
-		pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray),
-		                        gtkwin->menu.typing_icon,
-		                        _("User is typing..."));
+		 gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
+		 pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray),
+                                                                  gtkwin->menu.typing_icon,
+                                                                  _("User is typing..."));
 	} else {
 		gtk_image_set_from_stock(GTK_IMAGE(gtkwin->menu.typing_icon), stock_id, GTK_ICON_SIZE_MENU);
 	}
@@ -3769,6 +3790,8 @@ update_typing_message(PidginConversation
 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;
 
@@ -3801,6 +3824,7 @@ update_typing_message(PidginConversation
 		gtk_text_buffer_get_end_iter(buffer, &iter);
 		gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE);
 	}
+#endif /* if 0 */
 }
 
 static void
@@ -3857,10 +3881,9 @@ update_send_to_selection(PidginWindow *w
 	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;
 
-#if 0 /* TODO */
 	gtk_widget_show(win->menu.send_to);
 
 	menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to));
@@ -3882,7 +3905,6 @@ update_send_to_selection(PidginWindow *w
 			break;
 		}
 	}
-#endif
 
 	return FALSE;
 }
@@ -3992,7 +4014,6 @@ generate_send_to_items(PidginWindow *win
 static void
 generate_send_to_items(PidginWindow *win)
 {
-#if 0 /* TODO */
 	GtkWidget *menu;
 	GSList *group = NULL;
 	GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
@@ -4019,8 +4040,8 @@ generate_send_to_items(PidginWindow *win
 
 	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)
 		{
@@ -4044,7 +4065,8 @@ generate_send_to_items(PidginWindow *win
 						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);
@@ -4077,7 +4099,6 @@ generate_send_to_items(PidginWindow *win
 	if (!group)
 		gtk_widget_set_sensitive(win->menu.send_to, FALSE);
 	update_send_to_selection(win);
-#endif
 }
 
 static const char *
@@ -4104,10 +4125,11 @@ deleting_chat_buddy_cb(PurpleConvChatBud
 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);
 	}
 }
 
@@ -4126,20 +4148,21 @@ add_chat_buddy_common(PurpleConversation
 	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);
+	gc      = purple_conversation_get_connection(conv);
 
-	if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)))
+	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));
@@ -4147,20 +4170,23 @@ add_chat_buddy_common(PurpleConversation
 
 	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)))
@@ -4188,13 +4214,13 @@ add_chat_buddy_common(PurpleConversation
 			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)
@@ -4224,7 +4250,7 @@ tab_complete_process_item(int *most_matc
  */
 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))
@@ -4346,7 +4372,7 @@ tab_complete(PurpleConversation *conv)
 		/* 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));
 		}
 
 
@@ -4444,9 +4470,9 @@ static void topic_callback(GtkWidget *w,
 	char *new_topic;
 	const char *current_topic;
 
-	gc      = purple_conversation_get_gc(conv);
+	gc      = purple_conversation_get_connection(conv);
 
-	if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)))
+	if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
 		return;
 
 	if(prpl_info->set_chat_topic == NULL)
@@ -4521,6 +4547,7 @@ update_chat_alias(PurpleBuddy *buddy, Pu
 {
 	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;
@@ -4535,23 +4562,23 @@ update_chat_alias(PurpleBuddy *buddy, Pu
 	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);
 				}
 
@@ -4586,10 +4613,10 @@ blist_node_aliased_cb(PurpleBlistNode *n
 	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;
@@ -4609,7 +4636,7 @@ blist_node_aliased_cb(PurpleBlistNode *n
 	else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
 		update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info);
 	else if (PURPLE_BLIST_NODE_IS_CHAT(node) &&
-			purple_conversation_get_account(conv) == ((PurpleChat*)node)->account)
+			purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node))
 	{
 		if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0)
 			pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE);
@@ -4638,14 +4665,14 @@ buddy_cb_common(PurpleBuddy *buddy, Purp
 	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);
@@ -4724,22 +4751,13 @@ static gboolean resize_imhtml_cb(PidginC
 	GdkRectangle oneline;
 	int height, diff;
 	int pad_top, pad_inside, pad_bottom;
-	int total_height;
-	int max_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;
 	gboolean interior_focus;
 	int focus_width;
-	GtkAllocation imhtml_allocation;
-	GtkAllocation entry_allocation;
-	GtkAllocation lower_hbox_allocation;
 
-	gtk_widget_get_allocation(gtkconv->imhtml, &imhtml_allocation);
-	gtk_widget_get_allocation(gtkconv->entry, &entry_allocation);
-	gtk_widget_get_allocation(gtkconv->lower_hbox, &lower_hbox_allocation);
-	total_height = imhtml_allocation.height + entry_allocation.height;
-	max_height = total_height / 2;
-
 	pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
 	pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry));
 	pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry));
@@ -4772,15 +4790,12 @@ static gboolean resize_imhtml_cb(PidginC
 	if (!interior_focus)
 		height += 2 * focus_width;
 
-	diff = height - entry_allocation.height;
+	diff = height - gtkconv->entry->allocation.height;
 	if (ABS(diff) < oneline.height / 2)
 		return FALSE;
 
-	purple_debug_info("pidgin", "resizing to %d, %d lines, diff %d\n",
-	                  diff + lower_hbox_allocation.height, min_lines, diff);
-
 	gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
-		diff + lower_hbox_allocation.height);
+		diff + gtkconv->lower_hbox->allocation.height);
 
 	return FALSE;
 }
@@ -4808,8 +4823,8 @@ setup_chat_topic(PidginConversation *gtk
 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;
@@ -4827,7 +4842,7 @@ setup_chat_topic(PidginConversation *gtk
 		if(prpl_info->set_chat_topic == NULL) {
 			gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE);
 		} else {
-			g_signal_connect(GTK_WIDGET(gtkchat->topic_text), "activate",
+			g_signal_connect(GTK_OBJECT(gtkchat->topic_text), "activate",
 					G_CALLBACK(topic_callback), gtkconv);
 		}
 
@@ -4850,7 +4865,7 @@ pidgin_conv_userlist_create_tooltip(GtkW
 	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))
@@ -4858,8 +4873,8 @@ pidgin_conv_userlist_create_tooltip(GtkW
 
 	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);
 
@@ -4960,7 +4975,7 @@ setup_chat_userlist(PidginConversation *
 
 	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);
 }
@@ -4974,15 +4989,15 @@ pidgin_conv_create_tooltip(GtkWidget *ti
 
 	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
 	}
 
@@ -4997,8 +5012,8 @@ pidgin_conv_end_quickfind(PidginConversa
 {
 	gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL);
 
-	gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml));
-	gtk_widget_hide(gtkconv->quickfind.container);
+	webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview));
+	gtk_widget_hide_all(gtkconv->quickfind.container);
 
 	gtk_widget_grab_focus(gtkconv->entry);
 	return TRUE;
@@ -5008,9 +5023,9 @@ quickfind_process_input(GtkWidget *entry
 quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv)
 {
 	switch (event->keyval) {
-		case GDK_KEY_Return:
-		case GDK_KEY_KP_Enter:
-			if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) {
+		case GDK_Return:
+		case GDK_KP_Enter:
+			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;
@@ -5020,7 +5035,7 @@ quickfind_process_input(GtkWidget *entry
 				gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, &col);
 			}
 			break;
-		case GDK_KEY_Escape:
+		case GDK_Escape:
 			pidgin_conv_end_quickfind(gtkconv);
 			break;
 		default:
@@ -5064,16 +5079,185 @@ pidgin_conv_setup_quickfind(PidginConver
 
 /* }}} */
 
+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 if (g_str_has_prefix(cur, "%dateOpened%")) {
+			replace = purple_date_format_short(NULL);
+
+		} 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 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);
@@ -5163,9 +5347,41 @@ setup_common_pane(PidginConversation *gt
 	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;
 
@@ -5183,19 +5399,16 @@ setup_common_pane(PidginConversation *gt
 	} else {
 		gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 	}
-	gtk_widget_show(frame);
+	gtk_widget_show_all(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);
+	gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview");
+	g_object_set_data(G_OBJECT(gtkconv->webview), "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",
+	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);
@@ -5211,7 +5424,7 @@ setup_common_pane(PidginConversation *gt
 
 	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);
@@ -5258,11 +5471,9 @@ conv_dnd_recv(GtkWidget *widget, GdkDrag
 	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;
-	GdkAtom target = gtk_selection_data_get_target(sd);
-	const guchar *data = gtk_selection_data_get_data(sd);
+	PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
 
-	if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
+	if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
 	{
 		PurpleBlistNode *n = NULL;
 		PurpleBuddy *b;
@@ -5270,7 +5481,7 @@ conv_dnd_recv(GtkWidget *widget, GdkDrag
 		PurpleAccount *buddyaccount;
 		const char *buddyname;
 
-		n = *(PurpleBlistNode **) data;
+		n = *(PurpleBlistNode **)sd->data;
 
 		if (PURPLE_BLIST_NODE_IS_CONTACT(n))
 			b = purple_contact_get_priority_buddy((PurpleContact*)n);
@@ -5318,17 +5529,16 @@ conv_dnd_recv(GtkWidget *widget, GdkDrag
 			pidgin_conv_window_switch_gtkconv(win, gtkconv);
 		}
 
-		gtk_drag_finish(dc, TRUE,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
-	else if (target == gdk_atom_intern("application/x-im-contact", FALSE))
+	else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
 	{
 		char *protocol = NULL;
 		char *username = NULL;
 		PurpleAccount *account;
 		PidginConversation *gtkconv;
 
-		if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account,
+		if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account,
 						&protocol, &username, NULL))
 		{
 			if (account == NULL)
@@ -5359,14 +5569,12 @@ conv_dnd_recv(GtkWidget *widget, GdkDrag
 		g_free(username);
 		g_free(protocol);
 
-		gtk_drag_finish(dc, TRUE,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
-	else if (target == gdk_atom_intern("text/uri-list", FALSE)) {
+	else if (sd->target == gdk_atom_intern("text/uri-list", FALSE)) {
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 			pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv));
-		gtk_drag_finish(dc, TRUE,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
 	else
 		gtk_drag_finish(dc, FALSE, FALSE, t);
@@ -5383,7 +5591,7 @@ pidgin_conv_find_gtkconv(PurpleConversat
 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;
 
@@ -5397,9 +5605,9 @@ pidgin_conv_find_gtkconv(PurpleConversat
 	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);
 		}
 	}
 
@@ -5441,6 +5649,8 @@ static void set_typing_font(GtkWidget *w
 
 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;
@@ -5471,6 +5681,7 @@ static void set_typing_font(GtkWidget *w
 	}
 
 	g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv);
+#endif /* if 0 */
 }
 
 /**************************************************************************
@@ -5480,14 +5691,14 @@ private_gtkconv_new(PurpleConversation *
 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;
 	PurpleBlistNode *convnode;
-	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);
@@ -5495,7 +5706,7 @@ private_gtkconv_new(PurpleConversation *
 	}
 
 	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);
@@ -5506,6 +5717,11 @@ private_gtkconv_new(PurpleConversation *
 #endif
 	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));
@@ -5514,9 +5730,6 @@ private_gtkconv_new(PurpleConversation *
 	}
 	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);
@@ -5524,7 +5737,7 @@ private_gtkconv_new(PurpleConversation *
 			g_free(gtkconv->u.im);
 
 		g_free(gtkconv);
-		conv->ui_data = NULL;
+		purple_conversation_set_ui_data(conv, NULL);
 		return;
 	}
 
@@ -5539,7 +5752,7 @@ private_gtkconv_new(PurpleConversation *
 	                  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);
 
@@ -5551,12 +5764,12 @@ private_gtkconv_new(PurpleConversation *
 	                 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);
@@ -5569,11 +5782,9 @@ private_gtkconv_new(PurpleConversation *
 	if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
 		gtkconv->make_sound = TRUE;
 
-	if (convnode != NULL &&
-	    (value = g_hash_table_lookup(convnode->settings, "enable-logging")) &&
-	    purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN)
-	{
-		purple_conversation_set_logging(conv, purple_value_get_boolean(value));
+	if (convnode != NULL) {
+		gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging");
+		purple_conversation_set_logging(conv, logging);
 	}
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"))
@@ -5586,10 +5797,6 @@ private_gtkconv_new(PurpleConversation *
 	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),
@@ -5602,10 +5809,10 @@ private_gtkconv_new(PurpleConversation *
 
 	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]);
+		nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]);
 	}
 
-	if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
+	if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
 		pidgin_themes_smiley_themeize_custom(gtkconv->entry);
 }
 
@@ -5718,6 +5925,10 @@ pidgin_conv_destroy(PurpleConversation *
 		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);
 }
 
@@ -5745,6 +5956,7 @@ pidgin_conv_write_im(PurpleConversation 
 	purple_conversation_write(conv, who, message, flags, mtime);
 }
 
+#if 0
 static const char *
 get_text_tag_color(GtkTextTag *tag)
 {
@@ -5772,37 +5984,33 @@ static gboolean buddytag_event(GtkTextTa
 		GdkEventButton *btn_event = (GdkEventButton*) event;
 		PurpleConversation *conv = data;
 		char *buddyname;
-		gchar *name;
 
-		g_object_get(G_OBJECT(tag), "name", &name, NULL);
-
 		/* strlen("BUDDY " or "HILIT ") == 6 */
-		g_return_val_if_fail((name != NULL) && (strlen(name) > 6), FALSE);
+		g_return_val_if_fail((tag->name != NULL)
+				&& (strlen(tag->name) > 6), FALSE);
 
-		buddyname = name + 6;
+		buddyname = (tag->name) + 6;
 
 		/* emit chat-nick-clicked signal */
 		if (event->type == GDK_BUTTON_PRESS) {
 			gint plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
 						pidgin_conversations_get_handle(), "chat-nick-clicked",
 						data, buddyname, btn_event->button));
-			if (plugin_return) {
-				g_free(name);
+			if (plugin_return)
 				return TRUE;
-			}
 		}
 
-		if (btn_event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
+		if (btn_event->button == 1 &&
+				event->type == GDK_2BUTTON_PRESS) {
 			chat_do_im(PIDGIN_CONVERSATION(conv), buddyname);
-			g_free(name);
-
 			return TRUE;
-		} else if (btn_event->button == 2 && event->type == GDK_2BUTTON_PRESS) {
+		} else if (btn_event->button == 2
+				&& event->type == GDK_2BUTTON_PRESS) {
 			chat_do_info(PIDGIN_CONVERSATION(conv), buddyname);
-			g_free(name);
 
 			return TRUE;
-		} else if (btn_event->button == 3 && event->type == GDK_BUTTON_PRESS) {
+		} else if (btn_event->button == 3
+				&& event->type == GDK_BUTTON_PRESS) {
 			GtkTextIter start, end;
 
 			/* we shouldn't display the popup
@@ -5812,7 +6020,7 @@ static gboolean buddytag_event(GtkTextTa
 						&start, &end)) {
 				GtkWidget *menu = NULL;
 				PurpleConnection *gc =
-					purple_conversation_get_gc(conv);
+					purple_conversation_get_connection(conv);
 
 
 				menu = create_chat_menu(conv, buddyname, gc);
@@ -5821,22 +6029,21 @@ static gboolean buddytag_event(GtkTextTa
 						btn_event->button,
 						btn_event->time);
 
-				g_free(name);
-
 				/* Don't propagate the event any further */
 				return TRUE;
 			}
 		}
-
-		g_free(name);
 	}
 
 	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;
@@ -5870,8 +6077,11 @@ static GtkTextTag *get_buddy_tag(PurpleC
 	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);
@@ -5917,7 +6127,112 @@ str_embed_direction_chars(char **str)
 	*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, "%shortTime%")) {
+			replace = purple_utf8_strftime("%H:%M", NULL);
+
+		} else if (g_str_has_prefix(cur, "%userIconPath%")) {
+			if (flags & PURPLE_MESSAGE_SEND) {
+				if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) {
+					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 if (g_str_has_prefix(cur, "%messageDirection%")) {
+			replace = purple_markup_is_rtl(message) ? "rtl" : "ltr";
+
+		} 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,
 						const char *message, PurpleMessageFlags flags,
@@ -5926,24 +6241,32 @@ pidgin_conv_write_conv(PurpleConversatio
 	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);
 	g_return_if_fail(gtkconv != NULL);
@@ -5999,57 +6322,40 @@ pidgin_conv_write_conv(PurpleConversatio
 	}
 	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);
+	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;
 
-	line_count = gtk_text_buffer_get_line_count(
-			gtk_text_view_get_buffer(GTK_TEXT_VIEW(
-				gtkconv->imhtml)));
+	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);
 
-	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;
+	purple_debug_info("webkit", "JS: %s\n", script);
+	gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), script);
 
-		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);
-	}
+	g_free(script);
+	g_free(smileyed);
+	g_free(msg);
+	g_free(escape);
 
-	if (type == PURPLE_CONV_TYPE_CHAT)
-	{
-		/* Create anchor for user */
-		GtkTextIter iter;
-		char *tmp = g_strconcat("user:", name, NULL);
+#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 />");
 
-		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);
-
 	/* First message in a conversation. */
 	if (gtkconv->newday == 0)
 		pidgin_conv_calculate_newday(gtkconv, mtime);
@@ -6091,40 +6397,40 @@ pidgin_conv_write_conv(PurpleConversatio
 		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(""));
@@ -6134,11 +6440,6 @@ pidgin_conv_write_conv(PurpleConversatio
 		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);
@@ -6199,55 +6500,41 @@ pidgin_conv_write_conv(PurpleConversatio
 
 		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_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);
 
-		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);
-
 		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);
@@ -6256,6 +6543,8 @@ pidgin_conv_write_conv(PurpleConversatio
 	g_free(mdate);
 	g_free(sml_attrib);
 
+#endif
+
 	/* Tab highlighting stuff */
 	if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv))
 	{
@@ -6274,11 +6563,13 @@ pidgin_conv_write_conv(PurpleConversatio
 		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"),
@@ -6289,7 +6580,7 @@ static gboolean get_iter_from_chatbuddy(
 
 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;
 
@@ -6373,23 +6664,23 @@ pidgin_conv_chat_rename_user(PurpleConve
 	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter))
 		return;
 
-	old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
-	if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
-		GtkTreeRowReference *ref = old_cbuddy->ui_data;
-
-		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
-		gtk_tree_row_reference_free(ref);
-		old_cbuddy->ui_data = NULL;
-	}
-
 	if ((tag = get_buddy_tag(conv, old_name, 0, FALSE)))
 		g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
 	if ((tag = get_buddy_tag(conv, old_name, PURPLE_MESSAGE_NICK, FALSE)))
 		g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
 
+	old_cbuddy = purple_conv_chat_cb_find(chat, old_name);
 	if (!old_cbuddy)
 		return;
 
+	if (get_iter_from_chatbuddy(old_cbuddy, &iter)) {
+		GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy);
+
+		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+		gtk_tree_row_reference_free(ref);
+		purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL);
+	}
+
 	g_return_if_fail(new_alias != NULL);
 
 	new_cbuddy = purple_conv_chat_cb_find(chat, new_name);
@@ -6473,10 +6764,10 @@ pidgin_conv_chat_update_user(PurpleConve
 
 	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)
@@ -6523,6 +6814,13 @@ static gboolean
 }
 
 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;
@@ -6539,7 +6837,7 @@ pidgin_conv_custom_smiley_add(PurpleConv
 
 	/* 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) {
@@ -6549,7 +6847,7 @@ pidgin_conv_custom_smiley_add(PurpleConv
 		}
 	}
 
-	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 */
@@ -6563,12 +6861,14 @@ pidgin_conv_custom_smiley_write(PurpleCo
 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);
 
@@ -6584,7 +6884,7 @@ pidgin_conv_custom_smiley_write(PurpleCo
 
 	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);
@@ -6597,11 +6897,14 @@ pidgin_conv_custom_smiley_write(PurpleCo
 		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;
@@ -6610,7 +6913,7 @@ pidgin_conv_custom_smiley_close(PurpleCo
 	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);
 
@@ -6638,6 +6941,7 @@ pidgin_conv_custom_smiley_close(PurpleCo
 		g_object_unref(G_OBJECT(smiley->loader));
 		smiley->loader = gdk_pixbuf_loader_new();
 	}
+#endif /* if 0 */
 }
 
 static void
@@ -6665,11 +6969,11 @@ gray_stuff_out(PidginConversation *gtkco
 	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);
@@ -6688,7 +6992,7 @@ gray_stuff_out(PidginConversation *gtkco
 		/* Deal with menu items */
 		gtk_action_set_visible(win->menu.view_log, TRUE);
 		gtk_action_set_visible(win->menu.send_file, TRUE);
-		gtk_action_set_visible(GTK_ACTION(g_object_get_data(G_OBJECT(win->window), "get_attention")), TRUE);
+		gtk_action_set_visible(win->menu.get_attention, TRUE);
 		gtk_action_set_visible(win->menu.add_pounce, TRUE);
 		gtk_action_set_visible(win->menu.get_info, TRUE);
 		gtk_action_set_visible(win->menu.invite, FALSE);
@@ -6717,7 +7021,7 @@ gray_stuff_out(PidginConversation *gtkco
 		/* Deal with menu items */
 		gtk_action_set_visible(win->menu.view_log, TRUE);
 		gtk_action_set_visible(win->menu.send_file, FALSE);
-		gtk_action_set_visible(g_object_get_data(G_OBJECT(win->window), "get_attention"), FALSE);
+		gtk_action_set_visible(win->menu.get_attention, FALSE);
 		gtk_action_set_visible(win->menu.add_pounce, FALSE);
 		gtk_action_set_visible(win->menu.get_info, FALSE);
 		gtk_action_set_visible(win->menu.invite, TRUE);
@@ -6747,31 +7051,35 @@ gray_stuff_out(PidginConversation *gtkco
 		((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 (!(prpl_info->options & OPT_PROTO_IM_IMAGE)
+		 && !(features & PURPLE_CONNECTION_NO_IMAGES)) {
+			features |= PURPLE_CONNECTION_NO_IMAGES;
+			purple_conversation_set_features(conv, features);
+		}
 
-		if(conv->features & PURPLE_CONNECTION_NO_IMAGES)
+		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;
@@ -6785,17 +7093,17 @@ gray_stuff_out(PidginConversation *gtkco
 		gtk_action_set_sensitive(win->menu.add_pounce, TRUE);
 		gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
 		gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
-		gtk_action_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML));
-		gtk_action_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES));
+		gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML));
+		gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 		{
-			gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL));
+			gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL));
 			gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL));
 			gtk_action_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_action_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL));
+			gtk_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL));
 			gtk_action_set_sensitive(win->menu.alias,
 									 (account != NULL) &&
 									 (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL));
@@ -6816,8 +7124,7 @@ gray_stuff_out(PidginConversation *gtkco
 		/* Then deal with menu items */
 		gtk_action_set_sensitive(win->menu.view_log, TRUE);
 		gtk_action_set_sensitive(win->menu.send_file, FALSE);
-		gtk_action_set_sensitive(g_object_get_data(G_OBJECT(win->window),
-			"get_attention"), FALSE);
+		gtk_action_set_sensitive(win->menu.get_attention, FALSE);
 		gtk_action_set_sensitive(win->menu.add_pounce, TRUE);
 		gtk_action_set_sensitive(win->menu.get_info, FALSE);
 		gtk_action_set_sensitive(win->menu.invite, FALSE);
@@ -6837,7 +7144,7 @@ gray_stuff_out(PidginConversation *gtkco
 		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);
 
@@ -6885,6 +7192,7 @@ pidgin_conv_update_fields(PurpleConversa
 	{
 		gray_stuff_out(PIDGIN_CONVERSATION(conv));
 		generate_send_to_items(win);
+		regenerate_plugins_items(win);
 	}
 
 	if (fields & PIDGIN_CONV_TAB_ICON)
@@ -6915,12 +7223,14 @@ pidgin_conv_update_fields(PurpleConversa
 		}
 	}
 
+#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) ||
-			(fields & PIDGIN_CONV_TOPIC))
+    			(fields & PIDGIN_CONV_TOPIC))
 	{
 		char *title;
 		PurpleConvIm *im = NULL;
@@ -6943,7 +7253,7 @@ pidgin_conv_update_fields(PurpleConversa
 			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 {
@@ -6988,7 +7298,7 @@ pidgin_conv_update_fields(PurpleConversa
 			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";
@@ -7200,7 +7510,7 @@ pidgin_conv_update_buddy_icon(PurpleConv
 	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));
@@ -7286,7 +7596,7 @@ pidgin_conv_update_buddy_icon(PurpleConv
 	gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event);
 	gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE);
 	gtk_widget_add_events(event,
-	                      GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
+                              GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
 	g_signal_connect(G_OBJECT(event), "button-press-event",
 					 G_CALLBACK(icon_menu), gtkconv);
 
@@ -7328,14 +7638,11 @@ pidgin_conv_xy_to_right_infopane(PidginW
 {
 	gint pane_x, pane_y, x_rel;
 	PidginConversation *gtkconv;
-	GtkAllocation allocation;
 
-	gdk_window_get_origin(gtk_widget_get_window(win->notebook),
-	                      &pane_x, &pane_y);
+	gdk_window_get_origin(win->notebook->window, &pane_x, &pane_y);
 	x_rel = x - pane_x;
 	gtkconv = pidgin_conv_window_get_active_gtkconv(win);
-	gtk_widget_get_allocation(gtkconv->infopane, &allocation);
-	return (x_rel > allocation.x + allocation.width / 2);
+	return (x_rel > gtkconv->infopane->allocation.x + gtkconv->infopane->allocation.width / 2);
 }
 
 int
@@ -7353,7 +7660,7 @@ pidgin_conv_get_tab_at_xy(PidginWindow *
 
 	notebook = GTK_NOTEBOOK(win->notebook);
 
-	gdk_window_get_origin(gtk_widget_get_window(win->notebook), &nb_x, &nb_y);
+	gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y);
 	x_rel = x - nb_x;
 	y_rel = y - nb_y;
 
@@ -7363,32 +7670,30 @@ pidgin_conv_get_tab_at_xy(PidginWindow *
 	count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
 
 	for (i = 0; i < count; i++) {
-		GtkAllocation allocation;
 
 		page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
 		tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
-		gtk_widget_get_allocation(tab, &allocation);
 
 		/* Make sure the tab is not hidden beyond an arrow */
 		if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook))
 			continue;
 
 		if (horiz) {
-			if (x_rel >= allocation.x - PIDGIN_HIG_BOX_SPACE &&
-					x_rel <= allocation.x + allocation.width + PIDGIN_HIG_BOX_SPACE) {
+			if (x_rel >= tab->allocation.x - PIDGIN_HIG_BOX_SPACE &&
+					x_rel <= tab->allocation.x + tab->allocation.width + PIDGIN_HIG_BOX_SPACE) {
 				page_num = i;
 
-				if (to_right && x_rel >= allocation.x + allocation.width/2)
+				if (to_right && x_rel >= tab->allocation.x + tab->allocation.width/2)
 					*to_right = TRUE;
 
 				break;
 			}
 		} else {
-			if (y_rel >= allocation.y - PIDGIN_HIG_BOX_SPACE &&
-					y_rel <= allocation.y + allocation.height + PIDGIN_HIG_BOX_SPACE) {
+			if (y_rel >= tab->allocation.y - PIDGIN_HIG_BOX_SPACE &&
+					y_rel <= tab->allocation.y + tab->allocation.height + PIDGIN_HIG_BOX_SPACE) {
 				page_num = i;
 
-				if (to_right && y_rel >= allocation.y + allocation.height/2)
+				if (to_right && y_rel >= tab->allocation.y + tab->allocation.height/2)
 					*to_right = TRUE;
 
 				break;
@@ -7499,8 +7804,11 @@ show_timestamps_pref_cb(const char *name
 		        GTK_TOGGLE_ACTION(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 */
 	}
 }
 
@@ -7668,7 +7976,7 @@ hide_new_pref_cb(const char *name, Purpl
 
 		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(
@@ -7708,7 +8016,7 @@ get_gtkconv_with_contact(PurpleContact *
 	{
 		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);
 	}
@@ -7733,16 +8041,18 @@ account_signed_off_cb(PurpleConnection *
 							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;
+				comps = purple_chat_get_components(chat);
 			}
 			serv_join_chat(gc, comps);
 			if (chat == NULL && comps != NULL)
@@ -7809,7 +8119,7 @@ update_buddy_idle_changed(PurpleBuddy *b
 {
 	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);
 }
@@ -7819,7 +8129,7 @@ update_buddy_icon(PurpleBuddy *buddy)
 {
 	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);
 }
@@ -7884,7 +8194,7 @@ message_compare(gconstpointer p1, gconst
 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. */
@@ -7895,16 +8205,22 @@ add_message_history_to_gtkconv(gpointer 
 	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 {
@@ -7927,16 +8243,22 @@ add_message_history_to_gtkconv(gpointer 
 			GList *history = purple_conversation_get_message_history(conv);
 			for (; history; history = history->next) {
 				PurpleConvMessage *msg = history->data;
-				if (msg->when > when)
+				if (purple_conversation_message_get_timestamp(msg) > when)
 					msgs = g_list_prepend(msgs, msg);
 			}
 		}
 		msgs = g_list_sort(msgs, message_compare);
 		for (; msgs; msgs = g_list_delete_link(msgs, msgs)) {
 			PurpleConvMessage *msg = msgs->data;
-			pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when);
+			pidgin_conv_write_conv(
+					purple_conversation_message_get_conv(msg),
+					purple_conversation_message_get_sender(msg),
+					purple_conversation_message_get_alias(msg),
+					purple_conversation_message_get_message(msg),
+					purple_conversation_message_get_flags(msg),
+					purple_conversation_message_get_timestamp(msg));
 		}
-		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR><HR>", 0);
+		gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR><HR>");
 		g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL);
 	}
 
@@ -8012,16 +8334,16 @@ gboolean pidgin_conv_attach_to_conversat
 				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;
@@ -8043,6 +8365,7 @@ pidgin_conversations_init(void)
 
 	/* 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);
@@ -8130,7 +8453,7 @@ pidgin_conversations_init(void)
 	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/blist/show_protocol_icons",
 								show_protocol_icons_pref_cb, NULL);
 	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/hide_new",
-								hide_new_pref_cb, NULL);
+                                hide_new_pref_cb, NULL);
 
 
 
@@ -8287,7 +8610,7 @@ pidgin_conversations_init(void)
 	window_list = g_list_remove(window_list, hidden_convwin);
 
 	purple_signal_connect(purple_accounts_get_handle(), "account-status-changed",
-						handle, PURPLE_CALLBACK(account_status_changed_cb), NULL);
+                        handle, PURPLE_CALLBACK(account_status_changed_cb), NULL);
 
 	/* Callbacks to update a conversation */
 	purple_signal_connect(blist_handle, "blist-node-added", handle,
@@ -8326,6 +8649,8 @@ pidgin_conversations_init(void)
 	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);
@@ -8471,15 +8796,12 @@ build_warn_close_dialog(PidginWindow *gt
 	gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog),
 	                               6);
 	gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE);
-
-	/* TODO: figure out how to set no separator in GTK+ 3.0 */
-#if 0
-	gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog),
-	                             FALSE);
+#if !GTK_CHECK_VERSION(2,22,0)
+	gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), FALSE);
 #endif
 
 	/* Setup the outside spacing. */
-	vbox = gtk_dialog_get_content_area(GTK_DIALOG(warn_close_dialog));
+	vbox = GTK_DIALOG(warn_close_dialog)->vbox;
 
 	gtk_box_set_spacing(GTK_BOX(vbox), 12);
 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
@@ -8633,7 +8955,7 @@ notebook_init_grab(PidginWindow *gtkwin,
 	   always be true after a button press. */
 	if (!gdk_pointer_is_grabbed())
 #endif
-		gdk_pointer_grab(gtk_widget_get_window(gtkwin->notebook), FALSE,
+		gdk_pointer_grab(gtkwin->notebook->window, FALSE,
 		                 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
 		                 NULL, cursor, GDK_CURRENT_TIME);
 }
@@ -8753,22 +9075,19 @@ infopane_press_cb(GtkWidget *widget, Gdk
 
 	if (e->button == 1) {
 		int nb_x, nb_y;
-		GtkAllocation allocation;
 
-		gtk_widget_get_allocation(gtkconv->infopane_hbox, &allocation);
-
 		if (gtkconv->win->in_drag)
 			return TRUE;
 
 		gtkconv->win->in_predrag = TRUE;
 		gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont);
 
-		gdk_window_get_origin(gtk_widget_get_window(gtkconv->infopane_hbox), &nb_x, &nb_y);
+		gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y);
 
-		gtkconv->win->drag_min_x = allocation.x + nb_x;
-		gtkconv->win->drag_min_y = allocation.y + nb_y;
-		gtkconv->win->drag_max_x = allocation.width + gtkconv->win->drag_min_x;
-		gtkconv->win->drag_max_y = allocation.height + gtkconv->win->drag_min_y;
+		gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x;
+		gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y;
+		gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x;
+		gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y;
 
 		gtkconv->win->drag_motion_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event",
 								    G_CALLBACK(notebook_motion_cb), gtkconv->win);
@@ -8781,10 +9100,9 @@ infopane_press_cb(GtkWidget *widget, Gdk
 		/* Right click was pressed. Popup the context menu. */
 		GtkWidget *menu = gtk_menu_new(), *sub;
 		gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE);
-#if 0 /* TODO */
+
 		sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to));
-
-		if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) {
+		if (sub && gtk_widget_is_sensitive(gtkconv->win->menu.send_to)) {
 			GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To"));
 			if (populated)
 				pidgin_separator(menu);
@@ -8796,7 +9114,7 @@ infopane_press_cb(GtkWidget *widget, Gdk
 			gtk_widget_destroy(menu);
 			return FALSE;
 		}
-#endif
+
 		gtk_widget_show_all(menu);
 		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time);
 		return TRUE;
@@ -8811,7 +9129,6 @@ notebook_press_cb(GtkWidget *widget, Gdk
 	int tab_clicked;
 	GtkWidget *page;
 	GtkWidget *tab;
-	GtkAllocation allocation;
 
 	if (e->button == 2 && e->type == GDK_BUTTON_PRESS) {
 		PidginConversation *gtkconv;
@@ -8849,7 +9166,7 @@ notebook_press_cb(GtkWidget *widget, Gdk
 	* Get the relative position of the press event, with regards to
 	* the position of the notebook.
 	*/
-	gdk_window_get_origin(gtk_widget_get_window(win->notebook), &nb_x, &nb_y);
+	gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y);
 
 	/* Reset the min/max x/y */
 	win->drag_min_x = 0;
@@ -8861,21 +9178,19 @@ notebook_press_cb(GtkWidget *widget, Gdk
 	page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), tab_clicked);
 	tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(win->notebook), page);
 
-	gtk_widget_get_allocation(tab, &allocation);
+	win->drag_min_x = tab->allocation.x      + nb_x;
+	win->drag_min_y = tab->allocation.y      + nb_y;
+	win->drag_max_x = tab->allocation.width  + win->drag_min_x;
+	win->drag_max_y = tab->allocation.height + win->drag_min_y;
 
-	win->drag_min_x = allocation.x      + nb_x;
-	win->drag_min_y = allocation.y      + nb_y;
-	win->drag_max_x = allocation.width  + win->drag_min_x;
-	win->drag_max_y = allocation.height + win->drag_min_y;
-
 	/* Make sure the click occurred in the tab. */
 	if (e->x_root <  win->drag_min_x ||
 	    e->x_root >= win->drag_max_x ||
 	    e->y_root <  win->drag_min_y ||
 	    e->y_root >= win->drag_max_y) {
 
-		return FALSE;
-	}
+		    return FALSE;
+	    }
 
 	win->in_predrag = TRUE;
 	win->drag_tab = tab_clicked;
@@ -9103,14 +9418,11 @@ static void close_tab_cb(GtkWidget *w, G
 		close_conv_cb(NULL, gtkconv);
 }
 
-/* TODO: I don't know if this doable in GTK+ 3.0 */
-#if 0
 static gboolean
 right_click_menu_cb(GtkNotebook *notebook, GdkEventButton *event, PidginWindow *win)
 {
-	GtkWidget *item;
+	GtkWidget *item, *menu;
 	PidginConversation *gtkconv;
-	GtkWidget *menu = gtk_notebook_get_menu
 
 	if (event->type != GDK_BUTTON_PRESS || event->button != 3)
 		return FALSE;
@@ -9157,7 +9469,6 @@ right_click_menu_cb(GtkNotebook *noteboo
 
 	return FALSE;
 }
-#endif
 
 static void
 remove_edit_entry(PidginConversation *gtkconv, GtkWidget *entry)
@@ -9179,7 +9490,7 @@ alias_key_press_cb(GtkWidget *widget, Gd
 static gboolean
 alias_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 {
-	if (event->keyval == GDK_KEY_Escape) {
+	if (event->keyval == GDK_Escape) {
 		remove_edit_entry(user_data, widget);
 		return TRUE;
 	}
@@ -9206,7 +9517,8 @@ alias_cb(GtkEntry *entry, gpointer user_
 		PurpleBuddy *buddy;
 		buddy = purple_find_buddy(account, name);
 		if (buddy != NULL) {
-			purple_blist_alias_buddy(buddy, gtk_entry_get_text(entry));
+			purple_blist_alias_buddy(buddy,
+                                                 gtk_entry_get_text(entry));
 		}
 		serv_alias_buddy(buddy);
 	} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
@@ -9228,13 +9540,13 @@ infopane_entry_activate(PidginConversati
 		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;
@@ -9244,9 +9556,9 @@ infopane_entry_activate(PidginConversati
 		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;
@@ -9352,18 +9664,14 @@ make_status_icon_list(const char *stock,
 make_status_icon_list(const char *stock, GtkWidget *w)
 {
 	GList *l = NULL;
-	l = g_list_append(l,
-		gtk_widget_render_icon(w, stock,
-			gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), "GtkWindow"));
-	l = g_list_append(l,
-		gtk_widget_render_icon(w, stock,
-			gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow"));
-	l = g_list_append(l,
-		gtk_widget_render_icon(w, stock,
-			gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM), "GtkWindow"));
-	l = g_list_append(l,
-		gtk_widget_render_icon(w, stock,
-			gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), "GtkWindow"));
+	l = g_list_append(l, gtk_widget_render_icon (w, stock,
+                                       gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), "GtkWindow"));
+	l = g_list_append(l, gtk_widget_render_icon (w, stock,
+                                       gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow"));
+	l = g_list_append(l, gtk_widget_render_icon (w, stock,
+                                       gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM), "GtkWindow"));
+	l = g_list_append(l, gtk_widget_render_icon (w, stock,
+                                       gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), "GtkWindow"));
 	return l;
 }
 
@@ -9394,7 +9702,7 @@ static gboolean gtk_conv_configure_cb(Gt
 
 	/* Workaround for GTK+ bug # 169811 - "configure_event" is fired
 	* when the window is being maximized */
-	if (gdk_window_get_state(gtk_widget_get_window(w)) & GDK_WINDOW_STATE_MAXIMIZED)
+	if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED)
 		return FALSE;
 
 	/* don't save off-screen positioning */
@@ -9419,8 +9727,8 @@ pidgin_conv_set_position_size(PidginWind
 pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y,
 		int conv_width, int conv_height)
 {
-	/* if the window exists, is hidden, we're saving positions, and the
-	 * position is sane... */
+	 /* if the window exists, is hidden, we're saving positions, and the
+          * position is sane... */
 	if (win && win->window &&
 			!gtk_widget_get_visible(win->window) && conv_width != 0) {
 
@@ -9507,12 +9815,8 @@ pidgin_conv_window_new()
 	gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE);
 	gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), TRUE);
 
-	/* TODO: figure out how to add custom stuff to the right-click menu in
-	   GtkNotebook in GTK+ 3.0 */
-#if 0
 	g_signal_connect(G_OBJECT(win->notebook), "button-press-event",
 					G_CALLBACK(right_click_menu_cb), win);
-#endif
 
 	gtk_widget_show(win->notebook);
 
@@ -9604,7 +9908,7 @@ pidgin_conv_window_raise(PidginWindow *w
 void
 pidgin_conv_window_raise(PidginWindow *win)
 {
-	gdk_window_raise(GDK_WINDOW(gtk_widget_get_window(win->window)));
+	gdk_window_raise(GDK_WINDOW(win->window->window));
 }
 
 void
@@ -9779,7 +10083,7 @@ pidgin_conv_tab_pack(PidginWindow *win, 
 	g_signal_connect(G_OBJECT(ebox), "enter-notify-event",
 			G_CALLBACK(gtkconv_tab_set_tip), gtkconv);
 
-	if (gtk_widget_get_parent(gtkconv->tab_label) == NULL) {
+	if (gtkconv->tab_label->parent == NULL) {
 		/* Pack if it's a new widget */
 		gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first,              FALSE, FALSE, 0);
 		gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE,  TRUE,  0);
@@ -9800,7 +10104,9 @@ pidgin_conv_tab_pack(PidginWindow *win, 
 		gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox);
 	}
 
-	g_object_set(G_OBJECT(win->notebook), "expand", !tabs_side && !angle, NULL);
+	gtk_container_child_set(GTK_CONTAINER(win->notebook), gtkconv->tab_cont,
+	                        "tab-expand", !tabs_side && !angle,
+	                        "tab-fill", TRUE, NULL);
 
 	if (pidgin_conv_window_get_gtkconv_count(win) == 1)
 		gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
@@ -9824,12 +10130,7 @@ pidgin_conv_window_remove_gtkconv(Pidgin
 
 	index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont);
 
-#if GTK_CHECK_VERSION(2,10,0)
 	g_object_ref_sink(G_OBJECT(gtkconv->tab_cont));
-#else
-	g_object_ref(gtkconv->tab_cont);
-	gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont));
-#endif
 
 	gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index);
 
@@ -9912,7 +10213,7 @@ pidgin_conv_window_get_at_xy(int x, int 
 	for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) {
 		win = l->data;
 
-		if (gdkwin == gtk_widget_get_window(win->window))
+		if (gdkwin == win->window->window)
 			return win;
 	}
 
@@ -10041,7 +10342,7 @@ conv_placement_last_created_win_type_con
 
 	/* Workaround for GTK+ bug # 169811 - "configure_event" is fired
 	* when the window is being maximized */
-	if (gdk_window_get_state(gtk_widget_get_window(w)) & GDK_WINDOW_STATE_MAXIMIZED)
+	if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED)
 		return FALSE;
 
 	/* don't save off-screen positioning */
============================================================
--- pidgin/gtkconv.h	55f7d100ce6b3a5c7e94a02db2f5bb236dcfd52a
+++ pidgin/gtkconv.h	9f0bce49eedc37b8cf07de7c861e124d386d90c6
@@ -51,12 +51,12 @@ enum {
 	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 @@ enum {
 #include "pidgin.h"
 #include "conversation.h"
 #include "gtkconvwin.h"
+#include "gtkconv-theme.h"
 
 /**************************************************************************
  * @name Structures
@@ -77,39 +78,6 @@ enum {
  */
 
 /**
- * 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
@@ -132,7 +100,9 @@ struct _PidginConversation
 	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
@@ -178,8 +148,6 @@ struct _PidginConversation
 
 	/**
 	 * Quick Find.
-	 *
-	 * @since 2.7.0
 	 */
 	struct {
 		GtkWidget *entry;
@@ -267,8 +235,6 @@ void pidgin_conv_present_conversation(Pu
  * @param conv  The conversation.
  *
  * @return  Wheter Pidgin UI was successfully attached.
- *
- * @since 2.2.0
  */
 gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv);
 
============================================================
--- pidgin/gtkutils.c	ab7749a39ce68e43b9ec76d914eae9f73cf31761
+++ pidgin/gtkutils.c	86ee83df8349c84bd0b8819e37375deff98e801a
@@ -67,8 +67,14 @@
 #include "pidginstock.h"
 #include "gtkthemes.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 #include "pidgin/minidialog.h"
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
+#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x)
+#endif
+
 typedef struct {
 	GtkTreeModel *model;
 	gint default_item;
@@ -180,6 +186,7 @@ pidgin_create_dialog(const char *title, 
 
 	wnd = GTK_WINDOW(gtk_dialog_new());
 	pidgin_window_init(wnd, title, border_width, role, resizable);
+	g_object_set(G_OBJECT(wnd), "has-separator", FALSE, NULL);
 
 	return GTK_WIDGET(wnd);
 }
@@ -187,7 +194,7 @@ pidgin_dialog_get_vbox_with_properties(G
 GtkWidget *
 pidgin_dialog_get_vbox_with_properties(GtkDialog *dialog, gboolean homogeneous, gint spacing)
 {
-	GtkBox *vbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
+	GtkBox *vbox = GTK_BOX(GTK_DIALOG(dialog)->vbox);
 	gtk_box_set_homogeneous(vbox, homogeneous);
 	gtk_box_set_spacing(vbox, spacing);
 	return GTK_WIDGET(vbox);
@@ -195,12 +202,12 @@ GtkWidget *pidgin_dialog_get_vbox(GtkDia
 
 GtkWidget *pidgin_dialog_get_vbox(GtkDialog *dialog)
 {
-	return gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+	return GTK_DIALOG(dialog)->vbox;
 }
 
 GtkWidget *pidgin_dialog_get_action_area(GtkDialog *dialog)
 {
-	return gtk_dialog_get_action_area(GTK_DIALOG(dialog));
+	return GTK_DIALOG(dialog)->action_area;
 }
 
 GtkWidget *pidgin_dialog_add_button(GtkDialog *dialog, const char *label,
@@ -275,6 +282,69 @@ pidgin_create_imhtml(gboolean editable, 
 	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)
 {
@@ -291,7 +361,7 @@ pidgin_toggle_sensitive(GtkWidget *widge
 	if (to_toggle == NULL)
 		return;
 
-	sensitivity = gtk_widget_get_sensitive(to_toggle);
+	sensitivity = gtk_widget_is_sensitive(to_toggle);
 
 	gtk_widget_set_sensitive(to_toggle, !sensitivity);
 }
@@ -308,7 +378,7 @@ pidgin_toggle_sensitive_array(GtkWidget 
 		if (element == NULL)
 			continue;
 
-		sensitivity = gtk_widget_get_sensitive(element);
+		sensitivity = gtk_widget_is_sensitive(element);
 
 		gtk_widget_set_sensitive(element, !sensitivity);
 	}
@@ -676,6 +746,7 @@ create_protocols_menu(const char *defaul
 		if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) {
 			char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
 			                                  "16", "facebook.png", NULL);
+
 			pixbuf = pidgin_pixbuf_new_from_file(filename);
 			g_free(filename);
 
@@ -952,7 +1023,7 @@ void pidgin_retrieve_user_info_in_chat(P
 		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) {
@@ -1078,7 +1149,7 @@ pidgin_parse_x_im_contact(const char *ms
 					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);
@@ -1120,7 +1191,7 @@ pidgin_parse_x_im_contact(const char *ms
 						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);
@@ -1223,8 +1294,8 @@ pidgin_menu_position_func_helper(GtkMenu
 
 	widget     = GTK_WIDGET(menu);
 	screen     = gtk_widget_get_screen(widget);
-	xthickness = gtk_widget_get_style(widget)->xthickness;
-	ythickness = gtk_widget_get_style(widget)->ythickness;
+	xthickness = widget->style->xthickness;
+	ythickness = widget->style->ythickness;
 	rtl        = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL);
 
 	/*
@@ -1362,9 +1433,9 @@ pidgin_treeview_popup_menu_position_func
 	GtkTreePath *path;
 	GtkTreeViewColumn *col;
 	GdkRectangle rect;
-	gint ythickness = gtk_widget_get_style(GTK_WIDGET(menu))->ythickness;
+	gint ythickness = GTK_WIDGET(menu)->style->ythickness;
 
-	gdk_window_get_origin (gtk_widget_get_window(widget), x, y);
+	gdk_window_get_origin (widget->window, x, y);
 	gtk_tree_view_get_cursor (tv, &path, &col);
 	gtk_tree_view_get_cell_area (tv, path, col, &rect);
 
@@ -1481,7 +1552,7 @@ pidgin_dnd_file_manage(GtkSelectionData 
 pidgin_dnd_file_manage(GtkSelectionData *sd, PurpleAccount *account, const char *who)
 {
 	GdkPixbuf *pb;
-	GList *files = purple_uri_list_extract_filenames((const gchar *) gtk_selection_data_get_data(sd));
+	GList *files = purple_uri_list_extract_filenames((const gchar *)sd->data);
 	PurpleConnection *gc = purple_account_get_connection(account);
 	PurplePluginProtocolInfo *prpl_info = NULL;
 #ifndef _WIN32
@@ -1532,7 +1603,7 @@ pidgin_dnd_file_manage(GtkSelectionData 
 			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;
@@ -1763,21 +1834,27 @@ pidgin_append_menu_action(GtkWidget *men
                             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);
+	list = purple_menu_action_get_children(act);
+	menuitem = gtk_menu_item_new_with_mnemonic(purple_menu_action_get_label(act));
 
-		if (act->callback != NULL) {
+	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);
@@ -1791,7 +1868,6 @@ pidgin_append_menu_action(GtkWidget *men
 		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();
@@ -1799,21 +1875,20 @@ pidgin_append_menu_action(GtkWidget *men
 
 		group = gtk_menu_get_accel_group(GTK_MENU(menu));
 		if (group) {
-			char *path = g_strdup_printf("%s/%s",
-				gtk_menu_item_get_accel_path(GTK_MENU_ITEM(menuitem)),
-				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;
@@ -2013,8 +2088,8 @@ add_completion_list(PidginCompletionData
 					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)
 													 );
 				}
 			}
@@ -2106,7 +2181,7 @@ pidgin_screenname_autocomplete_default_f
 	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));
 	}
@@ -2117,23 +2192,23 @@ void pidgin_set_cursor(GtkWidget *widget
 	GdkCursor *cursor;
 
 	g_return_if_fail(widget != NULL);
-	if (gtk_widget_get_window(widget) == NULL)
+	if (widget->window == NULL)
 		return;
 
 	cursor = gdk_cursor_new(cursor_type);
-	gdk_window_set_cursor(gtk_widget_get_window(widget), cursor);
+	gdk_window_set_cursor(widget->window, cursor);
 	gdk_cursor_unref(cursor);
 
-	gdk_display_flush(gdk_window_get_display(gtk_widget_get_window(widget)));
+	gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
 }
 
 void pidgin_clear_cursor(GtkWidget *widget)
 {
 	g_return_if_fail(widget != NULL);
-	if (gtk_widget_get_window(widget) == NULL)
+	if (widget->window == NULL)
 		return;
 
-	gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
+	gdk_window_set_cursor(widget->window, NULL);
 }
 
 struct _icon_chooser {
@@ -2174,7 +2249,7 @@ icon_filesel_choose_cb(GtkWidget *widget
 	gtk_widget_destroy(dialog->icon_filesel);
 	g_free(filename);
 	g_free(dialog);
-}
+ }
 
 
 static void
@@ -2412,9 +2487,9 @@ pidgin_convert_buddy_icon(PurplePlugin *
 					   the image. */
 					purple_debug_info("buddyicon", "Converted image from "
 							"%dx%d to %dx%d, format=%s, quality=%u, "
-							"filesize=%zu\n", orig_width, orig_height,
-							new_width, new_height, prpl_formats[i], quality,
-							length);
+							"filesize=%" G_GSIZE_FORMAT "\n",
+							orig_width, orig_height, new_width, new_height,
+							prpl_formats[i], quality, length);
 					if (len)
 						*len = length;
 					g_strfreev(prpl_formats);
@@ -2793,7 +2868,7 @@ const char *pidgin_get_dim_grey_string(G
 	if (!widget)
 		return "dim grey";
 
-	style = gtk_widget_get_style(widget);
+ 	style = gtk_widget_get_style(widget);
 	if (!style)
 		return "dim grey";
 
@@ -2805,18 +2880,18 @@ static void
 }
 
 static void
-combo_box_changed_cb(GtkComboBoxText *combo_box, GtkEntry *entry)
+combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry)
 {
-	char *text = gtk_combo_box_text_get_active_text(combo_box);
+	char *text = gtk_combo_box_get_active_text(combo_box);
 	gtk_entry_set_text(entry, text ? text : "");
 	g_free(text);
 }
 
 static gboolean
-entry_key_pressed_cb(GtkWidget *entry, GdkEventKey *key, GtkComboBoxText *combo)
+entry_key_pressed_cb(GtkWidget *entry, GdkEventKey *key, GtkComboBox *combo)
 {
-	if (key->keyval == GDK_KEY_Down || key->keyval == GDK_KEY_Up) {
-		gtk_combo_box_popup(GTK_COMBO_BOX(combo));
+	if (key->keyval == GDK_Down || key->keyval == GDK_Up) {
+		gtk_combo_box_popup(combo);
 		return TRUE;
 	}
 	return FALSE;
@@ -2825,10 +2900,10 @@ pidgin_text_combo_box_entry_new(const ch
 GtkWidget *
 pidgin_text_combo_box_entry_new(const char *default_item, GList *items)
 {
-	GtkComboBoxText *ret = NULL;
+	GtkComboBox *ret = NULL;
 	GtkWidget *the_entry = NULL;
 
-	ret = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new_with_entry());
+	ret = GTK_COMBO_BOX(gtk_combo_box_entry_new_text());
 	the_entry = gtk_entry_new();
 	gtk_container_add(GTK_CONTAINER(ret), the_entry);
 
@@ -2838,7 +2913,7 @@ pidgin_text_combo_box_entry_new(const ch
 	for (; items != NULL ; items = items->next) {
 		char *text = items->data;
 		if (text && *text)
-			gtk_combo_box_text_append_text(ret, text);
+			gtk_combo_box_append_text(ret, text);
 	}
 
 	g_signal_connect(G_OBJECT(ret), "changed", (GCallback)combo_box_changed_cb, the_entry);
@@ -2849,12 +2924,12 @@ const char *pidgin_text_combo_box_entry_
 
 const char *pidgin_text_combo_box_entry_get_text(GtkWidget *widget)
 {
-	return gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN((widget)))));
+	return gtk_entry_get_text(GTK_ENTRY(GTK_BIN((widget))->child));
 }
 
 void pidgin_text_combo_box_entry_set_text(GtkWidget *widget, const char *text)
 {
-	gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN((widget)))), (text));
+	gtk_entry_set_text(GTK_ENTRY(GTK_BIN((widget))->child), (text));
 }
 
 GtkWidget *
@@ -2921,7 +2996,7 @@ gboolean pidgin_auto_parent_window(GtkWi
 		windows = g_list_delete_link(windows, windows);
 
 		if (window == widget ||
-				!GTK_WIDGET_VISIBLE(window))
+				!gtk_widget_get_visible(window))
 			continue;
 
 		if (!gdk_property_get(window->window, _WindowTime, _Cardinal, 0, sizeof(time_t), FALSE,
@@ -2980,7 +3055,7 @@ gboolean pidgin_auto_parent_window(GtkWi
 		}
 
 		if (gtk_window_has_toplevel_focus(GTK_WINDOW(window)) ||
-				(menu && menu == gtk_widget_get_window(window))) {
+				(menu && menu == window->window)) {
 			parent = window;
 			break;
 		}
@@ -3005,7 +3080,7 @@ static GObject *pidgin_pixbuf_from_data_
 
 	if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) {
 		purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() "
-				"failed with size=%zu: %s\n", count,
+				"failed with size=%" G_GSIZE_FORMAT ": %s\n", count,
 				error ? error->message : "(no error message)");
 		if (error)
 			g_error_free(error);
@@ -3015,7 +3090,7 @@ static GObject *pidgin_pixbuf_from_data_
 
 	if (!gdk_pixbuf_loader_close(loader, &error) || error) {
 		purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() "
-				"failed for image of size %zu: %s\n", count,
+				"failed for image of size %" G_GSIZE_FORMAT ": %s\n", count,
 				error ? error->message : "(no error message)");
 		if (error)
 			g_error_free(error);
@@ -3029,7 +3104,7 @@ static GObject *pidgin_pixbuf_from_data_
 		pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader));
 	if (!pixbuf) {
 		purple_debug_warning("gtkutils", "%s() returned NULL for image "
-				"of size %zu\n",
+				"of size %" G_GSIZE_FORMAT "\n",
 				animated ? "gdk_pixbuf_loader_get_animation"
 					: "gdk_pixbuf_loader_get_pixbuf", count);
 		g_object_unref(G_OBJECT(loader));
@@ -3195,9 +3270,9 @@ file_open_uri(GtkIMHtml *imhtml, const c
 	{
 		gchar *escaped = g_shell_quote(uri);
 		gchar *param = g_strconcat("/select,\"", uri, "\"", NULL);
-		gchar *wc_param = g_utf8_to_utf16(param, -1, NULL, NULL, NULL);
+		wchar_t *wc_param = g_utf8_to_utf16(param, -1, NULL, NULL, NULL);
 
-		code = (int)ShellExecuteW(NULL, "OPEN", L"explorer.exe", wc_param, NULL, SW_NORMAL);
+		code = (int)ShellExecuteW(NULL, L"OPEN", L"explorer.exe", wc_param, NULL, SW_NORMAL);
 
 		g_free(wc_param);
 		g_free(param);
@@ -3359,7 +3434,7 @@ save_file_cb(GtkWidget *item, const char
 		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;
 }
@@ -3541,7 +3616,7 @@ pidgin_make_scrollable(GtkWidget *child,
 		if (width != -1 || height != -1)
 			gtk_widget_set_size_request(sw, width, height);
 		if (child) {
-			if (GTK_IS_SCROLLABLE(child))
+			if (GTK_WIDGET_GET_CLASS(child)->set_scroll_adjustments_signal)
 				gtk_container_add(GTK_CONTAINER(sw), child);
 			else
 				gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), child);
@@ -3616,4 +3691,3 @@ void pidgin_utils_uninit(void)
 	gtk_imhtml_class_register_protocol("mailto:", NULL, NULL);
 	gtk_imhtml_class_register_protocol("gopher://", NULL, NULL);
 }
-
============================================================
--- pidgin/gtkutils.h	87131c0d472b78b884749e0e14b804cd446ae32d
+++ pidgin/gtkutils.h	619e6cf7ebfe6cf43fdd22ce4421c5fa7b5c49a5
@@ -109,12 +109,34 @@ GtkWidget *pidgin_create_imhtml(gboolean
 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 @@ GtkWidget *pidgin_create_small_button(Gt
  * @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 @@ GtkWidget *pidgin_create_window(const ch
  * @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 @@ GtkWidget *pidgin_create_dialog(const ch
  * @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 @@ GtkWidget *pidgin_dialog_get_vbox_with_p
  * 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 @@ GtkWidget *pidgin_dialog_get_vbox(GtkDia
  * @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 @@ GtkWidget *pidgin_dialog_add_button(GtkD
  * 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);
 
@@ -415,8 +426,6 @@ void pidgin_load_accels(void);
  *
  * @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);
 
@@ -426,8 +435,6 @@ void pidgin_retrieve_user_info(PurpleCon
  * @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);
 
@@ -466,8 +473,6 @@ void pidgin_set_accessible_label(GtkWidg
  *
  * @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);
 
@@ -482,8 +487,6 @@ void pidgin_set_accessible_relations(Gtk
  *        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);
@@ -555,8 +558,6 @@ GdkPixbuf * pidgin_create_status_icon(Pu
  * @param prim   The status primitive
  *
  * @return The stock-id
- *
- * @since 2.6.0
  */
 const char *pidgin_stock_id_from_status_primitive(PurpleStatusPrimitive prim);
 
@@ -566,8 +567,6 @@ const char *pidgin_stock_id_from_status_
  * @param presence   The presence.
  *
  * @return The stock-id
- *
- * @since 2.6.0
  */
 const char *pidgin_stock_id_from_presence(PurplePresence *presence);
 
@@ -735,8 +734,6 @@ const char *pidgin_get_dim_grey_string(G
  *
  * @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);
 
@@ -746,8 +743,6 @@ GtkWidget *pidgin_text_combo_box_entry_n
  * @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);
 
@@ -756,8 +751,6 @@ const char *pidgin_text_combo_box_entry_
  *
  * @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);
 
@@ -767,8 +760,6 @@ void pidgin_text_combo_box_entry_set_tex
  * @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);
 
@@ -783,7 +774,6 @@ gboolean pidgin_auto_parent_window(GtkWi
  * @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);
 
@@ -795,8 +785,6 @@ GtkWidget *pidgin_add_widget_to_vbox(Gtk
  *
  * @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);
 
@@ -808,8 +796,6 @@ GdkPixbuf *pidgin_pixbuf_from_data(const
  *
  * @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);
 
@@ -819,8 +805,6 @@ GdkPixbufAnimation *pidgin_pixbuf_anim_f
  * @param  image   A PurpleStoredImage.
  *
  * @return   A GdkPixbuf created from the stored image.
- *
- * @since 2.5.0
  */
 GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image);
 
@@ -844,8 +828,6 @@ GdkPixbuf *pidgin_pixbuf_from_imgstore(P
  *
  * @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);
 
@@ -871,8 +853,6 @@ GdkPixbuf *pidgin_pixbuf_new_from_file(c
  *
  * @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);
 
@@ -899,35 +879,27 @@ GdkPixbuf *pidgin_pixbuf_new_from_file_a
  *
  * @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);
 
============================================================
--- pidgin/plugins/gestures/gestures.c	c16ac78591c42117a071097e73e63e7d9e65506b
+++ pidgin/plugins/gestures/gestures.c	cae48552aef2dc49d4a35fcf7cbdfa45f27d26bb
@@ -48,7 +48,7 @@ stroke_close(GtkWidget *widget, void *da
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
-	gstroke_cleanup(gtkconv->imhtml);
+	gstroke_cleanup(gtkconv->webview);
 	purple_conversation_destroy(conv);
 }
 
@@ -126,15 +126,15 @@ attach_signals(PurpleConversation *conv)
 
 	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
@@ -145,7 +145,6 @@ new_conv_cb(PurpleConversation *conv)
 }
 
 #if 0
-#if GTK_CHECK_VERSION(2,4,0)
 static void
 mouse_button_menu_cb(GtkComboBox *opt, gpointer data)
 {
@@ -153,16 +152,7 @@ mouse_button_menu_cb(GtkComboBox *opt, g
 
 	gstroke_set_mouse_button(button + 2);
 }
-#else
-static void
-mouse_button_menu_cb(GtkMenuItem *item, gpointer data)
-{
-	int button = (int)data;
-
-	gstroke_set_mouse_button(button + 2);
-}
 #endif
-#endif
 
 static void
 toggle_draw_cb(GtkToggleButton *toggle, gpointer data)
@@ -215,8 +205,8 @@ plugin_unload(PurplePlugin *plugin)
 
 		gtkconv = PIDGIN_CONVERSATION(conv);
 
-		gstroke_cleanup(gtkconv->imhtml);
-		gstroke_disable(gtkconv->imhtml);
+		gstroke_cleanup(gtkconv->webview);
+		gstroke_disable(gtkconv->webview);
 	}
 
 	return TRUE;
@@ -230,10 +220,7 @@ get_config_frame(PurplePlugin *plugin)
 	GtkWidget *toggle;
 #if 0
 	GtkWidget *opt;
-#if GTK_CHECK_VERSION(2,4,0)
-	GtkWidget *menu, *item;
 #endif
-#endif
 
 	/* Outside container */
 	ret = gtk_vbox_new(FALSE, 18);
@@ -243,7 +230,6 @@ get_config_frame(PurplePlugin *plugin)
 	vbox = pidgin_make_frame(ret, _("Mouse Gestures Configuration"));
 
 #if 0
-#if GTK_CHECK_VERSION(2,4,0)
 	/* Mouse button drop-down menu */
 	opt = gtk_combo_box_new_text();
 
@@ -255,27 +241,7 @@ get_config_frame(PurplePlugin *plugin)
 	gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0);
 	gtk_combo_box_set_active(GTK_COMBO_BOX(opt),
 							gstroke_get_mouse_button() - 2);
-#else
-	/* Mouse button drop-down menu */
-	menu = gtk_menu_new();
-	opt = gtk_option_menu_new();
-
-	item = gtk_menu_item_new_with_label(_("Middle mouse button"));
-	g_signal_connect(G_OBJECT(item), "activate",
-					 G_CALLBACK(mouse_button_menu_cb), opt);
-	gtk_menu_append(menu, item);
-
-	item = gtk_menu_item_new_with_label(_("Right mouse button"));
-	g_signal_connect(G_OBJECT(item), "activate",
-					 G_CALLBACK(mouse_button_menu_cb), opt);
-	gtk_menu_append(menu, item);
-
-	gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0);
-	gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
-	gtk_option_menu_set_history(GTK_OPTION_MENU(opt),
-								gstroke_get_mouse_button() - 2);
 #endif
-#endif
 
 	/* "Visual gesture display" checkbox */
 	toggle = gtk_check_button_new_with_mnemonic(_("_Visual gesture display"));
============================================================
--- pidgin/plugins/gestures/stroke-draw.c	1d0c503d41235dc7cefee5ddbc3b526727e9d31d
+++ pidgin/plugins/gestures/stroke-draw.c	de1f7eaeb012577c84e6ec8fa5b37a64b65489ae
@@ -339,7 +339,7 @@ gstroke_invisible_window_init (GtkWidget
   unsigned int border_width;
   XSizeHints hints;
   Display *disp = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(widget));
-  Window wind = gdk_x11_window_get_xid(gtk_widget_get_window(widget));
+  Window wind = GDK_WINDOW_XWINDOW (gtk_widget_get_window(widget));
   int screen = DefaultScreen (disp);
 
 	if (!gstroke_draw_strokes())
============================================================
--- libpurple/ft.h	68c7c633daced2fb3d1981dc4ba98de2a063c4f1
+++ libpurple/ft.h	dd906b053187da009f745186df5b8c5671198056
@@ -87,7 +87,6 @@ typedef struct
 	 *
 	 * @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 @@ typedef struct
 	 * @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 @@ typedef struct
 	 * @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 @@ struct _PurpleXfer
 	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 @@ struct _PurpleXfer
 	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 @@ struct _PurpleXfer
 	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(PurpleXf
 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 @@ PurpleAccount *purple_xfer_get_account(c
  * @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 @@ PurpleXferStatusType purple_xfer_get_sta
  * @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 @@ const char *purple_xfer_get_local_filena
  *
  * @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 @@ size_t purple_xfer_get_bytes_sent(const 
  *
  * @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 @@ size_t purple_xfer_get_bytes_remaining(c
  *
  * @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 @@ unsigned int purple_xfer_get_remote_port
  * @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 @@ time_t purple_xfer_get_start_time(const 
  * @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(PurpleXfe
 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,9 +496,17 @@ void purple_xfer_set_local_filename(Purp
  * @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
  * can be used to jump backward in the file if the protocol detects
  * that some bit of data needs to be resent or has been sent twice.
@@ -478,7 +519,7 @@ void purple_xfer_set_size(PurpleXfer *xf
  *                   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 @@ gssize purple_xfer_write(PurpleXfer *xfe
  * 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 @@ void purple_xfer_conversation_write(Purp
  * 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 @@ void purple_xfer_ui_ready(PurpleXfer *xf
  * 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 @@ void purple_xfer_prpl_ready(PurpleXfer *
  * @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 @@ gconstpointer purple_xfer_get_thumbnail(
  *
  * @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 @@ const gchar *purple_xfer_get_thumbnail_m
  * @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,11 +764,45 @@ void purple_xfer_set_thumbnail(PurpleXfe
  * @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 @@ PurpleXferUiOps *purple_xfers_get_ui_ops
 #endif
 
 #endif /* _PURPLE_FT_H_ */
+
============================================================
--- pidgin/gtkft.c	61e433c5220b64ab25711815465a05575338bb8d
+++ pidgin/gtkft.c	c1adf6b48eb30131fe65b2c378f26248aba5a727
@@ -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 @@ get_xfer_info_strings(PurpleXfer *xfer, 
 	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 @@ get_xfer_info_strings(PurpleXfer *xfer, 
 		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 @@ get_xfer_info_strings(PurpleXfer *xfer, 
 		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 @@ update_detailed_info(PidginXferDialog *d
 	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 @@ update_detailed_info(PidginXferDialog *d
 	}
 
 	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 @@ update_buttons(PidginXferDialog *dialog,
 #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 @@ pidgin_xfer_dialog_new(void)
 	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 @@ pidgin_xfer_dialog_add_xfer(PidginXferDi
 
 	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 @@ pidgin_xfer_dialog_remove_xfer(PidginXfe
 	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 @@ pidgin_xfer_dialog_cancel_xfer(PidginXfe
 	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 @@ pidgin_xfer_dialog_cancel_xfer(PidginXfe
 		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_xfer_dialog_cancel_xfer(PidginXfe
 									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 @@ pidgin_xfer_dialog_update_xfer(PidginXfe
 	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 @@ pidgin_xfer_new_xfer(PurpleXfer *xfer)
 {
 	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 @@ pidgin_xfer_destroy(PurpleXfer *xfer)
 {
 	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);
 	}
 }
 
============================================================
--- libpurple/protocols/msn/msg.c	94fe3963ccab9a56f0311277c241efbc0242a4d6
+++ libpurple/protocols/msn/msg.c	f3c82185167ec7756f43622f6211604ae426ea9a
@@ -627,7 +627,7 @@ msn_plain_msg(MsnCmdProc *cmdproc, MsnMe
 	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 @@ msn_plain_msg(MsnCmdProc *cmdproc, MsnMe
 				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 @@ msn_control_msg(MsnCmdProc *cmdproc, Msn
 	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 @@ datacast_inform_user(MsnSwitchBoard *swb
 
 	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 @@ void msn_emoticon_msg(MsnCmdProc *cmdpro
 			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 @@ msn_datacast_msg(MsnCmdProc *cmdproc, Ms
 		/* 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 @@ msn_datacast_msg(MsnCmdProc *cmdproc, Ms
 		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 @@ msn_datacast_msg(MsnCmdProc *cmdproc, Ms
 		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 */
============================================================
--- libpurple/protocols/msn/switchboard.c	5da66f3d15024b12f90845eb547015040c81c219
+++ libpurple/protocols/msn/switchboard.c	b9c0b6f6d4ccef969a653349eabd0dcee49ff81a
@@ -312,7 +312,7 @@ msn_switchboard_add_user(MsnSwitchBoard 
 
 			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 @@ out_cmd(MsnCmdProc *cmdproc, MsnCommand 
 	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)
============================================================
--- libpurple/pounce.c	816cf5afb8a4108355fe832b51d0995e1d4ed8b5
+++ libpurple/pounce.c	70282f327d214954bd34bdfc6203a27b51aabe2e
@@ -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 @@ pounce_to_xmlnode(PurplePounce *pounce)
 	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);
 
============================================================
--- libpurple/pounce.h	336cf169179e55c73d7eb54c44f85a18b3ad82b6
+++ libpurple/pounce.h	499a5d7ebe4a1be6ddd418e8d20368c21a347cb2
@@ -59,31 +59,6 @@ typedef void (*PurplePounceCb)(PurplePou
 /** 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 @@ void purple_pounce_destroy_all_by_accoun
  * 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 @@ GList *purple_pounces_get_all(void);
  *
  * @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);
 
============================================================
--- libpurple/util.h	bdbdbec6b6696edbb793a3ae983c9a2039ccb439
+++ libpurple/util.h	44d8b59f9e919c1bdb5be60237127d26c3642e3c
@@ -36,9 +36,20 @@ typedef struct _PurpleUtilFetchUrlData P
   * 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" {
 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(PurpleMenuA
 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 @@ void purple_util_set_current_song(const 
  * @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 @@ char * purple_util_format_song_info(cons
 
 /**
  * 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 @@ time_t purple_str_to_time(const char *ti
  * This is exactly the same as g_markup_escape_text(), except that it
  * does not change ' to ' because ' 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 @@ char *purple_markup_linkify(const char *
  *         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 @@ char * purple_markup_get_css_property(co
  * @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 @@ char *purple_fd_get_ip(int fd);
  *
  * @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 @@ int purple_socket_get_family(int fd);
  *
  * @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 @@ gboolean purple_socket_speaks_ipv4(int f
  * @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 @@ const char *purple_strcasestr(const char
  *
  * @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,53 +1167,17 @@ typedef void (*PurpleUtilFetchUrlCallbac
  *                   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(NULL, 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 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
@@ -1177,9 +1191,8 @@ PurpleUtilFetchUrlData *purple_util_fetc
  * @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(
+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,
@@ -1225,14 +1238,15 @@ gboolean purple_email_is_valid(const cha
 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);
 
@@ -1242,7 +1256,6 @@ gboolean purple_ip_address_is_valid(cons
  * @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);
 
@@ -1252,7 +1265,6 @@ gboolean purple_ipv4_address_is_valid(co
  * @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);
 
@@ -1320,7 +1332,6 @@ gchar *purple_utf8_salvage(const char *s
  * @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);
 
@@ -1332,9 +1343,8 @@ gchar *purple_utf8_strip_unprintables(co
  * @param errnum The error code.
  *
  * @return The UTF-8 error message.
- * @since 2.4.0
  */
-G_CONST_RETURN gchar *purple_gai_strerror(gint errnum);
+const gchar *purple_gai_strerror(gint errnum);
 
 /**
  * Compares two UTF-8 strings case-insensitively.  This comparison is
@@ -1446,7 +1456,6 @@ const gchar *purple_get_host_name(void);
  * Returns a type 4 (random) UUID
  *
  * @return A UUID, caller is responsible for freeing it
- * @since 2.7.0
  */
 gchar *purple_uuid_random(void);
 
============================================================
--- pidgin/gtkpounce.c	5b85b37d2dd9ed687256b715bd086ca2e3cf173a
+++ pidgin/gtkpounce.c	a828e5fbcba0aceba91cac5ade578e0515f4cb83
@@ -410,15 +410,13 @@ pounce_dnd_recv(GtkWidget *widget, GdkDr
 				GtkSelectionData *sd, guint info, guint t, gpointer data)
 {
 	PidginPounceDialog *dialog;
-	GdkAtom target = gtk_selection_data_get_target(sd);
-	const guchar *sd_data = gtk_selection_data_get_data(sd);
 
-	if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
+	if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
 	{
 		PurpleBlistNode *node = NULL;
 		PurpleBuddy *buddy;
 
-		memcpy(&node, sd_data, sizeof(node));
+		memcpy(&node, sd->data, sizeof(node));
 
 		if (PURPLE_BLIST_NODE_IS_CONTACT(node))
 			buddy = purple_contact_get_priority_buddy((PurpleContact *)node);
@@ -429,19 +427,19 @@ pounce_dnd_recv(GtkWidget *widget, GdkDr
 
 		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, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
-	else if (target == gdk_atom_intern("application/x-im-contact", FALSE))
+	else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE))
 	{
 		char *protocol = NULL;
 		char *username = NULL;
 		PurpleAccount *account;
 
-		if (pidgin_parse_x_im_contact((const char *) sd_data, FALSE, &account,
+		if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account,
 										&protocol, &username, NULL))
 		{
 			if (account == NULL)
@@ -463,7 +461,7 @@ pounce_dnd_recv(GtkWidget *widget, GdkDr
 		g_free(username);
 		g_free(protocol);
 
-		gtk_drag_finish(dc, TRUE, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
 }
 
@@ -478,7 +476,7 @@ reset_send_msg_entry(PidginPounceDialog 
 {
 	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
@@ -542,7 +540,7 @@ pidgin_pounce_editor_show(PurpleAccount 
 					 G_CALLBACK(delete_win_cb), dialog);
 
 	/* Create the parent vbox for everything. */
-	vbox1 = gtk_dialog_get_content_area(GTK_DIALOG(window));
+	vbox1 = GTK_DIALOG(window)->vbox;
 
 	/* Create the vbox that will contain all the prefs stuff. */
 	vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
@@ -1020,7 +1018,11 @@ pounces_manager_configure_cb(GtkWidget *
 static gboolean
 pounces_manager_configure_cb(GtkWidget *widget, GdkEventConfigure *event, PouncesManager *dialog)
 {
+#if GTK_CHECK_VERSION(2,18,0)
 	if (gtk_widget_get_visible(widget)) {
+#else
+	if (GTK_WIDGET_VISIBLE(widget)) {
+#endif
 		purple_prefs_set_int(PIDGIN_PREFS_ROOT "/pounces/dialog/width",  event->width);
 		purple_prefs_set_int(PIDGIN_PREFS_ROOT "/pounces/dialog/height", event->height);
 	}
@@ -1421,7 +1423,6 @@ pounce_cb(PurplePounce *pounce, PurplePo
 	if (purple_pounce_action_is_enabled(pounce, "popup-notify"))
 	{
 		char *tmp;
-		const char *name_shown;
 		const char *reason;
 		reason = purple_pounce_action_get_attribute(pounce, "popup-notify",
 														  "reason");
@@ -1454,14 +1455,6 @@ pounce_cb(PurplePounce *pounce, PurplePo
 				   _("Unknown.... Please report this!")
 				   );
 
-		/*
-		 * Ok here is where I change the second argument, title, from
-		 * NULL to the account alias if we have it or the account
-		 * name if that's all we have
-		 */
-		if ((name_shown = purple_account_get_alias(account)) == NULL)
-			name_shown = purple_account_get_username(account);
-
 		pidgin_notify_pounce_add(account, pounce, alias, tmp, reason,
 				purple_date_format_full(NULL));
 
@@ -1485,7 +1478,7 @@ pounce_cb(PurplePounce *pounce, PurplePo
 			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);
 		}
 	}
 
============================================================
--- pidgin/gtkplugin.c	3520b503220a3ba79f25fe5a52bf1ac25816d100
+++ pidgin/gtkplugin.c	7c52fc39e8673533d60094e8f1b8dafee8cf916e
@@ -518,7 +518,7 @@ static void plugin_dialog_response_cb(Gt
 			break;
 
 		dialog = gtk_dialog_new_with_buttons(PIDGIN_ALERT_TITLE, GTK_WINDOW(d),
-						     GTK_DIALOG_DESTROY_WITH_PARENT,
+						     GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
 						     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
 						     NULL);
 		if (plugin_pref_dialogs == NULL)
@@ -527,7 +527,7 @@ static void plugin_dialog_response_cb(Gt
 		g_hash_table_insert(plugin_pref_dialogs, plug, dialog);
 
 		g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(pref_dialog_response_cb), plug);
-		gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), box);
+		gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), box);
 		gtk_window_set_role(GTK_WINDOW(dialog), "plugin_config");
 		gtk_window_set_title(GTK_WINDOW(dialog), _(purple_plugin_get_name(plug)));
 		gtk_widget_show_all(dialog);
@@ -562,12 +562,9 @@ pidgin_plugins_paint_tooltip(GtkWidget *
 pidgin_plugins_paint_tooltip(GtkWidget *tipwindow, gpointer data)
 {
 	PangoLayout *layout = g_object_get_data(G_OBJECT(tipwindow), "tooltip-plugin");
-	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(tipwindow));
-	gtk_paint_layout(gtk_widget_get_style(tipwindow), cr, GTK_STATE_NORMAL, FALSE,
-			tipwindow, "tooltip",
+	gtk_paint_layout(tipwindow->style, tipwindow->window, GTK_STATE_NORMAL, FALSE,
+			NULL, tipwindow, "tooltip",
 			6, 6, layout);
-	cairo_destroy(cr);
-
 	return TRUE;
 }
 
@@ -722,9 +719,8 @@ void pidgin_plugin_dialog_show()
 
 	plugin_dialog = gtk_dialog_new_with_buttons(_("Plugins"),
 						    NULL,
-						    0,
+						    GTK_DIALOG_NO_SEPARATOR,
 						    NULL);
-
 	pref_button = gtk_dialog_add_button(GTK_DIALOG(plugin_dialog),
 						_("Configure Pl_ugin"), PIDGIN_RESPONSE_CONFIGURE);
 	gtk_dialog_add_button(GTK_DIALOG(plugin_dialog),
@@ -776,7 +772,7 @@ void pidgin_plugin_dialog_show()
 	gtk_tree_view_append_column (GTK_TREE_VIEW(event_view), col);
 	gtk_tree_view_column_set_sort_column_id(col, 1);
 	g_object_unref(G_OBJECT(ls));
-	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(plugin_dialog))), 
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(plugin_dialog)->vbox), 
 		pidgin_make_scrollable(event_view, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), 
 		TRUE, TRUE, 0);
 	gtk_tree_view_set_search_column(GTK_TREE_VIEW(event_view), 1);
@@ -792,8 +788,8 @@ void pidgin_plugin_dialog_show()
 	gtk_expander_set_use_markup(GTK_EXPANDER(expander), TRUE);
 	gtk_widget_set_sensitive(expander, FALSE);
 	gtk_container_add(GTK_CONTAINER(expander), create_details());
-	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(plugin_dialog))),
-	                   expander, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(plugin_dialog)->vbox), expander,
+		FALSE, FALSE, 0);
 
 
 	g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (prefs_plugin_sel), NULL);
============================================================
--- libpurple/plugin.c	1dea199e1aa5529847ce92d2b4a557a5d91069f2
+++ libpurple/plugin.c	35623fc392954867721d557788b110c21048e80b
@@ -64,13 +64,6 @@ static GList *plugins_to_disable = NULL;
 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 @@ purple_plugin_load(PurplePlugin *plugin)
 
 	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 @@ purple_plugin_unload(PurplePlugin *plugi
 	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 @@ purple_plugins_probe(const char *ext)
 													(GCompareFunc)compare_prpl);
 		}
 	}
-
-	if (probe_cb != NULL)
-		probe_cb(probe_cb_data);
-
 #endif /* PURPLE_PLUGINS */
 }
 
@@ -1513,50 +1496,6 @@ purple_plugins_enabled(void)
 #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)
 {
============================================================
--- libpurple/plugin.h	a9769c4b5cea898831ab255f5fa4da9632d538e0
+++ libpurple/plugin.h	9490a14a777df5db74357039be3e45edff1e8324
@@ -317,8 +317,6 @@ gboolean purple_plugin_unload(PurplePlug
  * 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 @@ void purple_plugins_add_search_path(cons
  * 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,73 +562,7 @@ gboolean purple_plugins_enabled(void);
  */
 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.
  *
  * @param name The plugin name.
============================================================
--- libpurple/debug.c	6784d450303ff60b8713ce1f40c50c13a7f9a309
+++ libpurple/debug.c	1f07a5e221450697517fb50d49664b25a907bc59
@@ -224,12 +224,5 @@ purple_debug_init(void)
 		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);
 }
 
============================================================
--- libpurple/debug.h	3ba4c16eaf446f6ff5b933318195e8c12ea17ea7
+++ libpurple/debug.h	953d02706b77c840054be3a7dd86d68be9f98925
@@ -161,8 +161,6 @@ gboolean purple_debug_is_enabled(void);
  * 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 @@ void purple_debug_set_verbose(gboolean v
  * 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 @@ gboolean purple_debug_is_verbose(void);
  * @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 @@ void purple_debug_set_unsafe(gboolean un
  * @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);
 
============================================================
--- pidgin/gtkdebug.c	41efc8a66405dcbfe3d0d3ba52239d74c5f8b9a1
+++ pidgin/gtkdebug.c	1c51a02d41acfcaeb63dde3d6a38d384d6db5575
@@ -128,7 +128,11 @@ configure_cb(GtkWidget *w, GdkEventConfi
 static gboolean
 configure_cb(GtkWidget *w, GdkEventConfigure *event, DebugWindow *win)
 {
+#if GTK_CHECK_VERSION(2,18,0)
 	if (gtk_widget_get_visible(w)) {
+#else
+	if (GTK_WIDGET_VISIBLE(w)) {
+#endif
 		purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/width",  event->width);
 		purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/height", event->height);
 	}
@@ -186,7 +190,9 @@ find_cb(GtkWidget *w, DebugWindow *win)
 
 	gtk_container_set_border_width(GTK_CONTAINER(win->find), PIDGIN_HIG_BOX_SPACE);
 	gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE);
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(win->find), FALSE);
+#endif
 	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BORDER);
 	gtk_container_set_border_width(
 		GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BOX_SPACE);
@@ -622,8 +628,12 @@ regex_key_release_cb(GtkWidget *w, GdkEv
 
 static void
 regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) {
-	if(e->keyval == GDK_KEY_Return &&
+	if(e->keyval == GDK_Return &&
+#if GTK_CHECK_VERSION(2,18,0)
 	   gtk_widget_is_sensitive(win->filter) &&
+#else
+	   GTK_WIDGET_IS_SENSITIVE(win->filter) &&
+#endif
 	   !gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
 	{
 		gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), TRUE);
@@ -925,7 +935,7 @@ debug_window_new(void)
 		gtk_container_add(GTK_CONTAINER(item), gtk_label_new(_("Level ")));
 		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
 
-		win->filterlevel = gtk_combo_box_text_new();
+		win->filterlevel = gtk_combo_box_new_text();
 		item = gtk_tool_item_new();
 #if GTK_CHECK_VERSION(2,12,0)
 		gtk_widget_set_tooltip_text(win->filterlevel, _("Select the debug filter level."));
@@ -935,12 +945,12 @@ debug_window_new(void)
 		gtk_container_add(GTK_CONTAINER(item), win->filterlevel);
 		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
 
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("All"));
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Misc"));
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Info"));
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Warning"));
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Error "));
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Fatal Error"));
+		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("All"));
+		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Misc"));
+		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Info"));
+		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Warning"));
+		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Error "));
+		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Fatal Error"));
 		gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel),
 					purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel"));
 #ifdef USE_REGEX
============================================================
--- libpurple/blist.c	269ca437f879b25f4931396af7aa8254f346e4cf
+++ libpurple/blist.c	378a9f59fb3533ce6bf64daebc62f78fbaa1a59e
@@ -314,7 +314,7 @@ accountprivacy_to_xmlnode(PurpleAccount 
 	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)
@@ -641,7 +641,7 @@ purple_blist_load()
 				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;
@@ -956,12 +956,6 @@ purple_blist_update_node_icon(PurpleBlis
 		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?
@@ -1313,7 +1307,7 @@ void purple_blist_rename_group(PurpleGro
 
 				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);
@@ -1743,11 +1737,6 @@ purple_contact_get_group(const PurpleCon
 	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);
@@ -1785,6 +1774,13 @@ void purple_contact_invalidate_priority_
 	contact->priority_valid = FALSE;
 }
 
+int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline)   
+{
+	g_return_val_if_fail(contact != NULL, 0);
+
+	return offline ? contact->totalsize : contact->currentsize;
+}   
+
 PurpleGroup *purple_group_new(const char *name)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
@@ -2375,26 +2371,6 @@ const char *purple_buddy_get_server_alia
 	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;
============================================================
--- libpurple/blist.h	8a1cb3e38b767107811af6ea4cf78abb0a1b64f0
+++ libpurple/blist.h	e8112c0978fc5773f75801df4caf016b417b7eea
@@ -75,9 +75,6 @@ typedef enum
 
 } 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 @@ typedef enum
 #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 @@ struct _PurpleBlistUiOps
 	 * previous libpurple versions.
 	 *
 	 * @param node    The node which has been modified.
-	 *
-	 * @since 2.6.0.
 	 */
 	void (*save_node)(PurpleBlistNode *node);
 
@@ -241,7 +224,6 @@ struct _PurpleBlistUiOps
 	 * previous libpurple versions.
 	 *
 	 * @param node  The node which has been modified.
-	 * @since 2.6.0.
 	 */
 	void (*remove_node)(PurpleBlistNode *node);
 
@@ -256,7 +238,6 @@ struct _PurpleBlistUiOps
 	 *
 	 * @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 @@ PurpleBlistNode *purple_blist_get_root(v
  *         freeing the list.
  *
  * @see purple_find_buddies
- * @since 2.6.0
  */
 GSList *purple_blist_get_buddies(void);
 
@@ -319,8 +299,6 @@ GSList *purple_blist_get_buddies(void);
  * 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 @@ gpointer purple_blist_get_ui_data(void);
  * 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 @@ PurpleBlistNode *purple_blist_node_next(
  *
  * @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 @@ PurpleBlistNode *purple_blist_node_get_p
  *
  * @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 @@ PurpleBlistNode *purple_blist_node_get_f
  *
  * @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 @@ PurpleBlistNode *purple_blist_node_get_s
  *
  * @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 @@ PurpleBlistNode *purple_blist_node_get_s
  *
  * @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 @@ gpointer purple_blist_node_get_ui_data(c
  *
  * @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,22 +427,10 @@ void purple_blist_update_buddy_status(Pu
  * 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.
  *
  * @param buddy  The buddy whose name will be changed.
@@ -623,7 +584,6 @@ PurpleBuddyIcon *purple_buddy_get_icon(c
  * @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 @@ gpointer purple_buddy_get_protocol_data(
  * @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 @@ PurplePresence *purple_buddy_get_presenc
  *
  * @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 @@ void purple_contact_destroy(PurpleContac
  *
  * @param contact  The contact
  * @return         The group
- *
- * @since 2.7.0
  */
 PurpleGroup *purple_contact_get_group(const PurpleContact *contact);
 
@@ -774,19 +729,7 @@ PurpleBuddy *purple_contact_get_priority
  */
 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.
  *
  * @param contact  The contact
@@ -813,6 +756,15 @@ void purple_contact_invalidate_priority_
 void purple_contact_invalidate_priority_buddy(PurpleContact *contact);
 
 /**
+ * Determines the total size of a contact.
+ *
+ * @param contact	The contact
+ * @param offline	Count buddies in offline accounts
+ * @return The number of buddies in the contact
+ */
+int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline);
+
+/**
  * Removes a buddy from the buddy list and frees the memory allocated to it.
  * This doesn't actually try to remove the buddy from the server list.
  *
@@ -876,20 +828,7 @@ const char *purple_buddy_get_contact_ali
  */
 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;
  * the buddy's user name.
@@ -904,8 +843,6 @@ const char *purple_buddy_get_alias(Purpl
  *
  * @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 +918,6 @@ PurpleGroup *purple_chat_get_group(Purpl
  * @param chat  The chat.
  *
  * @return  The account the chat belongs to.
- *
- * @since 2.4.0
  */
 PurpleAccount *purple_chat_get_account(PurpleChat *chat);
 
@@ -992,8 +927,6 @@ PurpleAccount *purple_chat_get_account(P
  * @param chat  The chat.
  *
  * @constreturn  The hashtable.
- *
- * @since 2.4.0
  */
 GHashTable *purple_chat_get_components(PurpleChat *chat);
 
@@ -1211,8 +1144,6 @@ PurpleBlistNodeFlags purple_blist_node_g
  * @param node The node.
  *
  * @return The type of the node.
- *
- * @since 2.1.0
  */
 PurpleBlistNodeType purple_blist_node_get_type(PurpleBlistNode *node);
 
============================================================
--- pidgin/gtkblist.c	b512da5aafc01bae779465998a8fb0b7d9818384
+++ pidgin/gtkblist.c	40b8a067b95cff543efab5485cff0f73f85e5372
@@ -124,6 +124,11 @@ typedef struct
 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \
 	((PidginBuddyListPrivate *)((list)->priv))
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
+#define gtk_widget_has_focus(x) GTK_WIDGET_HAS_FOCUS(x)
+#endif
+
 static guint accounts_merge_id;
 static GtkActionGroup *accounts_action_group = NULL;
 
@@ -346,13 +351,13 @@ static void gtk_blist_menu_autojoin_cb(G
 
 static void gtk_blist_menu_autojoin_cb(GtkWidget *w, PurpleChat *chat)
 {
-	purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin",
+	purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin",
 			gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
 }
 
 static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat)
 {
-	purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent",
+	purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent",
 			gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
 }
 
@@ -462,9 +467,9 @@ gtk_blist_do_personize(GList *merges)
 	GList *tmp;
 
 	/* First, we find the contact to merge the rest of the buddies into.
-	 * This will be the contact with the most buddies in it; ties are broken
-	 * by which contact is higher in the list
-	 */
+ 	 * This will be the contact with the most buddies in it; ties are broken
+ 	 * by which contact is higher in the list
+ 	 */
 	for (tmp = merges; tmp; tmp = tmp->next) {
 		PurpleBlistNode *node = tmp->data;
 		PurpleBlistNode *b;
@@ -919,7 +924,7 @@ set_sensitive_if_input_cb(GtkWidget *ent
 	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);
@@ -943,7 +948,7 @@ chat_account_filter_func(PurpleAccount *
 	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);
 }
@@ -985,23 +990,20 @@ make_blist_request_dialog(PidginBlistReq
 	gtkblist = PIDGIN_BLIST(purple_get_blist());
 	blist_window = gtkblist ? GTK_WINDOW(gtkblist->window) : NULL;
 
-	/* TODO: set no separator in gtk+ 3... */
 	data->window = gtk_dialog_new_with_buttons(title,
-		blist_window, 0, NULL);
+		blist_window, GTK_DIALOG_NO_SEPARATOR,
+		NULL);
 
 	gtk_window_set_transient_for(GTK_WINDOW(data->window), blist_window);
 	gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK);
 	gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE);
 	gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE);
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(data->window))),
-	                    PIDGIN_HIG_BORDER);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(data->window))),
-	                               PIDGIN_HIG_BOX_SPACE);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BORDER);
+	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BOX_SPACE);
 	gtk_window_set_role(GTK_WINDOW(data->window), window_role);
 
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(data->window))),
-	                  hbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox);
 	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
 	gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
 
@@ -1036,6 +1038,7 @@ rebuild_chat_entries(PidginChatData *dat
 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;
@@ -1044,17 +1047,18 @@ rebuild_chat_entries(PidginChatData *dat
 	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 (prpl_info->chat_info != NULL)
+		list = prpl_info->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_defaults != NULL)
+		defaults = prpl_info->chat_info_defaults(gc, default_chat_name);
 
 	for (tmp = list; tmp; tmp = tmp->next)
 	{
@@ -1064,7 +1068,7 @@ rebuild_chat_entries(PidginChatData *dat
 
 		if (pce->is_int)
 		{
-			GtkAdjustment *adjust;
+			GtkObject *adjust;
 			adjust = gtk_adjustment_new(pce->min, pce->min, pce->max,
 										1, 10, 10);
 			input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
@@ -1417,7 +1421,7 @@ pidgin_append_blist_node_proto_menu(GtkW
                                       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;
@@ -1525,7 +1529,7 @@ pidgin_blist_make_buddy_menu(GtkWidget *
 
 	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,
@@ -1553,14 +1557,14 @@ pidgin_blist_make_buddy_menu(GtkWidget *
 				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)
-		pidgin_append_blist_node_move_to_menu(menu, (PurpleBlistNode *)contact);
+		pidgin_append_blist_node_move_to_menu(menu, PURPLE_BLIST_NODE(contact));
 
 	if (node->parent && node->parent->child->next &&
-	    !sub && !contact_expanded) {
+              !sub && !contact_expanded) {
 		pidgin_separator(menu);
 		pidgin_append_blist_node_privacy_menu(menu, node);
 		pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS,
@@ -1606,14 +1610,14 @@ gtk_blist_key_press_cb(GtkWidget *tv, Gd
 			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_KEY_F2:
+			case GDK_F2:
 				gtk_blist_menu_alias_cb(tv, node);
 				break;
 
-			case GDK_KEY_Left:
+			case GDK_Left:
 				path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter);
 				if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path)) {
 					/* Collapse the Group */
@@ -1635,7 +1639,7 @@ gtk_blist_key_press_cb(GtkWidget *tv, Gd
 				gtk_tree_path_free(path);
 				break;
 
-			case GDK_KEY_Right:
+			case GDK_Right:
 				path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter);
 				if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path)) {
 					/* Expand the Group */
@@ -1759,7 +1763,7 @@ create_chat_menu(PurpleBlistNode *node, 
 	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(purple_chat_get_account(c)), node);
 	pidgin_append_blist_node_extended_menu(menu, node);
 
 	pidgin_separator(menu);
@@ -1809,7 +1813,7 @@ create_buddy_menu(PurpleBlistNode *node,
 static GtkWidget *
 create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b)
 {
-	struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkWidget *menu;
 	GtkWidget *menuitem;
 	gboolean show_offline = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies");
@@ -1844,13 +1848,13 @@ create_buddy_menu(PurpleBlistNode *node,
 
 				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),
@@ -1877,12 +1881,10 @@ pidgin_blist_show_context_menu(PurpleBli
 								 guint button,
 								 guint32 time)
 {
-	struct _pidgin_blist_node *gtknode;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkWidget *menu = NULL;
 	gboolean handled = FALSE;
 
-	gtknode = (struct _pidgin_blist_node *)node->ui_data;
-
 	/* Create a menu based on the thing we right-clicked on */
 	if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
 		PurpleGroup *g = (PurpleGroup *)node;
@@ -1944,7 +1946,7 @@ gtk_blist_button_press_cb(GtkWidget *tv,
 		return FALSE;
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
 	gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1);
-	gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	gtknode = purple_blist_node_get_ui_data(node);
 
 	/* Right click draws a context menu */
 	if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) {
@@ -1968,12 +1970,12 @@ gtk_blist_button_press_cb(GtkWidget *tv,
 		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;
 	}
 
@@ -2123,7 +2125,7 @@ add_buddies_from_vcard(const char *prpl_
 		for (l = list; l != NULL; l = l->next)
 		{
 			purple_blist_request_add_buddy(account, l->data,
-										 (group ? group->name : NULL),
+										 (group ? purple_group_get_name(group) : NULL),
 										 alias);
 		}
 	}
@@ -2250,9 +2252,9 @@ static void pidgin_blist_drag_data_get_c
 											guint time,
 											gpointer null)
 {
-	GdkAtom target = gtk_selection_data_get_target(data);
 
-	if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) {
+	if (data->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE))
+	{
 		GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row");
 		GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref);
 		GtkTreeIter iter;
@@ -2268,7 +2270,9 @@ static void pidgin_blist_drag_data_get_c
 					sizeof (node));
 
 		gtk_tree_path_free(sourcerow);
-	} else if (target == gdk_atom_intern("application/x-im-contact", FALSE)) {
+	}
+	else if (data->target == gdk_atom_intern("application/x-im-contact", FALSE))
+	{
 		GtkTreeRowReference *ref;
 		GtkTreePath *sourcerow;
 		GtkTreeIter iter;
@@ -2302,7 +2306,7 @@ static void pidgin_blist_drag_data_get_c
 			buddy = (PurpleBuddy *)node;
 		}
 
-		gc = purple_account_get_connection(buddy->account);
+		gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
 		if (gc == NULL)
 		{
@@ -2311,7 +2315,7 @@ static void pidgin_blist_drag_data_get_c
 		}
 
 		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);
@@ -2321,13 +2325,13 @@ static void pidgin_blist_drag_data_get_c
 			"X-IM-Protocol: %s\r\n"
 			"X-IM-Username: %s\r\n",
 			protocol,
-			buddy->name);
+			purple_buddy_get_name(buddy));
 
-		if (buddy->alias != NULL)
+		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");
@@ -2346,19 +2350,16 @@ static void pidgin_blist_drag_data_rcv_c
 static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
 			  GtkSelectionData *sd, guint info, guint t)
 {
-	GdkAtom target = gtk_selection_data_get_target(sd);
-	const guchar *data = gtk_selection_data_get_data(sd);
-
 	if (gtkblist->drag_timeout) {
 		g_source_remove(gtkblist->drag_timeout);
 		gtkblist->drag_timeout = 0;
 	}
 
-	if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE) && data) {
+	if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE) && sd->data) {
 		PurpleBlistNode *n = NULL;
 		GtkTreePath *path = NULL;
 		GtkTreeViewDropPosition position;
-		memcpy(&n, data, sizeof(n));
+		memcpy(&n, sd->data, sizeof(n));
 		if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) {
 			/* if we're here, I think it means the drop is ok */
 			GtkTreeIter iter;
@@ -2369,7 +2370,7 @@ static void pidgin_blist_drag_data_rcv_c
 					&iter, path);
 			gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel),
 					&iter, NODE_COLUMN, &node, -1);
-			gtknode = node->ui_data;
+			gtknode = purple_blist_node_get_ui_data(node);
 
 			if (PURPLE_BLIST_NODE_IS_CONTACT(n)) {
 				PurpleContact *c = (PurpleContact*)n;
@@ -2494,10 +2495,12 @@ static void pidgin_blist_drag_data_rcv_c
 			}
 
 			gtk_tree_path_free(path);
-			gtk_drag_finish(dc, TRUE, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t);
+			gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 		}
-	} else if (target == gdk_atom_intern("application/x-im-contact",
-										   FALSE) && data) {
+	}
+	else if (sd->target == gdk_atom_intern("application/x-im-contact",
+										   FALSE) && sd->data)
+	{
 		PurpleGroup *group = NULL;
 		GtkTreePath *path = NULL;
 		GtkTreeViewDropPosition position;
@@ -2532,7 +2535,7 @@ static void pidgin_blist_drag_data_rcv_c
 			}
 		}
 
-		if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account,
+		if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account,
 										&protocol, &username, &alias))
 		{
 			if (account == NULL)
@@ -2544,7 +2547,7 @@ static void pidgin_blist_drag_data_rcv_c
 			else
 			{
 				purple_blist_request_add_buddy(account, username,
-											 (group ? group->name : NULL),
+											 (group ? purple_group_get_name(group) : NULL),
 											 alias);
 			}
 		}
@@ -2556,10 +2559,9 @@ static void pidgin_blist_drag_data_rcv_c
 		if (path != NULL)
 			gtk_tree_path_free(path);
 
-		gtk_drag_finish(dc, TRUE,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+		gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t);
 	}
-	else if (target == gdk_atom_intern("text/x-vcard", FALSE) && data)
+	else if (sd->target == gdk_atom_intern("text/x-vcard", FALSE) && sd->data)
 	{
 		gboolean result;
 		PurpleGroup *group = NULL;
@@ -2592,11 +2594,10 @@ static void pidgin_blist_drag_data_rcv_c
 			}
 		}
 
-		result = parse_vcard((const gchar *) data, group);
+		result = parse_vcard((const gchar *)sd->data, group);
 
-		gtk_drag_finish(dc, result,
-		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
-	} else if (target == gdk_atom_intern("text/uri-list", FALSE) && data) {
+		gtk_drag_finish(dc, result, (dc->action == GDK_ACTION_MOVE), t);
+	} else if (sd->target == gdk_atom_intern("text/uri-list", FALSE) && sd->data) {
 		GtkTreePath *path = NULL;
 		GtkTreeViewDropPosition position;
 
@@ -2613,9 +2614,8 @@ static void pidgin_blist_drag_data_rcv_c
 
 				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);
-					gtk_drag_finish(dc, TRUE,
-					                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
+					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);
 				}
@@ -2687,8 +2687,8 @@ static GdkPixbuf *pidgin_blist_get_buddy
 		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
@@ -2701,7 +2701,7 @@ static GdkPixbuf *pidgin_blist_get_buddy
 	 * a contact then this is a group or some other type of node and we
 	 * want to use that directly. */
 	if (contact) {
-		custom_img = purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact);
+		custom_img = purple_buddy_icons_node_find_custom_icon(PURPLE_BLIST_NODE(contact));
 	} else {
 		custom_img = purple_buddy_icons_node_find_custom_icon(node);
 	}
@@ -2714,7 +2714,7 @@ static GdkPixbuf *pidgin_blist_get_buddy
 	if (data == NULL) {
 		if (buddy) {
 			/* Not sure I like this...*/
-			if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name)))
+			if (!(icon = purple_buddy_icons_find(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))))
 				return NULL;
 			data = purple_buddy_icon_get_data(icon, &len);
 		}
@@ -2884,9 +2884,9 @@ static struct tooltip_data * create_tip_
 	char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL;
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		account = ((PurpleBuddy*)(node))->account;
+		account = purple_buddy_get_account((PurpleBuddy*)(node));
 	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
-		account = ((PurpleChat*)(node))->account;
+		account = purple_chat_get_account((PurpleChat*)(node));
 	}
 
 	td->padding = TOOLTIP_BORDER;
@@ -2940,6 +2940,7 @@ pidgin_blist_paint_tip(GtkWidget *widget
 pidgin_blist_paint_tip(GtkWidget *widget, gpointer null)
 {
 	GtkStyle *style;
+	cairo_t *cr;
 	int current_height, max_width;
 	int max_text_width;
 	int max_avatar_width;
@@ -2951,7 +2952,7 @@ pidgin_blist_paint_tip(GtkWidget *widget
 	if(gtkblist->tooltipdata == NULL)
 		return FALSE;
 
-	style = gtk_widget_get_style(gtkblist->tipwindow);
+	style = gtkblist->tipwindow->style;
 
 	max_text_width = 0;
 	max_avatar_width = 0;
@@ -2973,86 +2974,89 @@ pidgin_blist_paint_tip(GtkWidget *widget
 	else
 		prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE;
 
+	cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(gtkblist->tipwindow)));
 	current_height = 12;
 	for(l = gtkblist->tooltipdata; l; l = l->next)
 	{
 		struct tooltip_data *td = l->data;
-		cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(gtkblist->tipwindow));
 
 		if (td->avatar && pidgin_gdk_pixbuf_is_opaque(td->avatar))
 		{
 			if (dir == GTK_TEXT_DIR_RTL)
-				gtk_paint_flat_box(style, cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-						gtkblist->tipwindow, "tooltip",
-						TOOLTIP_BORDER - 1, current_height - 1,
-						td->avatar_width + 2, td->avatar_height + 2);
+				gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+						NULL, gtkblist->tipwindow, "tooltip",
+						TOOLTIP_BORDER -1, current_height -1, td->avatar_width +2, td->avatar_height + 2);
 			else
-				gtk_paint_flat_box(style, cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-						gtkblist->tipwindow, "tooltip",
-						max_width - (td->avatar_width + TOOLTIP_BORDER) - 1,
-						current_height - 1,
-						td->avatar_width + 2, td->avatar_height + 2);
+				gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+						NULL, gtkblist->tipwindow, "tooltip",
+						max_width - (td->avatar_width+ TOOLTIP_BORDER)-1,
+						current_height-1,td->avatar_width+2, td->avatar_height+2);
 		}
 
 		if (td->status_icon) {
 			if (dir == GTK_TEXT_DIR_RTL) {
 				gdk_cairo_set_source_pixbuf(cr, td->status_icon,
-					max_width - TOOLTIP_BORDER - status_size, current_height);
+				                            max_width - TOOLTIP_BORDER - status_size,
+				                            current_height);
 				cairo_paint(cr);
 			} else {
-				gdk_cairo_set_source_pixbuf(cr, td->status_icon, TOOLTIP_BORDER, current_height);
+				gdk_cairo_set_source_pixbuf(cr, td->status_icon,
+				                            TOOLTIP_BORDER, current_height);
 				cairo_paint(cr);
 			}
 		}
 
-		if (td->avatar) {
+		if(td->avatar) {
 			if (dir == GTK_TEXT_DIR_RTL) {
-				gdk_cairo_set_source_pixbuf(cr, td->avatar, TOOLTIP_BORDER,
-					current_height);
+				gdk_cairo_set_source_pixbuf(cr, td->avatar,
+				                            TOOLTIP_BORDER, current_height);
 				cairo_paint(cr);
 			} else {
 				gdk_cairo_set_source_pixbuf(cr, td->avatar,
-					max_width - (td->avatar_width + TOOLTIP_BORDER), current_height);
+				                            max_width - (td->avatar_width + TOOLTIP_BORDER),
+				                            current_height);
 				cairo_paint(cr);
 			}
 		}
 
 		if (!td->avatar_is_prpl_icon && td->prpl_icon) {
 			gdk_cairo_set_source_pixbuf(cr, td->prpl_icon, prpl_col,
-				current_height + ((td->name_height / 2) - (PRPL_SIZE / 2)));
+			                            current_height +
+			                               (td->name_height - PRPL_SIZE) / 2);
 			cairo_paint(cr);
 		}
 
 		if (td->name_layout) {
 			if (dir == GTK_TEXT_DIR_RTL) {
-				gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
-						gtkblist->tipwindow, "tooltip",
-						max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
+				gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
+						max_width  -(TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
 						current_height, td->name_layout);
 			} else {
-				gtk_paint_layout (style, cr, GTK_STATE_NORMAL, FALSE,
-						gtkblist->tipwindow, "tooltip",
+				gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
 						TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height, td->name_layout);
 			}
 		}
 
 		if (td->layout) {
 			if (dir != GTK_TEXT_DIR_RTL) {
-				gtk_paint_layout (style, cr, GTK_STATE_NORMAL, FALSE,
-						gtkblist->tipwindow, "tooltip",
+				gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
 						TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout);
 			} else {
-				gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
-						gtkblist->tipwindow, "tooltip",
+				gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
 						max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
 						current_height + td->name_height,
 						td->layout);
 			}
 		}
 
-		cairo_destroy(cr);
 		current_height += MAX(td->name_height + td->height, td->avatar_height) + td->padding;
 	}
+
+	cairo_destroy(cr);
 	return FALSE;
 }
 
@@ -3193,7 +3197,7 @@ static gboolean pidgin_blist_expand_time
 		return FALSE;
 	}
 
-	gtknode = node->ui_data;
+	gtknode = purple_blist_node_get_ui_data(node);
 
 	if (!gtknode->contact_expanded) {
 		GtkTreeIter i;
@@ -3201,8 +3205,7 @@ static gboolean pidgin_blist_expand_time
 		pidgin_blist_expand_contact_cb(NULL, node);
 
 		gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &gtkblist->contact_rect);
-		gtkblist->contact_rect.width =
-		gdk_window_get_width(gtk_widget_get_window(tv));
+		gdk_drawable_get_size(GDK_DRAWABLE(tv->window), &(gtkblist->contact_rect.width), NULL);
 		gtkblist->mouseover_contact = node;
 		gtk_tree_path_down (path);
 		while (gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &i, path)) {
@@ -3223,13 +3226,13 @@ static gboolean buddy_is_displayable(Pur
 	if(!buddy)
 		return FALSE;
 
-	gtknode = ((PurpleBlistNode*)buddy)->ui_data;
+	gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 
-	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")));
+			 purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy), "show_offline")));
 }
 
 void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget)
@@ -3404,7 +3407,7 @@ edit_mood_cb(PurpleConnection *gc, Purpl
 			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);
@@ -3420,7 +3423,7 @@ edit_mood_cb(PurpleConnection *gc, Purpl
 				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);
 				}
 			}
@@ -3455,9 +3458,9 @@ get_global_moods(void)
 		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
@@ -3515,7 +3518,7 @@ get_global_mood_status(void)
 		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");
@@ -3550,8 +3553,8 @@ set_mood_cb(GtkWidget *widget, PurpleAcc
 		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();
@@ -3561,7 +3564,7 @@ set_mood_cb(GtkWidget *widget, PurpleAcc
 	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"));
 
@@ -3590,7 +3593,7 @@ set_mood_cb(GtkWidget *widget, PurpleAcc
 	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);
@@ -3599,11 +3602,11 @@ set_mood_cb(GtkWidget *widget, PurpleAcc
 	}
 
 	purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
-	                      NULL, fields,
-	                      _("OK"), G_CALLBACK(edit_mood_cb),
-	                      _("Cancel"), NULL,
-	                      gc ? purple_connection_get_account(gc) : NULL,
-	                      NULL, NULL, gc);
+                              NULL, fields,
+                              _("OK"), G_CALLBACK(edit_mood_cb),
+                              _("Cancel"), NULL,
+                              gc ? purple_connection_get_account(gc) : NULL,
+                              NULL, NULL, gc);
 
 	g_free(global_moods);
 }
@@ -3617,9 +3620,10 @@ set_mood_show(void)
 /***************************************************
  *            Crap                                 *
  ***************************************************/
-#if 1
 /* TODO: fill out tooltips... */
 static const GtkActionEntry blist_menu_entries[] = {
+/* NOTE: Do not set any accelerator to Control+O. It is mapped by
+   gtk_blist_key_press_cb to "Get User Info" on the selected buddy. */
 	/* Buddies menu */
 	{ "BuddiesMenu", NULL, N_("_Buddies"), NULL, NULL, NULL },
 	{ "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, pidgin_dialogs_im },
@@ -3646,7 +3650,7 @@ static const GtkActionEntry blist_menu_e
 	{ "Plugins", PIDGIN_STOCK_TOOLBAR_PLUGINS, N_("Plu_gins"), "<control>U", NULL, pidgin_plugin_dialog_show },
 	{ "Preferences", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), "<control>P", NULL, pidgin_prefs_show },
 	{ "Privacy", NULL, N_("Pr_ivacy"), NULL, NULL, pidgin_privacy_dialog_show },
-	{ "SetMood", NULL, N_("Set _Mood"), "<control>O", NULL, set_mood_show },
+	{ "SetMood", NULL, N_("Set _Mood"), "<control>D", NULL, set_mood_show },
 	{ "FileTransfers", PIDGIN_STOCK_TOOLBAR_TRANSFER, N_("_File Transfers"), "<control>T", NULL, G_CALLBACK(gtk_blist_show_xfer_dialog_cb) },
 	{ "RoomList", NULL, N_("R_oom List"), NULL, NULL, pidgin_roomlist_dialog_show },
 	{ "SystemLog", NULL, N_("System _Log"), NULL, NULL, gtk_blist_show_systemlog_cb },
@@ -3657,6 +3661,7 @@ static const GtkActionEntry blist_menu_e
 	{ "BuildInformation", NULL, N_("_Build Information"), NULL, NULL, pidgin_dialogs_buildinfo },
 	{ "DebugWindow", NULL, N_("_Debug Window"), NULL, NULL, toggle_debug },
 	{ "DeveloperInformation", NULL, N_("De_veloper Information"), NULL, NULL, pidgin_dialogs_developers },
+	{ "PluginInformation", NULL, N_("_Plugin Information"), NULL, NULL, pidgin_dialogs_plugins_info },
 	{ "TranslatorInformation", NULL, N_("_Translator Information"), NULL, NULL, pidgin_dialogs_translators },
 	{ "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, pidgin_dialogs_about },
 };
@@ -3726,6 +3731,7 @@ static const char *blist_menu =
 			"<menuitem action='BuildInformation'/>"
 			"<menuitem action='DebugWindow'/>"
 			"<menuitem action='DeveloperInformation'/>"
+			"<menuitem action='PluginInformation'/>"
 			"<menuitem action='TranslatorInformation'/>"
 			"<separator/>"
 			"<menuitem action='About'/>"
@@ -3733,66 +3739,6 @@ static const char *blist_menu =
 	"</menubar>"
 "</ui>";
 
-#else
-static GtkItemFactoryEntry blist_menu[] =
-{
-/* NOTE: Do not set any accelerator to Control+O. It is mapped by
-   gtk_blist_key_press_cb to "Get User Info" on the selected buddy. */
-
-	/* Buddies menu */
-	{ N_("/_Buddies"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Buddies/New Instant _Message..."), "<CTL>M", pidgin_dialogs_im, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW },
-	{ N_("/Buddies/Join a _Chat..."), "<CTL>C", pidgin_blist_joinchat_show, 0, "<StockItem>", PIDGIN_STOCK_CHAT },
-	{ N_("/Buddies/Get User _Info..."), "<CTL>I", pidgin_dialogs_info, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO },
-	{ N_("/Buddies/View User _Log..."), "<CTL>L", pidgin_dialogs_log, 0, "<Item>", NULL },
-	{ "/Buddies/sep1", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Buddies/Sh_ow"), NULL, NULL, 0, "<Branch>", NULL},
-	{ N_("/Buddies/Show/_Offline Buddies"), NULL, pidgin_blist_edit_mode_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/_Empty Groups"), NULL, pidgin_blist_show_empty_groups_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/Buddy _Details"), NULL, pidgin_blist_buddy_details_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/Idle _Times"), NULL, pidgin_blist_show_idle_time_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/_Protocol Icons"), NULL, pidgin_blist_show_protocol_icons_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/_Sort Buddies"), NULL, NULL, 0, "<Branch>", NULL },
-	{ "/Buddies/sep2", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Buddies/_Add Buddy..."), "<CTL>B", pidgin_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD },
-	{ N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD },
-	{ N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD },
-	{ "/Buddies/sep3", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Buddies/_Quit"), "<CTL>Q", purple_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
-
-	/* Accounts menu */
-	{ N_("/_Accounts"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Accounts/Manage Accounts"), "<CTL>A", pidgin_accounts_window_show, 0, "<Item>", NULL },
-
-	/* Tools */
-	{ N_("/_Tools"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Tools/Buddy _Pounces"), NULL, pidgin_pounces_manager_show, 1, "<Item>", NULL },
-	{ N_("/Tools/_Certificates"), NULL, pidgin_certmgr_show, 0, "<Item>", NULL },
-	{ N_("/Tools/Custom Smile_ys"), "<CTL>Y", pidgin_smiley_manager_show, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SMILEY },
-	{ N_("/Tools/Plu_gins"), "<CTL>U", pidgin_plugin_dialog_show, 2, "<StockItem>", PIDGIN_STOCK_TOOLBAR_PLUGINS },
-	{ N_("/Tools/Pr_eferences"), "<CTL>P", pidgin_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES },
-	{ N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "<Item>", NULL },
-	{ N_("/Tools/Set _Mood"), "<CTL>D", set_mood_show, 0, "<Item>", NULL },
-	{ "/Tools/sep2", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_TRANSFER },
-	{ N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
-	{ N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 3, "<Item>", NULL },
-	{ "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Tools/Mute _Sounds"), NULL, pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
-	/* Help */
-	{ N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP },
-	{ "/Help/sep1", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Help/_Build Information"), NULL, pidgin_dialogs_buildinfo, 0, "<Item>", NULL },
-	{ N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
-	{ N_("/Help/De_veloper Information"), NULL, pidgin_dialogs_developers, 0, "<Item>", NULL },
-	{ N_("/Help/_Plugin Information"), NULL, pidgin_dialogs_plugins_info, 0, "<Item>", NULL },
-	{ N_("/Help/_Translator Information"), NULL, pidgin_dialogs_translators, 0, "<Item>", NULL },
-	{ "/Help/sep2", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Help/_About"), NULL, pidgin_dialogs_about, 4,  "<StockItem>", GTK_STOCK_ABOUT },
-};
-#endif
-
 /*********************************************************
  * Private Utility functions                             *
  *********************************************************/
@@ -3812,16 +3758,16 @@ static char *pidgin_get_tooltip_text(Pur
 		struct proto_chat_entry *pce;
 		char *name, *value;
 		PurpleConversation *conv;
-		PidginBlistNode *bnode = node->ui_data;
+		PidginBlistNode *bnode = purple_blist_node_get_ui_data(node);
 
 		chat = (PurpleChat *)node;
-		prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
+		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_chat_get_account(chat)));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 		connections = purple_connections_get_all();
 		if (connections && connections->next)
 		{
-			tmp = g_markup_escape_text(chat->account->username, -1);
+			tmp = g_markup_escape_text(purple_account_get_username(purple_chat_get_account(chat)), -1);
 			g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
 			g_free(tmp);
 		}
@@ -3831,12 +3777,12 @@ static char *pidgin_get_tooltip_text(Pur
 		} else {
 			char *chat_name;
 			if (prpl_info && prpl_info->get_chat_name)
-				chat_name = prpl_info->get_chat_name(chat->components);
+				chat_name = prpl_info->get_chat_name(purple_chat_get_components(chat));
 			else
 				chat_name = g_strdup(purple_chat_get_name(chat));
 
 			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chat_name,
-					chat->account);
+					purple_chat_get_account(chat));
 			g_free(chat_name);
 		}
 
@@ -3853,7 +3799,7 @@ static char *pidgin_get_tooltip_text(Pur
 		}
 
 		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(purple_chat_get_account(chat)));
 		else
 			cur = NULL;
 
@@ -3862,13 +3808,13 @@ static char *pidgin_get_tooltip_text(Pur
 			pce = cur->data;
 
 			if (!pce->secret && (!pce->required &&
-				g_hash_table_lookup(chat->components, pce->identifier) == NULL))
+				g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier) == NULL))
 			{
 				tmp = purple_text_strip_mnemonic(pce->label);
 				name = g_markup_escape_text(tmp, -1);
 				g_free(tmp);
 				value = g_markup_escape_text(g_hash_table_lookup(
-										chat->components, pce->identifier), -1);
+										purple_chat_get_components(chat), pce->identifier), -1);
 				g_string_append_printf(str, "\n<b>%s</b> %s",
 							name ? name : "",
 							value ? value : "");
@@ -3904,7 +3850,7 @@ static char *pidgin_get_tooltip_text(Pur
 			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);
@@ -3921,12 +3867,12 @@ static char *pidgin_get_tooltip_text(Pur
 		/* Alias */
 		/* If there's not a contact alias, the node is being displayed with
 		 * this alias, so there's no point in showing it in the tooltip. */
-		if (full && c && b->alias != NULL && b->alias[0] != '\0' &&
+		if (full && c && purple_buddy_get_local_buddy_alias(b) != NULL && purple_buddy_get_local_buddy_alias(b)[0] != '\0' &&
 		    (c->alias != NULL && c->alias[0] != '\0') &&
-		    strcmp(c->alias, b->alias) != 0)
+		    strcmp(c->alias, purple_buddy_get_local_buddy_alias(b)) != 0)
 		{
 			purple_notify_user_info_add_pair_plaintext(user_info,
-					_("Buddy Alias"), b->alias);
+					_("Buddy Alias"), purple_buddy_get_local_buddy_alias(b));
 		}
 
 		/* Nickname/Server Alias */
@@ -3934,10 +3880,10 @@ static char *pidgin_get_tooltip_text(Pur
 		 * alias, but many people on MSN set long nicknames, which
 		 * get ellipsized, so the only way to see the whole thing is
 		 * to look at the tooltip. */
-		if (full && b->server_alias != NULL && b->server_alias[0] != '\0')
+		if (full && purple_buddy_get_server_alias(b))
 		{
 			purple_notify_user_info_add_pair_plaintext(user_info,
-					_("Nickname"), b->server_alias);
+					_("Nickname"), purple_buddy_get_server_alias(b));
 		}
 
 		/* Logged In */
@@ -3972,7 +3918,7 @@ static char *pidgin_get_tooltip_text(Pur
 		/* Last Seen */
 		if (full && c && !PURPLE_BUDDY_IS_ONLINE(b))
 		{
-			struct _pidgin_blist_node *gtknode = ((PurpleBlistNode *)c)->ui_data;
+			struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(c));
 			PurpleBlistNode *bnode;
 			int lastseen = 0;
 
@@ -4012,7 +3958,7 @@ static char *pidgin_get_tooltip_text(Pur
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Offline"));
 		}
 
-		if (purple_account_is_connected(b->account) &&
+		if (purple_account_is_connected(purple_buddy_get_account(b)) &&
 				prpl_info && prpl_info->tooltip_text)
 		{
 			/* Additional text from the PRPL */
@@ -4020,11 +3966,11 @@ static char *pidgin_get_tooltip_text(Pur
 		}
 
 		/* These are Easter Eggs.  Patches to remove them will be rejected. */
-		if (!g_ascii_strcasecmp(b->name, "robflynn"))
+		if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "robflynn"))
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Description"), _("Spooky"));
-		if (!g_ascii_strcasecmp(b->name, "seanegn"))
+		if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "seanegn"))
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Awesome"));
-		if (!g_ascii_strcasecmp(b->name, "chipx86"))
+		if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "chipx86"))
 			purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Rockin'"));
 
 		tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n");
@@ -4101,7 +4047,7 @@ pidgin_blist_get_emblem(PurpleBlistNode 
 pidgin_blist_get_emblem(PurpleBlistNode *node)
 {
 	PurpleBuddy *buddy = NULL;
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	PurplePlugin *prpl;
 	PurplePluginProtocolInfo *prpl_info;
 	const char *name = NULL;
@@ -4124,10 +4070,10 @@ pidgin_blist_get_emblem(PurpleBlistNode 
 			return _pidgin_blist_get_cached_emblem(path);
 		}
 
-		if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) {
+		if (((struct _pidgin_blist_node*)purple_blist_node_get_ui_data(node->parent))->contact_expanded) {
 			if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"))
 				return NULL;
-			return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
+			return pidgin_create_prpl_icon(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PRPL_ICON_SMALL);
 		}
 	} else {
 		return NULL;
@@ -4135,7 +4081,7 @@ pidgin_blist_get_emblem(PurpleBlistNode 
 
 	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);
 	}
@@ -4171,7 +4117,7 @@ pidgin_blist_get_emblem(PurpleBlistNode 
 		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;
 
@@ -4208,7 +4154,7 @@ pidgin_blist_get_status_icon(PurpleBlist
 {
 	GdkPixbuf *ret;
 	const char *icon = NULL;
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	struct _pidgin_blist_node *gtkbuddynode = NULL;
 	PurpleBuddy *buddy = NULL;
 	PurpleChat *chat = NULL;
@@ -4219,11 +4165,11 @@ pidgin_blist_get_status_icon(PurpleBlist
 		if(!gtknode->contact_expanded) {
 			buddy = purple_contact_get_priority_buddy((PurpleContact*)node);
 			if (buddy != NULL)
-				gtkbuddynode = ((PurpleBlistNode*)buddy)->ui_data;
+				gtkbuddynode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 		}
 	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		buddy = (PurpleBuddy*)node;
-		gtkbuddynode = node->ui_data;
+		gtkbuddynode = purple_blist_node_get_ui_data(node);
 	} else if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
 		chat = (PurpleChat*)node;
 	} else {
@@ -4235,9 +4181,9 @@ pidgin_blist_get_status_icon(PurpleBlist
 		PurplePlugin *prpl;
 
 		if(buddy)
-			account = buddy->account;
+			account = purple_buddy_get_account(buddy);
 		else
-			account = chat->account;
+			account = purple_chat_get_account(chat);
 
 		prpl = purple_find_prpl(purple_account_get_protocol_id(account));
 		if(!prpl)
@@ -4252,7 +4198,7 @@ pidgin_blist_get_status_icon(PurpleBlist
 		if(conv != NULL) {
 			PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
 			if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) {
-				PidginBlistNode *ui = buddy->node.ui_data;
+				PidginBlistNode *ui = purple_blist_node_get_ui_data(&(buddy->node));
 				if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE))
 					return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview),
 							PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView");
@@ -4336,7 +4282,7 @@ pidgin_blist_get_name_markup(PurpleBuddy
 	PidginBlistTheme *theme;
 
 	if (conv != NULL) {
-		PidginBlistNode *ui = b->node.ui_data;
+		PidginBlistNode *ui = purple_blist_node_get_ui_data(&(b->node));
 		if (ui) {
 			if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)
 				hidden_conv = TRUE;
@@ -4370,12 +4316,12 @@ pidgin_blist_get_name_markup(PurpleBuddy
 	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;
 
@@ -4570,7 +4516,7 @@ static gboolean pidgin_blist_refresh_tim
 
 				if (buddy &&
 						purple_presence_is_idle(purple_buddy_get_presence(buddy)))
-					pidgin_blist_update_contact(list, (PurpleBlistNode*)buddy);
+					pidgin_blist_update_contact(list, PURPLE_BLIST_NODE(buddy));
 			}
 		}
 	}
@@ -4581,7 +4527,7 @@ static void pidgin_blist_hide_node(Purpl
 
 static void pidgin_blist_hide_node(PurpleBuddyList *list, PurpleBlistNode *node, gboolean update)
 {
-	struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkTreeIter iter;
 
 	if (!gtknode || !gtknode->row || !gtkblist)
@@ -4739,6 +4685,7 @@ conversation_updated_cb(PurpleConversati
 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;
@@ -4746,10 +4693,10 @@ conversation_updated_cb(PurpleConversati
 	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);
+			pidgin_blist_update_buddy(NULL, PURPLE_BLIST_NODE(buddy), TRUE);
 	}
 
 	if (gtkblist->menutrayicon) {
@@ -4829,7 +4776,7 @@ written_msg_update_ui_cb(PurpleAccount *
 written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message,
 		PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node)
 {
-	PidginBlistNode *ui = node->ui_data;
+	PidginBlistNode *ui = purple_blist_node_get_ui_data(node);
 	if (ui->conv.conv != conv || !pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) ||
 			!(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)))
 		return;
@@ -4845,7 +4792,7 @@ displayed_msg_update_ui_cb(PidginConvers
 static void
 displayed_msg_update_ui_cb(PidginConversation *gtkconv, PurpleBlistNode *node)
 {
-	PidginBlistNode *ui = node->ui_data;
+	PidginBlistNode *ui = purple_blist_node_get_ui_data(node);
 	if (ui->conv.conv != gtkconv->active_conv)
 		return;
 	ui->conv.flags &= ~(PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE |
@@ -4856,13 +4803,15 @@ conversation_created_cb(PurpleConversati
 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;
+					struct _pidgin_blist_node *ui = purple_blist_node_get_ui_data(buddy);
 					buddies = g_slist_delete_link(buddies, buddies);
 					if (!ui)
 						continue;
@@ -4880,11 +4829,11 @@ conversation_created_cb(PurpleConversati
 			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;
-				ui = chat->node.ui_data;
+				ui = purple_blist_node_get_ui_data(&(chat->node));
 				if (!ui)
 					break;
 				ui->conv.conv = conv;
@@ -4912,8 +4861,6 @@ static void pidgin_blist_new_list(Purple
 	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;
@@ -4921,7 +4868,7 @@ static void pidgin_blist_new_node(Purple
 
 static void pidgin_blist_new_node(PurpleBlistNode *node)
 {
-	node->ui_data = g_new0(struct _pidgin_blist_node, 1);
+	purple_blist_node_set_ui_data(node, g_new0(struct _pidgin_blist_node, 1));
 }
 
 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node)
@@ -4934,7 +4881,7 @@ gboolean pidgin_blist_node_is_contact_ex
 
 	g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE);
 
-	return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded;
+	return ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node))->contact_expanded;
 }
 
 enum {
@@ -4984,7 +4931,7 @@ static void _prefs_change_redo_list(cons
 		struct _pidgin_blist_node *gtknode;
 		GtkTreePath *path;
 
-		gtknode = node->ui_data;
+		gtknode = purple_blist_node_get_ui_data(node);
 		if (gtknode && gtknode->row)
 		{
 			path = gtk_tree_row_reference_get_path(gtknode->row);
@@ -5068,7 +5015,7 @@ gtk_blist_window_key_press_cb(GtkWidget 
 	widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window));
 
 	if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) {
-		if (gtk_bindings_activate(G_OBJECT(widget), event->keyval, event->state))
+		if (gtk_bindings_activate(GTK_OBJECT(widget), event->keyval, event->state))
 			return TRUE;
 	}
 	return FALSE;
@@ -5077,14 +5024,14 @@ headline_box_enter_cb(GtkWidget *widget,
 static gboolean
 headline_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, PidginBuddyList *gtkblist)
 {
-	gdk_window_set_cursor(gtk_widget_get_window(widget), gtkblist->hand_cursor);
+	gdk_window_set_cursor(widget->window, gtkblist->hand_cursor);
 	return FALSE;
 }
 
 static gboolean
 headline_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, PidginBuddyList *gtkblist)
 {
-	gdk_window_set_cursor(gtk_widget_get_window(widget), gtkblist->arrow_cursor);
+	gdk_window_set_cursor(widget->window, gtkblist->arrow_cursor);
 	return FALSE;
 }
 
@@ -5218,10 +5165,9 @@ static void
 }
 
 static void
-generic_error_destroy_cb(GtkWidget *dialog,
+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.
@@ -5479,28 +5425,6 @@ update_signed_on_elsewhere_tooltip(Purpl
 }
 
 
-/**
- * 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.
- */
-static 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));
-}
-
 /* Call appropriate error notification code based on error types */
 static void
 update_account_error_state(PurpleAccount *account,
@@ -5514,12 +5438,6 @@ update_account_error_state(PurpleAccount
 	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);
 
@@ -5590,22 +5508,17 @@ paint_headline_hbox  (GtkWidget      *wi
 		      GdkEventExpose *event,
 		      gpointer user_data)
 {
-	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget));
-	GtkAllocation allocation;
-
-	gtk_widget_get_allocation(widget, &allocation);
-	gtk_paint_flat_box (gtk_widget_get_style(widget),
-		cr,
-		GTK_STATE_NORMAL,
-		GTK_SHADOW_OUT,
-		widget,
-		"tooltip",
-		allocation.x + 1,
-		allocation.y + 1,
-		allocation.width - 2,
-		allocation.height - 2);
-	cairo_destroy(cr);
-
+	gtk_paint_flat_box (widget->style,
+		      widget->window,
+		      GTK_STATE_NORMAL,
+		      GTK_SHADOW_OUT,
+		      NULL,
+		      widget,
+		      "tooltip",
+		      widget->allocation.x + 1,
+		      widget->allocation.y + 1,
+		      widget->allocation.width - 2,
+		      widget->allocation.height - 2);
 	return FALSE;
 }
 
@@ -5944,10 +5857,8 @@ static void pidgin_blist_show(PurpleBudd
 			 G_CALLBACK(blist_focus_cb), gtkblist);
 	g_signal_connect(G_OBJECT(gtkblist->window), "focus-out-event",
 			 G_CALLBACK(blist_focus_cb), gtkblist);
+	GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE;
 
-	/* TODO: how is this done in gtk+ 3.0? */
-	/*GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE;*/
-
 	gtkblist->main_vbox = gtk_vbox_new(FALSE, 0);
 	gtk_widget_show(gtkblist->main_vbox);
 	gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->main_vbox);
@@ -6015,6 +5926,7 @@ static void pidgin_blist_show(PurpleBudd
 	pretty = pidgin_make_pretty_arrows(tmp);
 	g_free(tmp);
 	label = gtk_label_new(NULL);
+	gtk_widget_set_size_request(label, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width") - 12, -1);
 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 	gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.2);
 	gtk_label_set_markup(GTK_LABEL(label), pretty);
@@ -6031,8 +5943,10 @@ static void pidgin_blist_show(PurpleBudd
 	gtk_container_set_border_width(GTK_CONTAINER(gtkblist->headline_hbox), 6);
 	gtk_container_add(GTK_CONTAINER(ebox), gtkblist->headline_hbox);
 	gtkblist->headline_image = gtk_image_new_from_pixbuf(NULL);
-	gtk_misc_set_alignment(GTK_MISC(gtkblist->headline_image), 0.5, 0.5);
+	gtk_misc_set_alignment(GTK_MISC(gtkblist->headline_image), 0.0, 0);
 	gtkblist->headline_label = gtk_label_new(NULL);
+	gtk_widget_set_size_request(gtkblist->headline_label,
+				    purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25,-1);
 	gtk_label_set_line_wrap(GTK_LABEL(gtkblist->headline_label), TRUE);
 	gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), gtkblist->headline_image, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), gtkblist->headline_label, TRUE, TRUE, 0);
@@ -6042,7 +5956,7 @@ static void pidgin_blist_show(PurpleBudd
 			 G_CALLBACK(headline_style_set),
 			 NULL);
 	g_signal_connect (gtkblist->headline_hbox,
-			  "draw",
+			  "expose_event",
 			  G_CALLBACK (paint_headline_hbox),
 			  NULL);
 	gtk_widget_set_name(gtkblist->headline_hbox, "gtk-tooltips");
@@ -6339,7 +6253,7 @@ static gboolean get_iter_from_node(Purpl
 }
 
 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter) {
-	struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkTreePath *path;
 
 	if (!gtknode) {
@@ -6368,7 +6282,7 @@ static void pidgin_blist_remove(PurpleBu
 
 static void pidgin_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node)
 {
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 
 	purple_request_close_with_handle(node);
 
@@ -6390,9 +6304,9 @@ static void pidgin_blist_remove(PurpleBu
 		if(gtknode->recent_signonoff_timer > 0)
 			purple_timeout_remove(gtknode->recent_signonoff_timer);
 
-		purple_signals_disconnect_by_handle(node->ui_data);
-		g_free(node->ui_data);
-		node->ui_data = NULL;
+		purple_signals_disconnect_by_handle(gtknode);
+		g_free(gtknode);
+		purple_blist_node_set_ui_data(node, NULL);
 	}
 }
 
@@ -6436,8 +6350,8 @@ static gboolean insert_node(PurpleBuddyL
 
 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter)
 {
-	GtkTreeIter parent_iter, cur, *curptr = NULL;
-	struct _pidgin_blist_node *gtknode = node->ui_data;
+	GtkTreeIter parent_iter = {0, NULL, NULL, NULL}, cur, *curptr = NULL;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
 	GtkTreePath *newpath;
 
 	if(!iter)
@@ -6459,7 +6373,7 @@ static gboolean insert_node(PurpleBuddyL
 		gtk_tree_row_reference_free(gtknode->row);
 	} else {
 		pidgin_blist_new_node(node);
-		gtknode = (struct _pidgin_blist_node *)node->ui_data;
+		gtknode = purple_blist_node_get_ui_data(node);
 	}
 
 	newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel),
@@ -6477,7 +6391,7 @@ static gboolean insert_node(PurpleBuddyL
 
 	if(node->parent) {
 		GtkTreePath *expand = NULL;
-		struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data;
+		struct _pidgin_blist_node *gtkparentnode = purple_blist_node_get_ui_data(node->parent);
 
 		if(PURPLE_BLIST_NODE_IS_GROUP(node->parent)) {
 			if(!purple_blist_node_get_bool(node->parent, "collapsed"))
@@ -6499,12 +6413,12 @@ static gboolean pidgin_blist_group_has_s
 {
 	PurpleBlistNode *gnode, *cnode, *bnode;
 
-	gnode = (PurpleBlistNode *)group;
+	gnode = PURPLE_BLIST_NODE(group);
 	for(cnode = gnode->child; cnode; cnode = cnode->next) {
 		if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) {
 			for(bnode = cnode->child; bnode; bnode = bnode->next) {
 				PurpleBuddy *buddy = (PurpleBuddy *)bnode;
-				if (purple_account_is_connected(buddy->account) &&
+				if (purple_account_is_connected(purple_buddy_get_account(buddy)) &&
 					purple_blist_node_get_bool(bnode, "show_offline"))
 					return TRUE;
 			}
@@ -6644,7 +6558,7 @@ static char *pidgin_get_group_title(Purp
 	text_color = selected ? NULL : theme_font_get_color_default(pair, NULL);
 	text_font = theme_font_get_face_default(pair, "");
 
-	esc = g_markup_escape_text(group->name, -1);
+	esc = g_markup_escape_text(purple_group_get_name(group), -1);
 	if (text_color) {
 		mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s%s%s</span>",
 		                       text_color, text_font,
@@ -6671,7 +6585,7 @@ static void buddy_node(PurpleBuddy *budd
 	GdkColor *color = NULL;
 	char *mark;
 	char *idle = NULL;
-	gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded;
+	gboolean expanded = ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node->parent))->contact_expanded;
 	gboolean selected = (gtkblist->selected_node == node);
 	gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
 	PidginBlistTheme *theme;
@@ -6679,12 +6593,12 @@ static void buddy_node(PurpleBuddy *budd
 	if (editing_blist)
 		return;
 
-	status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy,
+	status = pidgin_blist_get_status_icon(PURPLE_BLIST_NODE(buddy),
 						biglist ? PIDGIN_STATUS_ICON_LARGE : PIDGIN_STATUS_ICON_SMALL);
 
 	/* Speed it up if we don't want buddy icons. */
 	if(biglist)
-		avatar = pidgin_blist_get_buddy_icon((PurpleBlistNode *)buddy, TRUE, TRUE);
+		avatar = pidgin_blist_get_buddy_icon(PURPLE_BLIST_NODE(buddy), TRUE, TRUE);
 	else
 		avatar = NULL;
 
@@ -6695,7 +6609,7 @@ static void buddy_node(PurpleBuddy *budd
 		do_alphashift(avatar, 77);
 	}
 
-	emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy);
+	emblem = pidgin_blist_get_emblem(PURPLE_BLIST_NODE(buddy));
 	mark = pidgin_blist_get_name_markup(buddy, selected, TRUE);
 
 	theme = pidgin_blist_get_theme();
@@ -6736,7 +6650,7 @@ static void buddy_node(PurpleBuddy *budd
 		}
 	}
 
-	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);
@@ -6807,7 +6721,7 @@ static void pidgin_blist_update_contact(
 		if(!insert_node(list, cnode, &iter))
 			return;
 
-		gtknode = (struct _pidgin_blist_node *)cnode->ui_data;
+		gtknode = purple_blist_node_get_ui_data(cnode);
 
 		if(gtknode->contact_expanded) {
 			GdkPixbuf *status;
@@ -6884,7 +6798,7 @@ static void pidgin_blist_update_buddy(Pu
 	/* First things first, update the contact */
 	pidgin_blist_update_contact(list, node);
 
-	gtkparentnode = (struct _pidgin_blist_node *)node->parent->ui_data;
+	gtkparentnode = purple_blist_node_get_ui_data(node->parent);
 
 	if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy))
 	{
@@ -6915,7 +6829,7 @@ static void pidgin_blist_update_chat(Pur
 
 	chat = (PurpleChat*)node;
 
-	if(purple_account_is_connected(chat->account)) {
+	if(purple_account_is_connected(purple_chat_get_account(chat))) {
 		GtkTreeIter iter;
 		GdkPixbuf *status, *avatar, *emblem, *prpl_icon;
 		const gchar *color, *font;
@@ -6934,7 +6848,7 @@ static void pidgin_blist_update_chat(Pur
 		if (!insert_node(list, node, &iter))
 			return;
 
-		ui = node->ui_data;
+		ui = purple_blist_node_get_ui_data(node);
 		conv = ui->conv.conv;
 		if (conv && pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv))) {
 			hidden = (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE);
@@ -6979,7 +6893,7 @@ static void pidgin_blist_update_chat(Pur
 		g_free(mark);
 		mark = tmp;
 
-		prpl_icon = pidgin_create_prpl_icon(chat->account, PIDGIN_PRPL_ICON_SMALL);
+		prpl_icon = pidgin_create_prpl_icon(purple_chat_get_account(chat), PIDGIN_PRPL_ICON_SMALL);
 
 		if (theme != NULL)
 			bgcolor = pidgin_blist_theme_get_contact_color(theme);
@@ -7020,10 +6934,10 @@ static void pidgin_blist_update(PurpleBu
 	if(!gtkblist || !gtkblist->treeview || !node)
 		return;
 
-	if (node->ui_data == NULL)
+	if (purple_blist_node_get_ui_data(node) == NULL)
 		pidgin_blist_new_node(node);
 
-	switch(node->type) {
+	switch (purple_blist_node_get_type(node)) {
 		case PURPLE_BLIST_GROUP_NODE:
 			pidgin_blist_update_group(list, node);
 			break;
@@ -7067,7 +6981,6 @@ static void pidgin_blist_destroy(PurpleB
 	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;
@@ -7098,8 +7011,7 @@ static void pidgin_blist_set_visible(Pur
 		return;
 
 	if (show) {
-		if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) &&
-		   !gtk_widget_get_visible(gtkblist->window))
+		if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && !gtk_widget_get_visible(gtkblist->window))
 			purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-unhiding", gtkblist);
 		pidgin_blist_restore_position();
 		gtk_window_present(GTK_WINDOW(gtkblist->window));
@@ -7119,7 +7031,6 @@ groups_tree(void)
 groups_tree(void)
 {
 	static GList *list = NULL;
-	char *tmp2;
 	PurpleGroup *g;
 	PurpleBlistNode *gnode;
 
@@ -7139,8 +7050,7 @@ groups_tree(void)
 			if (PURPLE_BLIST_NODE_IS_GROUP(gnode))
 			{
 				g    = (PurpleGroup *)gnode;
-				tmp2 = g->name;
-				list  = g_list_append(list, tmp2);
+				list  = g_list_append(list, (char *) purple_group_get_name(g));
 			}
 		}
 	}
@@ -7223,11 +7133,11 @@ add_buddy_cb(GtkWidget *w, int resp, Pid
 			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)
-			gtk_blist_auto_personize((PurpleBlistNode *)g, whoalias);
+			gtk_blist_auto_personize(PURPLE_BLIST_NODE(g), whoalias);
 
 		/*
 		 * XXX
@@ -7375,10 +7285,10 @@ add_chat_cb(GtkWidget *w, PidginAddChatD
 		purple_blist_add_chat(chat, group, NULL);
 
 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin)))
-			purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", TRUE);
+			purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin", TRUE);
 
 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent)))
-			purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", TRUE);
+			purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent", TRUE);
 	}
 
 	gtk_widget_destroy(data->chat_data.rq_data.window);
@@ -7415,11 +7325,13 @@ pidgin_blist_request_add_chat(PurpleAcco
 	GList *l;
 	PurpleConnection *gc;
 	GtkBox *vbox;
+	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	if (account != NULL) {
 		gc = purple_account_get_connection(account);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat == NULL) {
+		if (prpl_info->join_chat == NULL) {
 			purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL);
 			return;
 		}
@@ -7427,8 +7339,9 @@ pidgin_blist_request_add_chat(PurpleAcco
 		/* Find an account with chat capabilities */
 		for (l = purple_connections_get_all(); l != NULL; l = l->next) {
 			gc = (PurpleConnection *)l->data;
+			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
-			if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat != NULL) {
+			if (prpl_info->join_chat != NULL) {
 				account = purple_connection_get_account(gc);
 				break;
 			}
@@ -7472,7 +7385,7 @@ pidgin_blist_request_add_chat(PurpleAcco
 	if (name != NULL)
 		gtk_widget_grab_focus(data->alias_entry);
 
-	data->group_combo = pidgin_text_combo_box_entry_new(group ? group->name : NULL, groups_tree());
+	data->group_combo = pidgin_text_combo_box_entry_new(group ? purple_group_get_name(group) : NULL, groups_tree());
 	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"),
 	                          data->chat_data.rq_data.sg, data->group_combo,
 	                          TRUE, NULL);
@@ -7578,7 +7491,7 @@ set_urgent(void)
 static void
 set_urgent(void)
 {
-	if (gtkblist->window && !gtk_widget_is_focus(gtkblist->window))
+	if (gtkblist->window && !gtk_widget_has_focus(gtkblist->window))
 		pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE);
 }
 
@@ -7629,11 +7542,11 @@ static gboolean autojoin_cb(PurpleConnec
 
 			chat = (PurpleChat *)cnode;
 
-			if(chat->account != account)
+			if(purple_chat_get_account(chat) != account)
 				continue;
 
-			if (purple_blist_node_get_bool((PurpleBlistNode*)chat, "gtk-autojoin"))
-				serv_join_chat(gc, chat->components);
+			if (purple_blist_node_get_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin"))
+				serv_join_chat(gc, purple_chat_get_components(chat));
 		}
 	}
 
@@ -7650,25 +7563,25 @@ static gboolean buddy_signonoff_timeout_
 
 static gboolean buddy_signonoff_timeout_cb(PurpleBuddy *buddy)
 {
-	struct _pidgin_blist_node *gtknode = ((PurpleBlistNode*)buddy)->ui_data;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 
 	gtknode->recent_signonoff = FALSE;
 	gtknode->recent_signonoff_timer = 0;
 
-	pidgin_blist_update(NULL, (PurpleBlistNode*)buddy);
+	pidgin_blist_update(NULL, PURPLE_BLIST_NODE(buddy));
 
 	return FALSE;
 }
 
 static void buddy_signonoff_cb(PurpleBuddy *buddy)
 {
-	struct _pidgin_blist_node *gtknode;
+	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 
-	if(!((PurpleBlistNode*)buddy)->ui_data) {
-		pidgin_blist_new_node((PurpleBlistNode*)buddy);
+	if(!gtknode) {
+		pidgin_blist_new_node(PURPLE_BLIST_NODE(buddy));
 	}
 
-	gtknode = ((PurpleBlistNode*)buddy)->ui_data;
+	gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy));
 
 	gtknode->recent_signonoff = TRUE;
 
@@ -8035,7 +7948,7 @@ static void sort_method_log_activity(Pur
 		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)) {
@@ -8070,8 +7983,8 @@ static void sort_method_log_activity(Pur
 
 		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);
+                        	buddy = (PurpleBuddy*)n2;
+				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 {
@@ -8106,7 +8019,7 @@ static void
 }
 
 static void
-plugin_act(GtkWidget *obj, PurplePluginAction *pam)
+plugin_act(GtkObject *obj, PurplePluginAction *pam)
 {
 	if (pam && pam->callback)
 		pam->callback(pam);
@@ -8247,7 +8160,7 @@ pidgin_blist_update_accounts_menu(void)
 			g_string_append(accounts_ui, "<separator/>");
 
 			gc = purple_account_get_connection(account);
-			plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
+			plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? purple_connection_get_prpl(gc) : NULL;
 			if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
 				build_plugin_actions(accounts_action_group, accounts_ui, base, plugin, gc);
 			} else {
@@ -8424,3 +8337,4 @@ pidgin_blist_update_sort_methods(void)
 
 	g_string_free(ui_string, TRUE);
 }
+
============================================================
--- pidgin/gtkblist.h	baccdc1bcbcdb04a0c7d141fa31ef47a74b7ff37
+++ pidgin/gtkblist.h	483d62f56dfdeca131e516046df865efe652aac5
@@ -86,15 +86,6 @@ struct _PidginBuddyList {
 	GtkWidget *menutray;            /**< The menu tray widget. */
 	GtkWidget *menutrayicon;        /**< The menu tray icon. */
 
-	/** Caches connection error messages; keys are #PurpleAccount and
-	 *  values are non- at 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 @@ void pidgin_blist_add_alert(GtkWidget *w
  * 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 @@ void pidgin_blist_set_theme(PidginBlistT
  * Gets Pidgin's current buddy list theme
  *
  * @returns	the current theme
- *
- * @since 2.6.0
  */
 PidginBlistTheme *pidgin_blist_get_theme(void);
 
@@ -391,8 +378,6 @@ void pidgin_blist_set_headline(const cha
  * @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);
 
@@ -404,15 +389,11 @@ gchar *pidgin_blist_get_name_markup(Purp
  *
  * @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);
 
============================================================
--- libpurple/plugins/statenotify.c	d75872c082c7a48bb21d5b231a46d4ce01f418c2
+++ libpurple/plugins/statenotify.c	706fda00f11db595cb3caac1a0f8835c4ebd9300
@@ -30,7 +30,7 @@ write_status(PurpleBuddy *buddy, const c
 
 	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 @@ write_status(PurpleBuddy *buddy, const c
 	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
============================================================
--- libpurple/protocols/msn/error.c	0aa59b69acf25ea8a8452b810cb23d2bde37252a
+++ libpurple/protocols/msn/error.c	bfb252c753f7cb79299d76c71d83891b4193c864
@@ -274,7 +274,7 @@ msn_error_handle(MsnSession *session, un
 	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);
 }
 
============================================================
--- libpurple/protocols/msn/notification.c	d568c550413334155dfcabc1b8673c1316437b12
+++ libpurple/protocols/msn/notification.c	4534badc27d66694efc1b7b709415892f6a50651
@@ -1193,7 +1193,7 @@ ipg_cmd_post(MsnCmdProc *cmdproc, MsnCom
 	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 @@ url_cmd(MsnCmdProc *cmdproc, MsnCommand 
 
 	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 @@ initial_email_msg(MsnCmdProc *cmdproc, M
 	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 @@ initial_mdata_msg(MsnCmdProc *cmdproc, M
 	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 @@ email_msg(MsnCmdProc *cmdproc, MsnMessag
 	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 @@ system_msg(MsnCmdProc *cmdproc, MsnMessa
 		}
 
 		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);
============================================================
--- libpurple/protocols/msn/servconn.c	837f49664be01471e06f5b056f485e643764a8ef
+++ libpurple/protocols/msn/servconn.c	624edc2481c2067e1485e69aed41cc73b465aac5
@@ -421,8 +421,10 @@ read_cb(gpointer data, gint source, Purp
 
 	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)
============================================================
--- libpurple/protocols/msn/session.c	ecc04c767dd6d9c5f66fcc137c59e6b6d0e0cbf3
+++ libpurple/protocols/msn/session.c	942c0db801f3605c4ee4b56cfb23853109c5dbbb
@@ -459,7 +459,7 @@ msn_session_set_login_step(MsnSession *s
 	if (session->logged_in)
 		return;
 
-	gc = session->account->gc;
+	gc = purple_account_get_connection(session->account);
 
 	session->login_step = step;
 
============================================================
--- libpurple/protocols/msn/user.c	8c7e757f6b615aee9dce7caf348ea1ce6770fafe
+++ libpurple/protocols/msn/user.c	89093932f4c0236e67e2baeb427b2788a9b1d5d9
@@ -76,7 +76,7 @@ msn_user_destroy(MsnUser *user)
 	}
 
 	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 @@ msn_user_is_yahoo(PurpleAccount *account
 
 	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 @@ queue_buddy_icon_request(MsnUser *user)
 		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 @@ msn_user_set_object(MsnUser *user, MsnOb
 {
 	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;
 
============================================================
--- pidgin/gtknotify.c	b77d088af7b52b323cae0679f15957cba50e9d8c
+++ pidgin/gtknotify.c	b7e888ce5803fb36a468b59e341f173239edefae
@@ -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
 {
@@ -534,19 +534,14 @@ pidgin_notify_message(PurpleNotifyMsgTyp
 
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER);
 	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-	/* TODO: not sure if there is a way to do this in gtk+ 3, or
-	   if we want to... */
-#if 0
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 #endif
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                    PIDGIN_HIG_BORDER);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                               PIDGIN_HIG_BOX_SPACE);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
+	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BOX_SPACE);
 
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                  hbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
 	if (img != NULL)
 		gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
@@ -696,6 +691,8 @@ pidgin_notify_emails(PurpleConnection *g
 	PurpleAccount *account;
 	PidginNotifyMailData *data = NULL, *data2;
 	gboolean new_data = FALSE;
+	GtkTreeSelection *sel;
+	GtkTreeIter iter;
 
 	/* Don't bother updating if there aren't new emails and we don't have any displayed currently */
 	if (count == 0 && mail_dialog == NULL)
@@ -782,7 +779,18 @@ pidgin_notify_emails(PurpleConnection *g
 		}
 	}
 
+	/* Select first item if nothing selected */
+	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(mail_dialog->treeview));
+	if ((gtk_tree_selection_count_selected_rows(sel) < 1)
+		&& gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mail_dialog->treemodel), &iter)) {
+		gtk_tree_selection_select_iter(sel, &iter);
+	}
+
+#if GTK_CHECK_VERSION(2,18,0)
 	if (!gtk_widget_get_visible(mail_dialog->dialog)) {
+#else
+	if (!GTK_WIDGET_VISIBLE(mail_dialog->dialog)) {
+#endif
 		GdkPixbuf *pixbuf = gtk_widget_render_icon(mail_dialog->dialog, PIDGIN_STOCK_DIALOG_MAIL,
 							   gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), NULL);
 		char *label_text = g_strdup_printf(ngettext("<b>%d new email.</b>",
@@ -798,7 +806,11 @@ pidgin_notify_emails(PurpleConnection *g
 		g_free(label_text);
 		if (pixbuf)
 			g_object_unref(pixbuf);
+#if GTK_CHECK_VERSION(2,18,0)
 	} else if (!gtk_widget_has_focus(mail_dialog->dialog))
+#else
+	} else if (!GTK_WIDGET_HAS_FOCUS(mail_dialog->dialog))
+#endif
 		pidgin_set_urgent(GTK_WINDOW(mail_dialog->dialog), TRUE);
 
 	return data;
@@ -807,7 +819,7 @@ formatted_input_cb(GtkWidget *win, GdkEv
 static gboolean
 formatted_input_cb(GtkWidget *win, GdkEventKey *event, gpointer data)
 {
-	if (event->keyval == GDK_KEY_Escape)
+	if (event->keyval == GDK_Escape)
 	{
 		purple_notify_close(PURPLE_NOTIFY_FORMATTED, win);
 
@@ -817,21 +829,6 @@ formatted_input_cb(GtkWidget *win, GdkEv
 	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)
@@ -840,7 +837,7 @@ pidgin_notify_formatted(const char *titl
 	GtkWidget *vbox;
 	GtkWidget *label;
 	GtkWidget *button;
-	GtkWidget *imhtml;
+	GtkWidget *web_view;
 	GtkWidget *frame;
 	char label_text[2048];
 	char *linked_text, *primary_esc, *secondary_esc;
@@ -854,7 +851,7 @@ pidgin_notify_formatted(const char *titl
 					 G_CALLBACK(formatted_close_cb), NULL);
 
 	/* Setup the main vbox */
-	vbox = gtk_dialog_get_content_area(GTK_DIALOG(window));
+	vbox = GTK_DIALOG(window)->vbox;
 
 	/* Setup the descriptive label */
 	primary_esc = g_markup_escape_text(primary, -1);
@@ -876,12 +873,10 @@ pidgin_notify_formatted(const char *titl
 	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);
 
@@ -896,10 +891,10 @@ pidgin_notify_formatted(const char *titl
 
 	/* 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);
@@ -984,7 +979,7 @@ pidgin_notify_searchresults(PurpleConnec
 							 G_CALLBACK(searchresults_close_cb), data);
 
 	/* Setup the main vbox */
-	vbox = gtk_dialog_get_content_area(GTK_DIALOG(window));
+	vbox = GTK_DIALOG(window)->vbox;
 
 	/* Setup the descriptive label */
 	primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL;
@@ -1041,7 +1036,7 @@ pidgin_notify_searchresults(PurpleConnec
 		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);
@@ -1055,7 +1050,7 @@ pidgin_notify_searchresults(PurpleConnec
 		switch (b->type) {
 			case PURPLE_NOTIFY_BUTTON_LABELED:
 				if(b->label) {
-					button = gtk_button_new_with_label(b->label);
+					button = gtk_dialog_add_button(GTK_DIALOG(window), b->label, GTK_RESPONSE_NONE);
 				} else {
 					purple_debug_warning("gtknotify", "Missing button label\n");
 				}
@@ -1100,7 +1095,7 @@ pidgin_notify_searchresults(PurpleConnec
 	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;
@@ -1154,10 +1149,9 @@ pidgin_notify_userinfo(PurpleConnection 
 	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;
@@ -1518,17 +1512,14 @@ pidgin_create_notification_dialog(Pidgin
 
 	/* Setup the dialog */
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BOX_SPACE);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                               PIDGIN_HIG_BOX_SPACE);
-	/* TODO: not sure if this is possible (or necessary) in gtk+ 3 */
-#if 0
+	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BOX_SPACE);
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 #endif
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                    PIDGIN_HIG_BORDER);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
 
 	/* Vertical box */
-	vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+	vbox = GTK_DIALOG(dialog)->vbox;
 
 	/* Golden ratio it up! */
 	gtk_widget_set_size_request(dialog, 550, 400);
@@ -1560,11 +1551,13 @@ pidgin_create_notification_dialog(Pidgin
 		gtk_tree_view_set_search_column(GTK_TREE_VIEW(spec_dialog->treeview), PIDGIN_MAIL_TEXT);
 		gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(spec_dialog->treeview),
 			             pidgin_tree_view_search_equal_func, NULL, NULL);
+		sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(spec_dialog->treeview));
+		gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE);
 
 		g_signal_connect(G_OBJECT(dialog), "response",
 						 G_CALLBACK(email_response_cb), spec_dialog);
-		g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(spec_dialog->treeview))),
-						 "changed", G_CALLBACK(selection_changed_cb), spec_dialog);
+		g_signal_connect(G_OBJECT(sel), "changed",
+		                 G_CALLBACK(selection_changed_cb), spec_dialog);
 		g_signal_connect(G_OBJECT(spec_dialog->treeview), "row-activated", G_CALLBACK(email_row_activated_cb), NULL);
 
 		column = gtk_tree_view_column_new();
@@ -1662,7 +1655,7 @@ pidgin_create_notification_dialog(Pidgin
 	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);
 
============================================================
--- libpurple/notify.c	08e10f6f929bf17b0348613541b5689e4d14f3b2
+++ libpurple/notify.c	83687c994a16239c96d3bb0e344e03351a457cc3
@@ -56,6 +56,16 @@ struct _PurpleNotifyUserInfo
 	GQueue entries;
 };
 
+/**
+ * Single column of a search result.
+ */
+struct _PurpleNotifySearchColumn
+{
+	char *title;           /**< Title of the column. */
+	gboolean visible;      /**< Should the column be visible to the user. Defaults to TRUE. */
+
+};
+
 void *
 purple_notify_message(void *handle, PurpleNotifyMsgType type,
 					const char *title, const char *primary,
@@ -368,6 +378,13 @@ purple_notify_searchresults_column_new(c
 	return sc;
 }
 
+const char *purple_notify_searchresult_column_get_title(const PurpleNotifySearchColumn *column)
+{
+	g_return_val_if_fail(column != NULL, NULL);
+	
+	return column->title;
+}
+
 void purple_notify_searchresult_column_set_visible(PurpleNotifySearchColumn *column, gboolean visible)
 {
 	g_return_if_fail(column != NULL);
============================================================
--- libpurple/notify.h	8594c96f730538e44c8e85ec27f74cd63f2861b6
+++ libpurple/notify.h	5c94bb2a3af6824ca4d0cda1fe44c233511bae6c
@@ -32,10 +32,13 @@ typedef struct _PurpleNotifyUserInfoEntr
 #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,17 +109,8 @@ typedef enum
 	PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER
 } PurpleNotifyUserInfoEntryType;
 
-/**
- * Single column of a search result.
- */
-typedef struct
-{
-	char *title;           /**< Title of the column. */
-	gboolean visible;      /**< Should the column be visible to the user. Defaults to TRUE. */
 
-} PurpleNotifySearchColumn;
 
-
 /**
  * Callback for a button in a search result.
  *
@@ -277,9 +271,18 @@ PurpleNotifySearchColumn *purple_notify_
 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 field   The search column object.
+ * @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);
@@ -287,7 +290,7 @@ void purple_notify_searchresult_column_s
 /**
  * Returns whether or not a search result column is visible.
  *
- * @param field The search column object.
+ * @param column The search column object.
  *
  * @return TRUE if the search result column is visible. FALSE otherwise.
  */
@@ -550,7 +553,6 @@ void purple_notify_user_info_add_section
  * 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);
 
@@ -569,7 +571,6 @@ void purple_notify_user_info_add_section
  *
  * @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);
 
============================================================
--- pidgin/gtkprefs.c	633565c4d067b89f96e3c3b402932e4c631fcdf0
+++ pidgin/gtkprefs.c	68d0db1c519f022cf5e23e10a40c68a5c607f0d6
@@ -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 @@ static GtkWidget *prefs_blist_themes_com
 /* 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 @@ static GtkListStore *prefs_blist_themes;
 /* 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;
 
@@ -118,7 +123,7 @@ pidgin_prefs_labeled_spin_button(GtkWidg
 		const char *key, int min, int max, GtkSizeGroup *sg)
 {
 	GtkWidget *spin;
-	GtkAdjustment *adjust;
+	GtkObject *adjust;
 	int val;
 
 	val = purple_prefs_get_int(key);
@@ -241,7 +246,7 @@ pidgin_prefs_dropdown_from_list(GtkWidge
 	int         int_value  = 0;
 	const char *str_value  = NULL;
 	gboolean    bool_value = FALSE;
-	GtkListStore *store;
+	GtkListStore *store = NULL;
 	GtkTreeIter iter;
 	GtkTreeIter active;
 	GtkCellRenderer *renderer;
@@ -257,6 +262,9 @@ pidgin_prefs_dropdown_from_list(GtkWidge
 	} else if (type == PURPLE_PREF_BOOLEAN) {
 		store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_BOOLEAN);
 		stored_bool = purple_prefs_get_bool(key);
+	} else {
+		g_warn_if_reached();
+		return NULL;
 	}
 
 	dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
@@ -376,6 +384,8 @@ delete_prefs(GtkWidget *asdf, void *gdsa
 
 	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;
 
@@ -527,6 +537,18 @@ prefs_themes_sort(PurpleTheme *theme)
 		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);
 	}
 }
 
@@ -582,6 +604,17 @@ prefs_themes_refresh(void)
 	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);
@@ -602,6 +635,7 @@ prefs_themes_refresh(void)
 	/* 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;
@@ -615,6 +649,10 @@ prefs_themes_init(void)
 
 	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);
@@ -864,10 +902,9 @@ theme_dnd_recv(GtkWidget *widget, GdkDra
 theme_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
 		GtkSelectionData *sd, guint info, guint t, gpointer user_data)
 {
-	gchar *name = g_strchomp((gchar *)gtk_selection_data_get_data(sd));
+	gchar *name = g_strchomp((gchar *)sd->data);
 
-	if ((gtk_selection_data_get_length(sd) >= 0)
-	 && (gtk_selection_data_get_format(sd) == 8)) {
+	if ((sd->length >= 0) && (sd->format == 8)) {
 		/* Well, it looks like the drag event was cool.
 		 * Let's do something with it */
 		gchar *temp;
@@ -894,7 +931,7 @@ theme_dnd_recv(GtkWidget *widget, GdkDra
 		} 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
@@ -905,7 +942,7 @@ theme_dnd_recv(GtkWidget *widget, GdkDra
 			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);
@@ -1057,6 +1094,72 @@ prefs_set_blist_theme_cb(GtkComboBox *co
 	}
 }
 
+/* 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)
@@ -1110,6 +1213,40 @@ static GtkWidget *
 }
 
 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;
@@ -1139,6 +1276,20 @@ theme_page(void)
 		(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,
@@ -2074,6 +2225,14 @@ proxy_page(void)
 		path = g_find_program_in_path("gnome-network-properties");
 		if (path == NULL)
 			path = g_find_program_in_path("gnome-network-preferences");
+		if (path == NULL) {
+			path = g_find_program_in_path("gnome-control-center");
+			if (path != NULL) {
+				char *tmp = g_strdup_printf("%s network", path);
+				g_free(path);
+				path = tmp;
+			}
+		}
 
 		if (path == NULL) {
 			label = gtk_label_new(NULL);
@@ -2468,7 +2627,7 @@ sound_page(void)
 sound_page(void)
 {
 	GtkWidget *ret;
-	GtkWidget *vbox, *vbox2, *sw, *button, *parent, *parent_parent, *parent_parent_parent;
+	GtkWidget *vbox, *vbox2, *sw, *button;
 	GtkSizeGroup *sg;
 	GtkTreeIter iter;
 	GtkWidget *event_view;
@@ -2565,18 +2724,15 @@ sound_page(void)
 								sound_changed2_cb, vbox);
 #endif
 	vbox = pidgin_make_frame(ret, _("Sound Events"));
-	parent = gtk_widget_get_parent(vbox);
-	parent_parent = gtk_widget_get_parent(parent);
-	parent_parent_parent = gtk_widget_get_parent(parent_parent);
 
 	/* The following is an ugly hack to make the frame expand so the
 	 * sound events list is big enough to be usable */
-	gtk_box_set_child_packing(GTK_BOX(parent), vbox, TRUE, TRUE, 0,
+	gtk_box_set_child_packing(GTK_BOX(vbox->parent), vbox, TRUE, TRUE, 0,
 			GTK_PACK_START);
-	gtk_box_set_child_packing(GTK_BOX(parent_parent),
-			parent, TRUE, TRUE, 0, GTK_PACK_START);
-	gtk_box_set_child_packing(GTK_BOX(parent_parent_parent),
-			parent_parent, TRUE, TRUE, 0, GTK_PACK_START);
+	gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent), vbox->parent, TRUE,
+			TRUE, 0, GTK_PACK_START);
+	gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent->parent),
+			vbox->parent->parent, TRUE, TRUE, 0, GTK_PACK_START);
 
 	/* SOUND SELECTION */
 	event_store = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
@@ -2907,6 +3063,10 @@ pidgin_prefs_init(void)
 	/* 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");
@@ -2929,7 +3089,6 @@ pidgin_prefs_update_old(void)
 	purple_prefs_rename("/purple/conversations/placement",
 					  PIDGIN_PREFS_ROOT "/conversations/placement");
 
-	purple_prefs_rename(PIDGIN_PREFS_ROOT "/debug/timestamps", "/purple/debug/timestamps");
 	purple_prefs_rename(PIDGIN_PREFS_ROOT "/conversations/im/raise_on_events", "/plugins/gtk/X11/notify/method_raise");
 
 	purple_prefs_rename_boolean_toggle(PIDGIN_PREFS_ROOT "/conversations/ignore_colors",
@@ -2975,6 +3134,7 @@ pidgin_prefs_update_old(void)
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ignore_fonts");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ignore_font_sizes");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/passthrough_unknown_commands");
+	purple_prefs_remove(PIDGIN_PREFS_ROOT "/debug/timestamps");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/idle");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/logging/individual_logs");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/sound/signon");
============================================================
--- libpurple/prefs.h	e1b30d339896a98a86013a11095fad0c46f76137
+++ libpurple/prefs.h	96616faf790ad983d3cdb7d8cd49cd776f51bbc7
@@ -317,8 +317,6 @@ GList *purple_prefs_get_path_list(const 
  * @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);
 
============================================================
--- libpurple/request.c	c3bffd1695fd47406da8b1723c1b7cf196738292
+++ libpurple/request.c	da818cd177aa782fd8c9c9bc5f7bcf92cee13b6e
@@ -42,7 +42,109 @@ typedef struct
 
 } 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 @@ purple_request_fields_get_account(const 
 	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 @@ purple_request_field_group_get_fields(co
 	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)
@@ -865,13 +989,6 @@ void
 }
 
 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)
 {
============================================================
--- libpurple/request.h	a23823bdef393da5bbd160e88f8b14ee5c124984
+++ libpurple/request.h	7470e8c9ba6e2ec79dbb946ad68d5b4740d827eb
@@ -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,123 +81,6 @@ typedef enum
 } 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;
-	char *tooltip;
-
-};
-#endif
-
-/**
  * Request UI operations.
  */
 typedef struct
@@ -411,6 +306,25 @@ PurpleAccount *purple_request_fields_get
 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);
+
 /*@}*/
 
 /**************************************************************************/
@@ -463,6 +377,16 @@ GList *purple_request_field_group_get_fi
 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);
+
 /*@}*/
 
 /**************************************************************************/
@@ -553,8 +477,6 @@ PurpleRequestFieldType purple_request_fi
  * @param field The field.
  *
  * @return The UI data.
- *
- * @since 2.6.0
  */
 PurpleRequestFieldGroup *purple_request_field_get_group(const PurpleRequestField *field);
 
@@ -618,8 +540,6 @@ gboolean purple_request_field_is_require
  * @param field The field.
  *
  * @return The UI data.
- *
- * @since 2.6.0
  */
 gpointer purple_request_field_get_ui_data(const PurpleRequestField *field);
 
@@ -630,8 +550,6 @@ gpointer purple_request_field_get_ui_dat
  * @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);
@@ -983,18 +901,6 @@ void *purple_request_field_list_get_data
  *
  * @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.
  */
@@ -1424,8 +1330,7 @@ void *purple_request_action_varg(void *h
 
 /**
  * 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,
@@ -1436,7 +1341,6 @@ void *purple_request_action_with_icon(vo
 /**
  * <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,
============================================================
--- pidgin/gtkrequest.c	85a99e8121c1499e09bb1be139d69d530116ff73
+++ pidgin/gtkrequest.c	2576a5d62585b406fb1e8c6cf07a052235679325
@@ -39,6 +39,21 @@
 
 #include <gdk/gdkkeysyms.h>
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_set_can_default(x,y) do {\
+	if (y) \
+		GTK_WIDGET_SET_FLAGS(x, GTK_CAN_DEFAULT); \
+	else \
+		GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_DEFAULT); \
+} while(0)
+#define gtk_widget_set_can_focus(x,y) do {\
+	if (y) \
+		GTK_WIDGET_SET_FLAGS(x, GTK_CAN_FOCUS); \
+	else \
+		GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_FOCUS); \
+} while(0)
+#endif
+
 static GtkWidget * create_account_field(PurpleRequestField *field);
 
 typedef struct
@@ -105,10 +120,8 @@ pidgin_widget_decorate_account(GtkWidget
 #endif
 
 	if (GTK_IS_DIALOG(cont)) {
-		gtk_box_pack_start(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(cont))),
-	                       image, FALSE, TRUE, 0);
-		gtk_box_reorder_child(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(cont))),
-	                          image, 0);
+		gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cont)->action_area), image, FALSE, TRUE, 0);
+		gtk_box_reorder_child(GTK_BOX(GTK_DIALOG(cont)->action_area), image, 0);
 	} else if (GTK_IS_HBOX(cont)) {
 		gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
 		gtk_box_pack_end(GTK_BOX(cont), image, FALSE, TRUE, 0);
@@ -265,7 +278,11 @@ multifield_ok_cb(GtkWidget *button, Pidg
 {
 	generic_response_start(data);
 
+#if GTK_CHECK_VERSION(2,18,0)
 	if (!gtk_widget_has_focus(button))
+#else
+	if (!GTK_WIDGET_HAS_FOCUS(button))
+#endif
 		gtk_widget_grab_focus(button);
 
 	if (data->cbs[0] != NULL)
@@ -361,22 +378,18 @@ pidgin_request_input(const char *title, 
 
 	/* Setup the dialog */
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                               PIDGIN_HIG_BORDER / 2);
+	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2);
 	if (!multiline)
 		gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-	/* TODO: not sure how to do this with GTK+ 3 */
-#if 0
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 #endif
 	gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0);
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                    PIDGIN_HIG_BORDER);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
 
 	/* Setup the main horizontal box */
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                  hbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
 	/* Dialog icon. */
 	img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION,
@@ -534,20 +547,16 @@ pidgin_request_choice(const char *title,
 
 	/* Setup the dialog */
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                               PIDGIN_HIG_BORDER / 2);
+	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2);
 	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-	/* TODO: don't know if this is possible with GTK+ 3 */
-#if 0
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 #endif
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                    PIDGIN_HIG_BORDER);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
 
 	/* Setup the main horizontal box */
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                  hbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
 	/* Dialog icon. */
 	img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION,
@@ -662,20 +671,16 @@ pidgin_request_action_with_icon(const ch
 
 	/* Setup the dialog */
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                               PIDGIN_HIG_BORDER / 2);
+	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2);
 	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-	/* TODO: this is probably not supported by GTK+ 3 */
-#if 0
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 #endif
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                    PIDGIN_HIG_BORDER);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
 
 	/* Setup the main horizontal box */
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
-	                  hbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
 	/* Dialog icon. */
 	if (icon_data) {
@@ -775,6 +780,7 @@ req_entry_field_changed_cb(GtkWidget *en
 req_entry_field_changed_cb(GtkWidget *entry, PurpleRequestField *field)
 {
 	PurpleRequestFieldGroup *group;
+	PurpleRequestFields *fields;
 	PidginRequestData *req_data;
 
 	if (purple_request_field_string_is_multiline(field))
@@ -797,10 +803,11 @@ req_entry_field_changed_cb(GtkWidget *en
 	}
 
 	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
@@ -822,7 +829,7 @@ setup_entry_field(GtkWidget *entry, Purp
 		{
 			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. */
@@ -996,12 +1003,12 @@ create_choice_field(PurpleRequestField *
 
 	if (num_labels > 5)
 	{
-		widget = gtk_combo_box_text_new();
+		widget = gtk_combo_box_new_text();
 
 		for (l = labels; l != NULL; l = l->next)
 		{
 			const char *text = l->data;
-			gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget), text);
+			gtk_combo_box_append_text(GTK_COMBO_BOX(widget), text);
 		}
 
 		gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
@@ -1246,7 +1253,7 @@ pidgin_request_fields(const char *title,
 	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);
============================================================
--- pidgin/gtkprefs.h	cac6ac04ebbc3df8f2be657e35427b6498c8692c
+++ pidgin/gtkprefs.h	06dae34edc2dfc557810f5c2ac1add220a10a363
@@ -92,8 +92,6 @@ GtkWidget *pidgin_prefs_labeled_entry(Gt
  * @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);
============================================================
--- libpurple/account.c	8720a4144d94561cc8671c623058b21f214bc3f5
+++ libpurple/account.c	ef149c07d62b280188639727a5b3afce307be4bb
@@ -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 @@ account_to_xmlnode(PurpleAccount *accoun
 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 @@ account_to_xmlnode(PurpleAccount *accoun
 		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;
@@ -996,7 +986,6 @@ purple_account_new(const char *username,
 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;
@@ -1011,8 +1000,6 @@ purple_account_new(const char *username,
 
 	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);
 
@@ -1055,7 +1042,6 @@ purple_account_destroy(PurpleAccount *ac
 void
 purple_account_destroy(PurpleAccount *account)
 {
-	PurpleAccountPrivate *priv = NULL;
 	GList *l;
 
 	g_return_if_fail(account != NULL);
@@ -1086,7 +1072,8 @@ purple_account_destroy(PurpleAccount *ac
 
 	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);
@@ -1101,13 +1088,11 @@ purple_account_destroy(PurpleAccount *ac
 		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);
@@ -1134,6 +1119,15 @@ void
 }
 
 void
+purple_account_register_completed(PurpleAccount *account, gboolean succeeded)
+{
+	g_return_if_fail(account != NULL);
+
+	if (account->registration_cb)
+		(account->registration_cb)(account, succeeded, account->registration_cb_user_data);
+}
+
+void
 purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data)
 {
 	g_return_if_fail(account != NULL);
@@ -1280,6 +1274,14 @@ purple_account_disconnect(PurpleAccount 
 	account->disconnecting = FALSE;
 }
 
+gboolean
+purple_account_is_disconnecting(const PurpleAccount *account)
+{
+	g_return_val_if_fail(account != NULL, TRUE);
+	
+	return account->disconnecting;
+}
+
 void
 purple_account_notify_added(PurpleAccount *account, const char *remote_user,
                           const char *id, const char *alias,
@@ -1606,7 +1608,7 @@ purple_account_request_change_user_info(
 	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,
@@ -2486,6 +2488,24 @@ purple_account_get_ui_bool(const PurpleA
 	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)
 {
@@ -2518,7 +2538,7 @@ void
 }
 
 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;
@@ -2535,42 +2555,15 @@ purple_account_add_buddy(PurpleAccount *
 		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)
+purple_account_add_buddies(PurpleAccount *account, GList *buddies, 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)
-{
-	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
 	PurplePlugin *prpl = NULL;
 
@@ -2589,24 +2582,13 @@ purple_account_add_buddies(PurpleAccount
 			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);
+				prpl_info->add_buddy(gc, curb->data, curg->data, message);
 				curb = curb->next;
 				curg = curg->next;
 			}
@@ -2617,55 +2599,6 @@ void
 }
 
 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);
-				curb = curb->next;
-				curg = curg->next;
-			}
-		}
-
-		g_list_free(groups);
-	}
-}
-
-void
 purple_account_remove_buddy(PurpleAccount *account, PurpleBuddy *buddy,
 		PurpleGroup *group)
 {
@@ -2795,18 +2728,16 @@ set_current_error(PurpleAccount *account
 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",
@@ -2848,8 +2779,7 @@ purple_account_get_current_error(PurpleA
 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
============================================================
--- libpurple/account.h	0408092f37ba3b8a88d9f0643914f719cef34492
+++ libpurple/account.h	1b1cfdea540c3749c52bb6252274779b78350cb6
@@ -168,7 +168,7 @@ struct _PurpleAccount
 	PurpleAccountRegistrationCb registration_cb;
 	void *registration_cb_user_data;
 
-	gpointer priv;              /**< Pointer to opaque private data. */
+	PurpleConnectionErrorInfo *current_error;	/**< Errors */
 };
 
 #ifdef __cplusplus
@@ -221,6 +221,15 @@ void purple_account_register(PurpleAccou
 void purple_account_register(PurpleAccount *account);
 
 /**
+ * Registration of the account was completed.
+ * Calls the registration call-back set with purple_account_set_register_callback().
+ *
+ * @param account The account being registered.
+ * @param succeeded Was the account registration successful?
+ */
+void purple_account_register_completed(PurpleAccount *account, gboolean succeeded);
+
+/**
  * Unregisters an account (deleting it from the server).
  *
  * @param account The account to unregister.
@@ -237,6 +246,15 @@ void purple_account_disconnect(PurpleAcc
 void purple_account_disconnect(PurpleAccount *account);
 
 /**
+ * Indicates if the account is currently being disconnected.
+ *
+ * @param account The account
+ *
+ * @return TRUE if the account is being disconnected.
+ */
+gboolean purple_account_is_disconnecting(const PurpleAccount *account);
+
+/**
  * Notifies the user that the account was added to a remote user's
  * buddy list.
  *
@@ -433,8 +451,6 @@ void purple_account_set_proxy_info(Purpl
  *
  * @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 +507,6 @@ void purple_account_set_status_list(Purp
  *                   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 +520,6 @@ void purple_account_set_public_alias(Pur
  * @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 +555,6 @@ void purple_account_clear_settings(Purpl
  *
  * @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 +621,25 @@ void purple_account_set_ui_bool(PurpleAc
 							  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 +747,6 @@ PurpleConnection *purple_account_get_con
  * @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 +795,6 @@ PurpleProxyInfo *purple_account_get_prox
  * @param account   The account.
  *
  * @return The privacy type.
- *
- * @since 2.7.0
  */
 PurplePrivacyType purple_account_get_privacy_type(const PurpleAccount *account);
 
@@ -958,40 +984,18 @@ void purple_account_destroy_log(PurpleAc
  *
  * @param account The account.
  * @param buddy The buddy to add.
- *
- * @deprecated Use purple_account_add_buddy_with_invite and \c NULL message.
- */
-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.
- */
-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.
============================================================
--- libpurple/connection.c	c82ad48edd5011deb0c9c0395997078a06adbb2d
+++ libpurple/connection.c	a59139c405b8ced03d0e396d2320c5676bdce9b4
@@ -92,12 +92,6 @@ void
 }
 
 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 @@ _purple_connection_new(PurpleAccount *ac
 		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
 }
 
 void
-purple_connection_destroy(PurpleConnection *gc)
-{
-	_purple_connection_destroy(gc);
-}
-
-void
 _purple_connection_destroy(PurpleConnection *gc)
 {
 	PurpleAccount *account;
@@ -404,6 +387,14 @@ void
 }
 
 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 @@ purple_connection_get_state(const Purple
 	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 @@ purple_connection_get_password(const Pur
 {
 	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 *
@@ -628,6 +627,13 @@ purple_connection_error_is_fatal (Purple
 	}
 }
 
+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)
 {
============================================================
--- libpurple/connection.h	bd283d6499a978f990ebc0698ae29cb2727db719
+++ libpurple/connection.h	7d28070255aadfd8e25213fdeb2a6fc63bd512a5
@@ -59,8 +59,6 @@ typedef enum
 
 /**
  * Possible errors that can cause a connection to be closed.
- *
- *  @since 2.3.0
  */
 typedef enum
 {
@@ -216,8 +214,6 @@ typedef struct
 	 * @param text  a localized message describing the disconnection
 	 *              in more detail to the user.
 	 * @see #purple_connection_error
-	 *
-	 * @since 2.3.0
 	 */
 	void (*report_disconnect)(PurpleConnection *gc,
 	                          PurpleConnectionError reason,
@@ -239,7 +235,6 @@ struct _PurpleConnection
 
 	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
@@ -272,64 +267,7 @@ extern "C" {
 /**************************************************************************/
 /*@{*/
 
-#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
  * signed on.  What does it mean to be completely signed on?  If
@@ -342,6 +280,14 @@ void purple_connection_set_state(PurpleC
 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.
@@ -362,8 +308,6 @@ void purple_connection_set_display_name(
  *
  * @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);
 
@@ -377,6 +321,15 @@ PurpleConnectionState purple_connection_
 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.
@@ -399,8 +352,6 @@ PurpleAccount *purple_connection_get_acc
  * @param gc The connection.
  *
  * @return The protocol plugin.
- *
- * @since 2.4.0
  */
 PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc);
 
@@ -428,8 +379,6 @@ const char *purple_connection_get_displa
  * @param connection The PurpleConnection.
  *
  * @return The protocol data for the connection.
- *
- * @since 2.6.0
  */
 void *purple_connection_get_protocol_data(const PurpleConnection *connection);
 
@@ -461,8 +410,6 @@ void purple_connection_notice(PurpleConn
  * @param gc          the connection which is closing.
  * @param reason      why the connection is closing.
  * @param description a non- at c NULL localized description of the error.
- *
- * @since 2.3.0
  */
 void
 purple_connection_error(PurpleConnection *gc,
@@ -473,8 +420,6 @@ purple_connection_error(PurpleConnection
  * 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().
- *
- * @since 2.3.0
  */
 void
 purple_connection_ssl_error (PurpleConnection *gc,
@@ -497,12 +442,18 @@ purple_connection_ssl_error (PurpleConne
  *
  * @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);
+
 /*@}*/
 
 /**************************************************************************/
============================================================
--- pidgin/gtkaccount.c	8b3038ae49ad6317fcf2b0c483862458fd46c433
+++ pidgin/gtkaccount.c	d7d5141343a56b92a9cf35bf94b632a6e08276cf
@@ -167,7 +167,7 @@ static const char *
 static void add_voice_options(AccountPrefsDialog *dialog);
 
 static const char *
-xmpp_default_domain_hackery(GtkWidget *protocol_combo)
+google_talk_default_domain_hackery(GtkWidget *protocol_combo, const char *value_if_gtalk)
 {
 	GtkTreeModel *model;
 	GtkTreeIter iter;
@@ -185,14 +185,9 @@ xmpp_default_domain_hackery(GtkWidget *p
 			gtk_tree_model_get(model, &iter, 1, &item_name, -1);
 			if (item_name) {
 				if (!strcmp(item_name, _("Google Talk")))
-					value = "gmail.com";
+					value = value_if_gtalk;
 				g_free(item_name);
 			}
-			if (item_name) {
-				if (!strcmp(item_name, _("Facebook")))
-					value = "chat.facebook.com";
-				g_free(item_name);
-			}
 			/* If it's not GTalk, but still Jabber then the value is not NULL, it's empty */
 			if (NULL == value)
 				value = "";
@@ -390,11 +385,9 @@ account_dnd_recv(GtkWidget *widget, GdkD
 account_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
 		 GtkSelectionData *sd, guint info, guint t, AccountPrefsDialog *dialog)
 {
-	const gchar *name = (gchar *) gtk_selection_data_get_data(sd);
-	gint length = gtk_selection_data_get_length(sd);
-	gint format = gtk_selection_data_get_format(sd);
+	gchar *name = (gchar *)sd->data;
 
-	if (length >= 0 && format == 8) {
+	if ((sd->length >= 0) && (sd->format == 8)) {
 		/* Well, it looks like the drag event was cool.
 		 * Let's do something with it */
 		if (!g_ascii_strncasecmp(name, "file://", 7)) {
@@ -600,7 +593,7 @@ add_login_options(AccountPrefsDialog *di
 
 		/* Google Talk default domain hackery! */
 		if (!strcmp(_("Domain"), purple_account_user_split_get_text(split)) && !value)
-			value = xmpp_default_domain_hackery(dialog->protocol_menu);
+			value = google_talk_default_domain_hackery(dialog->protocol_menu, "gmail.com");
 
 		if (value != NULL)
 			gtk_entry_set_text(GTK_ENTRY(entry), value);
@@ -1089,7 +1082,7 @@ proxy_type_changed_cb(GtkWidget *menu, A
 		dialog->new_proxy_type == PURPLE_PROXY_NONE ||
 		dialog->new_proxy_type == PURPLE_PROXY_USE_ENVVAR) {
 
-		gtk_widget_hide(dialog->proxy_vbox);
+		gtk_widget_hide_all(dialog->proxy_vbox);
 	}
 	else
 		gtk_widget_show_all(dialog->proxy_vbox);
@@ -1792,9 +1785,7 @@ drag_data_get_cb(GtkWidget *widget, GdkD
 				 GtkSelectionData *data, guint info, guint time,
 				 AccountsWindow *dialog)
 {
-	GdkAtom target = gtk_selection_data_get_target(data);
-
-	if (target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE)) {
+	if (data->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE)) {
 		GtkTreeRowReference *ref;
 		GtkTreePath *source_row;
 		GtkTreeIter iter;
@@ -1865,16 +1856,13 @@ drag_data_received_cb(GtkWidget *widget,
 					  guint x, guint y, GtkSelectionData *sd,
 					  guint info, guint t, AccountsWindow *dialog)
 {
-	GdkAtom target = gtk_selection_data_get_target(sd);
-	const guchar *data = gtk_selection_data_get_data(sd);
-
-	if (target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE) && data) {
+	if (sd->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE) && sd->data) {
 		gint dest_index;
 		PurpleAccount *a = NULL;
 		GtkTreePath *path = NULL;
 		GtkTreeViewDropPosition position;
 
-		memcpy(&a, data, sizeof(a));
+		memcpy(&a, sd->data, sizeof(a));
 
 		if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y,
 											  &path, &position)) {
@@ -2764,3 +2752,4 @@ pidgin_account_uninit(void)
 	purple_signals_disconnect_by_handle(pidgin_account_get_handle());
 	purple_signals_unregister_by_instance(pidgin_account_get_handle());
 }
+
============================================================
--- libpurple/accountopt.c	936c7a55e737721760d3f576695d3f5a981b53c3
+++ libpurple/accountopt.c	a3ce387f8f2eb11f75d03bc4a091891ec120a515
@@ -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)
============================================================
--- libpurple/accountopt.h	2761d8a1eb1e58b7fcf0bdf4e697c1e8380f885c
+++ libpurple/accountopt.h	6fb3f74e2639a79103025c11b27cbb0702eaf2ed
@@ -28,51 +28,16 @@
 
 #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.                     */
+/**************************************************************************/
+/** Data Structures                                                       */
+/**************************************************************************/
 
-	char *text;             /**< The text that will appear to the user. */
-	char *pref_name;        /**< The name of the associated preference. */
+/** @copydoc _PurpleAccountOption */
+typedef struct _PurpleAccountOption		PurpleAccountOption;
+/** @copydoc _PurpleAccountUserSplit */
+typedef struct _PurpleAccountUserSplit	PurpleAccountUserSplit;
 
-	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)
-	                         */
-} PurpleAccountOption;
-
-/**
- * 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" {
 #endif
============================================================
--- pidgin/gtksound.c	b8de9a25c429dd4eb3fedbe500d4d86b004409b3
+++ pidgin/gtksound.c	3a0ce941d579254a111fec47d7214a90578d23ae
@@ -96,8 +96,8 @@ chat_nick_matches_name(PurpleConversatio
 	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 @@ chat_msg_received_cb(PurpleAccount *acco
 	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);
============================================================
--- pidgin/gtksound.h	132519f653121f18564d7dea38ef78c7f21a800a
+++ pidgin/gtksound.h	73e09bda8431971dbabb94604df39a2c10f066c4
@@ -67,8 +67,6 @@ void *pidgin_sound_get_handle(void);
  * 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);
 
============================================================
--- libpurple/log.h	fdae3f0adc203739096c27e7d4bb6fc140b28591
+++ libpurple/log.h	0edac1da98c11c1936b7948a963507e6f378ea91
@@ -301,8 +301,6 @@ int purple_log_get_total_size(PurpleLogT
  * @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);
 
============================================================
--- libpurple/server.h	814e3db213e48c7b3ca82d658b3130c48a1eea2a
+++ libpurple/server.h	aa2992d9f813d62e61f234e5a81b139230d5b89f
@@ -61,32 +61,6 @@ PurpleAttentionType *purple_get_attentio
  */
 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 *);
 
============================================================
--- libpurple/status.c	6fef128edcbdfb94c015322f552eb258654a742f
+++ libpurple/status.c	e584a97b248cc677d75510612369b18e5cd95af2
@@ -257,6 +257,42 @@ purple_status_type_new(PurpleStatusPrimi
 			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,
@@ -277,10 +313,10 @@ purple_status_type_new_with_attrs(Purple
 			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;
@@ -301,61 +337,6 @@ purple_status_type_destroy(PurpleStatusT
 	g_free(status_type);
 }
 
-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)
 {
@@ -687,6 +668,68 @@ status_has_changed(PurpleStatus *status)
 	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)
 {
@@ -763,31 +806,31 @@ purple_status_set_active_with_attrs_list
 
 		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
@@ -809,7 +852,7 @@ purple_status_set_active_with_attrs_list
 		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)
@@ -818,21 +861,21 @@ purple_status_set_active_with_attrs_list
 					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;
 		}
@@ -844,68 +887,6 @@ purple_status_set_active_with_attrs_list
 	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)
 {
@@ -1118,7 +1099,7 @@ purple_presence_new_for_conv(PurpleConve
 
 	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;
 }
@@ -1167,30 +1148,6 @@ void
 }
 
 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)
 {
============================================================
--- libpurple/status.h	c862eafdce07416ff396a871b201a914d48c7a2f
+++ libpurple/status.h	76bd1e123d36bdeb5f5dc7f745a56705606cb605
@@ -271,57 +271,7 @@ void purple_status_type_destroy(PurpleSt
  */
 void purple_status_type_destroy(PurpleStatusType *status_type);
 
-#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.
  *
  * @param status_type The status type.
@@ -552,52 +502,7 @@ void purple_status_set_active_with_attrs
 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.
  *
  * @param status The status.
@@ -803,33 +708,7 @@ void purple_presence_destroy(PurplePrese
  */
 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.
  *
  * Only independent statuses can be set unactive. Normal statuses can only
============================================================
--- pidgin/gtkdocklet.h	16acb1dd32c2646895f80d34f177dca23aa5e72c
+++ pidgin/gtkdocklet.h	d7d5c58d5738247b75c933e739068ad0c5c491ed
@@ -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_ */
============================================================
--- libpurple/protocols/irc/cmds.c	6e9293a2315f5361d9534e0ce9aa833ecf3a32af
+++ libpurple/protocols/irc/cmds.c	dff36f8bfb80beb85ddc1471fc672a39044f6e91
@@ -423,7 +423,7 @@ int irc_cmd_quit(struct irc_conn *irc, c
 
 		irc->quitting = TRUE;
 
-		if (!irc->account->disconnecting)
+		if (!purple_account_is_disconnecting(irc->account))
 			purple_account_set_status(irc->account, "offline", TRUE, NULL);
 	}
 
============================================================
--- libpurple/protocols/irc/irc.h	898f5f8b0dda728c4f0465eb2edee4ee55ca519a
+++ libpurple/protocols/irc/irc.h	e95d79a54dcd38b9fd06251da503d473c6186bc6
@@ -54,6 +54,7 @@ struct irc_conn {
 	GHashTable *cmds;
 	char *server;
 	int fd;
+	guint inpa;
 	guint timer;
 	guint who_channel_timer;
 	GHashTable *buddies;
============================================================
--- libpurple/protocols/irc/msgs.c	5af44182adf1b67f71eb62c9ca0dcc769865a661
+++ libpurple/protocols/irc/msgs.c	f3be925b8b5fbbde48b88f24a08369198dab25f4
@@ -92,7 +92,7 @@ static void irc_connected(struct irc_con
 	/* 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);
 	}
 
@@ -457,12 +457,12 @@ void irc_msg_who(struct irc_conn *irc, c
 		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);
 		}
 	}
 }
============================================================
--- libpurple/protocols/irc/parse.c	96e4f4e12e436c0db7935c1d11fbd1a424982935
+++ libpurple/protocols/irc/parse.c	f51c494235b66b3884f61bd9221644ffb592f51b
@@ -171,11 +171,11 @@ static PurpleCmdRet irc_parse_purple_cmd
 	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;
@@ -260,6 +260,12 @@ static char *irc_recv_convert(struct irc
 	gboolean autodetect;
 	int i;
 
+	autodetect = purple_account_get_bool(irc->account, "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
+
+	if (autodetect && g_utf8_validate(string, -1, NULL)) {
+		return g_strdup(string);
+	}
+
 	enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);
 	encodings = g_strsplit(enclist, ",", -1);
 
@@ -268,12 +274,6 @@ static char *irc_recv_convert(struct irc
 		return purple_utf8_salvage(string);
 	}
 
-	autodetect = purple_account_get_bool(irc->account, "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
-
-	if (autodetect && g_utf8_validate(string, -1, NULL)) {
-		return g_strdup(string);
-	}
-
 	for (i = 0; encodings[i] != NULL; i++) {
 		charset = encodings[i];
 		while (*charset == ' ')
@@ -708,7 +708,14 @@ void irc_parse_msg(struct irc_conn *irc,
 		switch (fmt[i]) {
 		case 'v':
 			if (!(end = strchr(cur, ' '))) end = cur + strlen(cur);
-			args[i] = g_strndup(cur, end - cur);
+			/* This is a string of unknown encoding which we do not
+			 * want to transcode, but it may or may not be valid
+			 * UTF-8, so we'll salvage it.  If a nick/channel/target
+			 * field has inadvertently been marked verbatim, this
+			 * could cause weirdness. */
+			tmp = g_strndup(cur, end - cur);
+			args[i] = purple_utf8_salvage(tmp);
+			g_free(tmp);
 			cur += end - cur;
 			break;
 		case 't':
@@ -726,7 +733,9 @@ void irc_parse_msg(struct irc_conn *irc,
 			cur = cur + strlen(cur);
 			break;
 		case '*':
-			args[i] = g_strdup(cur);
+			/* Ditto 'v' above; we're going to salvage this in case
+			 * it leaks past the IRC prpl */
+			args[i] = purple_utf8_salvage(cur);
 			cur = cur + strlen(cur);
 			break;
 		default:
============================================================
--- pidgin/gtkprivacy.c	196607e44b622317230cd365439ec671c0e45d98
+++ pidgin/gtkprivacy.c	743e1fc257b3c00dd75889ba535ac08bb02c2dc0
@@ -211,7 +211,7 @@ select_account_cb(GtkWidget *dropdown, P
 	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,12 +230,12 @@ type_changed_cb(GtkComboBox *combo, Pidg
 {
 	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);
 	gtk_widget_hide(dialog->block_widget);
-	gtk_widget_hide(dialog->button_box);
+	gtk_widget_hide_all(dialog->button_box);
 
 	if (new_type == PURPLE_PRIVACY_ALLOW_USERS) {
 		gtk_widget_show(dialog->allow_widget);
@@ -363,15 +363,15 @@ privacy_dialog_new(void)
 	dialog->account = pidgin_account_option_menu_get_selected(dropdown);
 
 	/* Add the drop-down list with the allow/block types. */
-	dialog->type_menu = gtk_combo_box_text_new();
+	dialog->type_menu = gtk_combo_box_new_text();
 	gtk_box_pack_start(GTK_BOX(vbox), dialog->type_menu, FALSE, FALSE, 0);
 	gtk_widget_show(dialog->type_menu);
 
 	for (i = 0; i < menu_entry_count; i++) {
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(dialog->type_menu),
+		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 @@ privacy_dialog_new(void)
 
 	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;
@@ -434,7 +434,7 @@ pidgin_privacy_dialog_show(void)
 		privacy_dialog = privacy_dialog_new();
 
 	gtk_widget_show(privacy_dialog->win);
-	gdk_window_raise(gtk_widget_get_window(privacy_dialog->win));
+	gdk_window_raise(privacy_dialog->win->window);
 }
 
 void
============================================================
--- libpurple/privacy.c	d0ea5addf9ad746869966e8b5334c7e3faa54f4b
+++ libpurple/privacy.c	ceb4aafd864c871a4fd4dd14ea0d3c0d9fa006fd
@@ -264,9 +264,9 @@ purple_privacy_allow(PurpleAccount *acco
 						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_allow(PurpleAccount *acco
 				}
 			}
 			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 @@ purple_privacy_allow(PurpleAccount *acco
 	}
 
 	/* 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 @@ purple_privacy_deny(PurpleAccount *accou
 					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(PurpleAccount *accou
 				}
 			}
 			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 @@ purple_privacy_deny(PurpleAccount *accou
 			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 @@ purple_privacy_deny(PurpleAccount *accou
 	}
 
 	/* 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 @@ purple_privacy_check(PurpleAccount *acco
 {
 	GSList *list;
 
-	switch (account->perm_deny) {
+	switch (purple_account_get_privacy_type(account)) {
 		case PURPLE_PRIVACY_ALLOW_ALL:
 			return TRUE;
 
============================================================
--- libpurple/plugins/perl/common/Account.xs	ed152a6f2cb93b88a2b8683f6b573a6ac3b62c9f
+++ libpurple/plugins/perl/common/Account.xs	f36af75ca5cac6c275b9525ea1bfa47a4345d34d
@@ -199,9 +199,10 @@ void
     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 @@ PPCODE:
     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)
============================================================
--- libpurple/protocols/yahoo/util.c	f8b28029aa4f0ff84c9b09af3801de7d849d27b8
+++ libpurple/protocols/yahoo/util.c	2b68a8b18e8bdd2209612d25306e00c0a677512b
@@ -63,8 +63,9 @@ gchar* yahoo_get_cookies(PurpleConnectio
 	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(PurpleConnecti
  */
 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(PurpleConnecti
  */
 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;
 
============================================================
--- libpurple/protocols/yahoo/libymsg.h	dc09f3a4609fdaa4e3bec26b3ba5f7caa8d44e8c
+++ libpurple/protocols/yahoo/libymsg.h	d260fccb7275f1e79b682ebbef480b72638c1a34
@@ -188,6 +188,7 @@ typedef struct {
 typedef struct {
 	PurpleConnection *gc;
 	int fd;
+	guint inpa;
 	guchar *rxqueue;
 	int rxlen;
 	PurpleCircBuffer *txbuf;
@@ -371,7 +372,7 @@ void yahoo_set_idle(PurpleConnection *gc
 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);
============================================================
--- libpurple/plugins/perl/common/BuddyList.xs	47b35c6d8dfe803f3a99bd048836d36bf1a7e7f7
+++ libpurple/plugins/perl/common/BuddyList.xs	3ea46fdf4991152bc447da87804c75b4fbb648dd
@@ -82,11 +82,6 @@ purple_contact_get_priority_buddy(contac
 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 @@ void
 	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 @@ const char *
 	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
============================================================
--- libpurple/value.c	a0f522996e62f2fa8bc92ce830a0cd5326d4bb93
+++ libpurple/value.c	e1aad509cfbe35e49b0b21d03d674989c5780d20
@@ -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, ...)
 {
============================================================
--- libpurple/value.h	2e4ee485ddf46affd4170adf8e560b17024fdbba
+++ libpurple/value.h	ca533ddfea5937c410bf315a1fa288b7eeaf089a
@@ -86,41 +86,8 @@ typedef enum
 /**
  * A wrapper for a type, subtype, and specific type of value.
  */
-typedef struct
-{
-	PurpleType type;
-	unsigned short flags;
+typedef struct _PurpleValue PurpleValue;
 
-	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;
-
 #ifdef __cplusplus
 extern "C" {
 #endif
============================================================
--- libpurple/plugins/perl/common/Connection.xs	ca73a65964d2f48d228261112d06a921723a74ee
+++ libpurple/plugins/perl/common/Connection.xs	aa69a56e06a79d2b05c0679c153305ef0907e794
@@ -36,10 +36,6 @@ void
 	const char *text
 
 void
-purple_connection_destroy(gc)
-	Purple::Connection gc
-
-void
 purple_connection_set_state(gc, state)
 	Purple::Connection gc
 	Purple::ConnectionState state
============================================================
--- libpurple/plugins/perl/common/Conversation.xs	93523a4b31d84d29231091710d70039703480336
+++ libpurple/plugins/perl/common/Conversation.xs	f38bcaa0037f58ba2ef3715cd26ec8a296e115ec
@@ -146,7 +146,7 @@ Purple::Connection
 	Purple::Conversation conv
 
 Purple::Connection
-purple_conversation_get_gc(conv)
+purple_conversation_get_connection(conv)
 	Purple::Conversation conv
 
 void
@@ -338,24 +338,6 @@ void
 	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:
============================================================
--- doc/account-signals.dox	fbbda66b6dee3f472ede95693a40404d5d6bcad1
+++ doc/account-signals.dox	074cb3dd1ce0d28c25719a45fe8b0ca4d2842e5c
@@ -34,7 +34,6 @@ void (*account_created)(PurpleAccount *a
   @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 @@ void (*account_destroying)(PurpleAccount
   @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 @@ int (*account_authorization_requested)(P
   @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 @@ int (*account_authorization_requested)(P
           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 @@ void (*account_authorization_denied)(Pur
    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 @@ void (*account_authorization_granted)(Pu
    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 @@ void (*account_error_changed)(PurpleAcco
                    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 @@ void (*signed_on)(PurpleAccount *account
   @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 @@ void (*signed_off)(PurpleAccount *accoun
   @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 @@ void (*connection_error)(PurpleAccount *
    @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
============================================================
--- doc/blist-signals.dox	f6065f770272546198653176d1131ad3b2feb96d
+++ doc/blist-signals.dox	135607c97a84768314c026bc2510386ca658920f
@@ -136,7 +136,6 @@ void (*buddy_caps_changed)(PurpleBuddy *
   @param buddy	  The buddy
   @param newcaps
   @param oldcaps
-  @since 2.7.0
  @endsignaldef
 
  @signaldef ui-caps-changed
@@ -147,7 +146,6 @@ void (*ui_caps_changed)(PurpleMediaCaps 
     Emitted when updating the media capabilities of the UI.
   @param newcaps
   @param oldcaps
-  @since 2.7.0
  @endsignaldef
  
  */
============================================================
--- doc/conversation-signals.dox	a5115551dcbf617a6d099b0ea4ce1916a28be613
+++ doc/conversation-signals.dox	4b5f34703686f30f0c9398fe62f1d8e043ff2ec5
@@ -149,7 +149,6 @@ void (*blocked_im_msg)(PurpleAccount *ac
   @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 @@ void (*chat_invite_blocked)(PurpleAccoun
   @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 @@ void (*conversation_extended_menu)(Purpl
    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 @@ void (*cleared_message_history)(PurpleCo
   @signaldesc
     Emitted when the conversation history is cleared.
   @param conv   The conversation.
-  @since 2.8.0
  @endsignaldef
 
  @signaldef sent-attention
@@ -501,7 +497,6 @@ void (*got_attention)(PurpleAccount *acc
   @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 @@ void (*got_attention)(PurpleAccount *acc
   @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
============================================================
--- doc/connection-signals.dox	203161c89cc32f7a2393c75b3281202e9fa80e2a
+++ doc/connection-signals.dox	2a46e279d035eb69077efaa667447f836cb5ae3b
@@ -44,7 +44,6 @@ gboolean (*autojoin)(PurpleConnection *g
   @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
============================================================
--- libpurple/sslconn.c	31b8e25e3ce31929d3f6941674a74187fbf20dee
+++ libpurple/sslconn.c	a6ac0febfadc512a390810ee0818a62a5a1c8d97
@@ -185,15 +185,6 @@ PurpleSslConnection *
 }
 
 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,
============================================================
--- libpurple/sslconn.h	93719cf2c503556e445e9512b31e1a89ad8069de
+++ libpurple/sslconn.h	cc5210a131c86bd8dc61876fbaaaa19da735b001
@@ -203,7 +203,6 @@ PurpleSslConnection *purple_ssl_connect(
  * @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,39 +210,17 @@ PurpleSslConnection *purple_ssl_connect_
 									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.
- *
- * @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 host       The hostname of the other peer (to verify the CN)
  * @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 @@ size_t purple_ssl_write(PurpleSslConnect
  *
  * @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);
 
============================================================
--- libpurple/protocols/yahoo/yahoochat.c	6d85b7b10ce44ee13d49c1d93d536b9a4a713314
+++ libpurple/protocols/yahoo/yahoochat.c	3ced7d4b8041409ac69c51b363734a2783a62cef
@@ -53,7 +53,7 @@ static void yahoo_chat_online(PurpleConn
 /* 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 @@ static PurpleConversation *yahoo_find_co
 	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(PurpleConnec
 
 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 @@ void yahoo_process_chat_online(PurpleCon
 /* 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 @@ void yahoo_process_chat_logout(PurpleCon
 /* 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(PurpleConne
 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(PurpleConnect
 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(PurpleConn
 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(PurpleConne
 
 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(PurpleConnect
 
 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(PurpleConn
 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 @@ void yahoo_chat_goto(PurpleConnection *g
 	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,
 
 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 yahoo_c_send(PurpleConnection *gc, i
 	int ret;
 	YahooData *yd;
 
-	yd = (YahooData *) gc->proto_data;
+	yd = purple_connection_get_protocol_data(gc);
 	if (!yd)
 		return -1;
 
@@ -1114,7 +1114,7 @@ void yahoo_c_join(PurpleConnection *gc, 
 	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 @@ void yahoo_c_invite(PurpleConnection *gc
 	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 @@ static void yahoo_roomlist_cleanup(Purpl
 	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 @@ static void yahoo_roomlist_send_cb(gpoin
 		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 @@ static void yahoo_roomlist_got_connected
 {
 	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 @@ PurpleRoomlist *yahoo_roomlist_get_list(
 	struct yahoo_roomlist *yrl;
 	const char *rll, *rlurl;
 	char *url;
+	GList *proto_data;
 
 	account = purple_connection_get_account(gc);
 
@@ -1556,7 +1561,9 @@ PurpleRoomlist *yahoo_roomlist_get_list(
 		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 @@ void yahoo_roomlist_cancel(PurpleRoomlis
 {
 	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,48 +1587,54 @@ void yahoo_roomlist_expand_category(Purp
 
 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);
 
 	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);
============================================================
--- libpurple/buddyicon.c	125bc4c1e95593c9219b287fd84278a6544265f0
+++ libpurple/buddyicon.c	99032cc8b1655f707616bfbefb8e1eafe884c19e
@@ -955,25 +955,6 @@ purple_buddy_icons_node_set_custom_icon_
 	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);
-}
-
 static void
 delete_buddy_icon_settings(PurpleBlistNode *node, const char *setting_name)
 {
============================================================
--- libpurple/buddyicon.h	19598cbb463e5a2df486ad0aa60f994601dedabf
+++ libpurple/buddyicon.h	1bfd811e67d43946eeb9354158d7c9edeba41655
@@ -275,7 +275,6 @@ purple_buddy_icons_get_account_icon_time
  * @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 @@ purple_buddy_icons_node_has_custom_icon(
  * @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 @@ purple_buddy_icons_node_find_custom_icon
  *
  * @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,46 +326,12 @@ purple_buddy_icons_node_set_custom_icon(
  *
  * @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.
  *
  * @param caching TRUE of buddy icon caching should be enabled, or
============================================================
--- libpurple/imgstore.h	290044744e57b99b1859c03df36a3c2ecfd4f5e8
+++ libpurple/imgstore.h	986f77512b321b47e1f370d637ba2db7663fc195
@@ -68,7 +68,6 @@ purple_imgstore_add(gpointer data, size_
  * @param path  The path to the image.
  *
  * @return  The stored image.
- * @since 2.X.X
  */
 PurpleStoredImage *
 purple_imgstore_new_from_file(const char *path);
============================================================
--- libpurple/protocols/jabber/buddy.c	192ff18e3fa0f353cc38303aa5c97bd81041d5bc
+++ libpurple/protocols/jabber/buddy.c	0d6da7631e8e4c26e360a89e27a4685bd115bcdb
@@ -501,7 +501,7 @@ void jabber_set_info(PurpleConnection *g
 		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;
@@ -557,7 +557,7 @@ void jabber_set_buddy_icon(PurpleConnect
 	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));
 
@@ -642,7 +642,7 @@ void jabber_setup_set_info(PurplePluginA
 	/*
 	 * Get existing, XML-formatted, user info
 	 */
-	if((user_info = purple_account_get_user_info(gc->account)) != NULL)
+	if((user_info = purple_account_get_user_info(purple_connection_get_account(gc))) != NULL)
 		x_vc_data = xmlnode_from_str(user_info, -1);
 
 	/*
@@ -1360,7 +1360,7 @@ static void jabber_last_parse(JabberStre
 
 									if (jbr ==
 										jabber_buddy_find_resource(jb, NULL)) {
-										purple_prpl_got_user_idle(js->gc->account,
+										purple_prpl_got_user_idle(purple_connection_get_account(js->gc),
 											buddy_name, jbr->idle, jbr->idle);
 									}
 								}
@@ -2255,10 +2255,10 @@ void jabber_user_search(JabberStream *js
 	   make sure we aren't persisting an old value */
 	if(js->user_directories && js->user_directories->data &&
 	   !strcmp(directory, js->user_directories->data)) {
-		purple_account_set_string(js->gc->account, "user_directory", "");
+		purple_account_set_string(purple_connection_get_account(js->gc), "user_directory", "");
 	}
 	else {
-		purple_account_set_string(js->gc->account, "user_directory", directory);
+		purple_account_set_string(purple_connection_get_account(js->gc), "user_directory", directory);
 	}
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search");
@@ -2273,7 +2273,7 @@ void jabber_user_search_begin(PurplePlug
 {
 	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;
 
============================================================
--- libpurple/protocols/jabber/chat.c	338a3fae5f4b20bacd627fb04c275c60fd12ad27
+++ libpurple/protocols/jabber/chat.c	4c815064086009aa2452714e65230db5316d5181
@@ -70,7 +70,7 @@ GHashTable *jabber_chat_info_defaults(Pu
 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 @@ JabberChat *jabber_chat_find_by_conv(Pur
 	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
 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 @@ void jabber_chat_join(PurpleConnection *
 {
 	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 
 
 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(Purple
 
 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(Pur
 
 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(PurpleRoomli
 
 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);
 
============================================================
--- libpurple/protocols/jabber/message.c	56cb48ae5198a3d7b0180dd2a2facf6999ed83c5
+++ libpurple/protocols/jabber/message.c	b351da1958a81e535a2b44c65360d2d5ba843501
@@ -638,6 +638,8 @@ void jabber_message_parse(JabberStream *
 					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 @@ int jabber_message_send_im(PurpleConnect
 
 	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 @@ int jabber_message_send_chat(PurpleConne
 	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);
============================================================
--- libpurple/protocols/jabber/presence.c	0754e42d7bd0daabb0eb5b38f19860d3fac7865d
+++ libpurple/protocols/jabber/presence.c	accfe90f95a0720700d62798cd40d41326a58245
@@ -299,11 +299,6 @@ void jabber_presence_send(JabberStream *
 	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 @@ static void authorize_add_cb(gpointer da
 {
 	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 @@ static void deny_add_cb(gpointer data)
 {
 	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 @@ jabber_vcard_parse_avatar(JabberStream *
 					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);
 		}
============================================================
--- libpurple/protocols/jabber/presence.h	cc80ff55fcda9f0353daf26fdbb46c57475f5232
+++ libpurple/protocols/jabber/presence.h	d96dfd36c80d2f14eacc54327bcd9108c980b4e2
@@ -92,7 +92,6 @@ void jabber_presence_send(JabberStream *
  */
 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,
============================================================
--- libpurple/protocols/jabber/roster.c	35bdcb53d9cfc3e3f89ccfead5dc6dcfc707aeda
+++ libpurple/protocols/jabber/roster.c	deecd8f9446f67e5e094f09e2b9c5b88686518d7
@@ -96,7 +96,7 @@ static void remove_purple_buddies(Jabber
 {
 	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 @@ static void add_purple_buddy_to_groups(J
 	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 @@ static void jabber_roster_update(JabberS
 	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 @@ static void jabber_roster_update(JabberS
 		                  "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(PurpleConne
 }
 
 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 @@ void jabber_roster_add_buddy(PurpleConne
 	} 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(PurpleCo
 
 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 @@ void jabber_roster_alias_change(PurpleCo
 		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 @@ void jabber_roster_group_change(PurpleCo
 	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 @@ void jabber_roster_group_change(PurpleCo
 	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 @@ void jabber_roster_remove_buddy(PurpleCo
 		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");
============================================================
--- libpurple/protocols/jabber/roster.h	125bb57d2933e3af9378fe6bdbecbfe7107fa642
+++ libpurple/protocols/jabber/roster.h	28a71d745542596d65e7f5d2de8ae8f0db329d53
@@ -32,7 +32,7 @@ void jabber_roster_add_buddy(PurpleConne
                          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,
============================================================
--- libpurple/plugins/ssl/Makefile.am	4dc470b3e95ae11960e40bfda08d0f4567fc9c1f
+++ libpurple/plugins/ssl/Makefile.am	41a1cffb7e4d83d9b51be3828c5361fc4ba0c65d
@@ -9,31 +9,16 @@ if PLUGINS
 
 if PLUGINS
 
-# I'm sorry to report that Automake Conditionals don't support
-#   if USE_GNUTLS && USE_NSS
-# but only support testing a single variable. Hence:
-
-if USE_GNUTLS
-if USE_NSS
 plugin_LTLIBRARIES = \
-	ssl.la           \
-	ssl-gnutls.la    \
-	ssl-nss.la
-else
-plugin_LTLIBRARIES = \
-	ssl.la           \
+	ssl.la
+if USE_GNUTLS
+plugin_LTLIBRARIES += \
 	ssl-gnutls.la
 endif
-else
 if USE_NSS
-plugin_LTLIBRARIES = \
-	ssl.la           \
+plugin_LTLIBRARIES += \
 	ssl-nss.la
-else
-plugin_LTLIBRARIES = \
-	ssl.la
 endif
-endif
 
 ssl_la_SOURCES        = ssl.c
 ssl_gnutls_la_SOURCES = ssl-gnutls.c
@@ -56,3 +41,4 @@ ssl_nss_la_CFLAGS = $(AM_CPPFLAGS) $(NSS
 
 ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS)
 ssl_nss_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS)
+
============================================================
--- libpurple/plugins/ssl/ssl-gnutls.c	1da6bdaf868c12329feac7b2dd7141f296a984ea
+++ libpurple/plugins/ssl/ssl-gnutls.c	109587e7087179a687b2378e342d299a73a53e68
@@ -1142,6 +1142,37 @@ x509_times (PurpleCertificate *crt, time
 	return success;
 }
 
+static GByteArray *
+x509_get_der_data(PurpleCertificate *crt)
+{
+	gnutls_x509_crt crt_dat;
+	GByteArray *data;
+	size_t len;
+	int ret;
+
+	crt_dat = X509_GET_GNUTLS_DATA(crt);
+	g_return_val_if_fail(crt_dat, NULL);
+
+	/* Obtain the output size required */
+	len = 0;
+	ret = gnutls_x509_crt_export(crt_dat, GNUTLS_X509_FMT_DER, NULL, &len);
+	g_return_val_if_fail(ret == GNUTLS_E_SHORT_MEMORY_BUFFER, NULL);
+
+	/* Now allocate a buffer and *really* export it */
+	data = g_byte_array_sized_new(len);
+	data->len = len;
+	ret = gnutls_x509_crt_export(crt_dat, GNUTLS_X509_FMT_DER, data->data, &len);
+	if (ret != 0) {
+		purple_debug_error("gnutls/x509",
+		                   "Failed to export cert to buffer with code %d\n",
+		                   ret);
+		g_byte_array_free(data, TRUE);
+		return NULL;
+	}
+
+	return data;
+}
+
 /* X.509 certificate operations provided by this plugin */
 static PurpleCertificateScheme x509_gnutls = {
 	"x509",                          /* Scheme name */
@@ -1158,9 +1189,9 @@ static PurpleCertificateScheme x509_gnut
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
 	x509_importcerts_from_file,      /* Multiple certificates import function */
+	x509_get_der_data,               /* Binary DER data */
 
 	NULL,
-	NULL,
 	NULL
 
 };
============================================================
--- libpurple/plugins/ssl/ssl-nss.c	124c474174cbde7da43e375e4ffa1f47950ab95b
+++ libpurple/plugins/ssl/ssl-nss.c	e7a5c12e7b2e9b258b2210c47774f507764dc5e7
@@ -930,6 +930,29 @@ x509_times (PurpleCertificate *crt, time
 	return TRUE;
 }
 
+static GByteArray *
+x509_get_der_data(PurpleCertificate *crt)
+{
+	CERTCertificate *crt_dat;
+	SECItem *dercrt;
+	GByteArray *data;
+
+	crt_dat = X509_NSS_DATA(crt);
+	g_return_val_if_fail(crt_dat, NULL);
+
+	dercrt = SEC_ASN1EncodeItem(NULL, NULL, crt_dat,
+	                            SEC_ASN1_GET(SEC_SignedCertificateTemplate));
+	g_return_val_if_fail(dercrt != NULL, FALSE);
+
+	data = g_byte_array_sized_new(dercrt->len);
+	memcpy(data->data, dercrt->data, dercrt->len);
+	data->len = dercrt->len;
+
+	SECITEM_FreeItem(dercrt, PR_TRUE);
+
+	return data;
+}
+
 static PurpleCertificateScheme x509_nss = {
 	"x509",                          /* Scheme name */
 	N_("X.509 Certificates"),        /* User-visible scheme name */
@@ -945,9 +968,9 @@ static PurpleCertificateScheme x509_nss 
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
 	x509_importcerts_from_file,      /* Multiple certificate import function */
+	x509_get_der_data,               /* Binary DER data */
 
 	NULL,
-	NULL,
 	NULL
 };
 
============================================================
--- libpurple/xmlnode.c	62f65e9ad8e60c0016637ebe74f8d6e37dcae5c5
+++ libpurple/xmlnode.c	788fc4f961ccbbd827cecb0c0fca0b164de0520d
@@ -78,6 +78,19 @@ xmlnode_new_child(xmlnode *parent, const
 	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
 }
 
 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
 
 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 @@ const char *xmlnode_get_prefix(const xml
 	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 @@ xmlnode_to_str_helper(const xmlnode *nod
 	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)
============================================================
--- libpurple/xmlnode.h	716b906f1214ba3bcbe0de955e09cc068a716e72
+++ libpurple/xmlnode.h	5908475d5f2b76bc27c23a0f926e513224d1b0c0
@@ -157,42 +157,14 @@ void xmlnode_set_attrib(xmlnode *node, c
  */
 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,9 +221,39 @@ void xmlnode_set_namespace(xmlnode *node
  * @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
  *
  * @param node   The node to qualify
@@ -268,13 +270,24 @@ const char *xmlnode_get_prefix(const xml
 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 @@ void xmlnode_free(xmlnode *node);
  * 			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 @@ xmlnode *xmlnode_from_file(const char *d
 #endif
 
 #endif /* _PURPLE_XMLNODE_H_ */
+
============================================================
--- libpurple/protocols/jabber/oob.c	21febd77dcfc1b208d841290a68bf8c206b7ccf8
+++ libpurple/protocols/jabber/oob.c	4c47827f316dcc7798f97e2d4f66a04fe5e627c9
@@ -48,13 +48,13 @@ static void jabber_oob_xfer_init(PurpleX
 
 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 @@ static void jabber_oob_xfer_free(PurpleX
 		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
 
 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(Purple
 
 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 @@ static void jabber_oob_xfer_start(Purple
 		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(P
 }
 
 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 @@ void jabber_oob_parse(JabberStream *js, 
 	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);
============================================================
--- libpurple/protocols/jabber/si.c	5d124c72109c805345b052ce8684de5d2b782f0f
+++ libpurple/protocols/jabber/si.c	144be1a222c0ede26fcd49cd85a1eecd9724533b
@@ -87,9 +87,9 @@ jabber_si_xfer_find(JabberStream *js, co
 
 	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(gpointe
 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 @@ jabber_si_bytestreams_connect_cb(gpointe
 	}
 
 	/* 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 @@ jabber_si_bytestreams_connect_cb(gpointe
 		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)
 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(gpo
 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_attemp
 
 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 @@ static void jabber_si_bytestreams_attemp
 		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 @@ static void jabber_si_bytestreams_attemp
 		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 @@ static void jabber_si_bytestreams_attemp
 		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 @@ static void jabber_si_bytestreams_attemp
 		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 @@ void jabber_bytestreams_parse(JabberStre
 	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 @@ jabber_si_xfer_bytestreams_send_read_aga
 		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 @@ jabber_si_xfer_bytestreams_send_read_aga
 	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 @@ jabber_si_xfer_bytestreams_send_read_aga
 		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 @@ jabber_si_xfer_bytestreams_send_read_aga
 		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 @@ jabber_si_xfer_bytestreams_send_read_aga
 		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 @@ jabber_si_xfer_bytestreams_send_read_aga
 		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 @@ jabber_si_xfer_bytestreams_send_read_aga
 	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 @@ jabber_si_xfer_bytestreams_send_read_aga
 	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 @@ jabber_si_xfer_bytestreams_send_read_res
 		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 @@ jabber_si_xfer_bytestreams_send_read_res
 	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 @@ jabber_si_xfer_bytestreams_send_read_cb(
 		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 @@ jabber_si_xfer_bytestreams_send_read_cb(
 		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 @@ jabber_si_xfer_bytestreams_send_read_cb(
 		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 @@ jabber_si_xfer_bytestreams_send_read_cb(
 	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 @@ jabber_si_xfer_bytestreams_send_read_cb(
 			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 @@ jabber_si_xfer_bytestreams_send_read_cb(
 	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 @@ jabber_si_xfer_bytestreams_send_connecte
 		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 @@ jabber_si_xfer_bytestreams_send_connecte
 		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 @@ jabber_si_xfer_bytestreams_send_connecte
 	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 @@ jabber_si_connect_proxy_cb(JabberStream 
 		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 @@ jabber_si_connect_proxy_cb(JabberStream 
 			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 @@ jabber_si_connect_proxy_cb(JabberStream 
 	}
 
 	/* 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 @@ jabber_si_xfer_bytestreams_listen_cb(int
 	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 @@ jabber_si_xfer_bytestreams_listen_cb(int
 	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 @@ jabber_si_xfer_bytestreams_listen_cb(int
 
 		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 @@ jabber_si_xfer_bytestreams_listen_cb(int
 		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 @@ jabber_si_xfer_bytestreams_send_init(Pur
 
 	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 @@ jabber_si_xfer_bytestreams_send_init(Pur
 		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 @@ jabber_si_xfer_ibb_recv_data_cb(JabberIB
 	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 @@ jabber_si_xfer_ibb_read(guchar **out_buf
 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 @@ jabber_si_xfer_ibb_open_cb(JabberStream 
 	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 @@ jabber_si_xfer_ibb_write(const guchar *b
 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(JabberIBBSess
 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 @@ jabber_si_xfer_ibb_send_init(JabberStrea
 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 @@ static void jabber_si_xfer_send_method_c
 
 	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(
 
 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 @@ static void jabber_si_xfer_send_request(
 
 	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 @@ static void jabber_si_xfer_send_request(
 
 	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(PurpleXf
 
 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 @@ static void jabber_si_xfer_free(PurpleXf
 			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 @@ static void jabber_si_xfer_free(PurpleXf
 		/* 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(P
  */
 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_denie
 
 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 @@ static void jabber_si_xfer_request_denie
 		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(P
 
 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 @@ static void jabber_si_xfer_send_disco_cb
 		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 
 
 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(PurpleXf
 
 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 @@ static void jabber_si_xfer_init(PurpleXf
 		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 @@ static void jabber_si_xfer_init(PurpleXf
 			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 @@ static void jabber_si_xfer_init(PurpleXf
 			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 @@ static void jabber_si_xfer_init(PurpleXf
 		} 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 @@ static void jabber_si_xfer_init(PurpleXf
 
 			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 @@ static void jabber_si_xfer_init(PurpleXf
 		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 *jabber_si_new_xfer(PurpleCon
 	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 @@ void jabber_si_parse(JabberStream *js, c
 	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 @@ void jabber_si_parse(JabberStream *js, c
 		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 @@ void jabber_si_parse(JabberStream *js, c
 	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)
============================================================
--- pidgin/plugins/contact_priority.c	8a91916ddf3d0102e2ccd37b24d90d06434bb9a7
+++ pidgin/plugins/contact_priority.c	b98d3468b8a654740033da9db214f3323356b614
@@ -75,7 +75,7 @@ get_config_frame(PurplePlugin *plugin)
 	GtkWidget *ret = NULL, *hbox = NULL, *frame = NULL, *vbox = NULL;
 	GtkWidget *label = NULL, *spin = NULL, *check = NULL;
 	GtkWidget *optmenu = NULL;
-	GtkAdjustment *adj = NULL;
+	GtkObject *adj = NULL;
 	GtkSizeGroup *sg = NULL;
 	PurpleAccount *account = NULL;
 	int i;
============================================================
--- pidgin/gtklog.c	bcaf8cadf221947de49602db8131895452e03f95
+++ pidgin/gtklog.c	44a45ba9d6fd6476019345d45e77fc6969b0bdfd
@@ -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 @@ static void search_cb(GtkWidget *button,
 		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 @@ static void search_cb(GtkWidget *button,
 	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 @@ static void search_cb(GtkWidget *button,
 	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 
 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 @@ static void log_select_cb(GtkTreeSelecti
 	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);
@@ -581,11 +575,10 @@ static PidginLogViewer *display_log_view
 	gtk_dialog_add_button(GTK_DIALOG(lv->window), _("_Browse logs folder"), GTK_RESPONSE_HELP);
 #endif
 	gtk_container_set_border_width (GTK_CONTAINER(lv->window), PIDGIN_HIG_BOX_SPACE);
-	/* TODO: is it possible to set this in GTK+ 3.0? */
-#if 0
+#if !GTK_CHECK_VERSION(2,22,0)
 	gtk_dialog_set_has_separator(GTK_DIALOG(lv->window), FALSE);
 #endif
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))), 0);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(lv->window)->vbox), 0);
 	g_signal_connect(G_OBJECT(lv->window), "response",
 					 G_CALLBACK(destroy_cb), ht);
 	gtk_window_set_role(GTK_WINDOW(lv->window), "log_viewer");
@@ -594,12 +587,11 @@ static PidginLogViewer *display_log_view
 	if (icon != NULL) {
 		title_box = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 		gtk_container_set_border_width(GTK_CONTAINER(title_box), PIDGIN_HIG_BOX_SPACE);
-		gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))),
-		                   title_box, FALSE, FALSE, 0);
+		gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lv->window)->vbox), title_box, FALSE, FALSE, 0);
 
 		gtk_box_pack_start(GTK_BOX(title_box), icon, FALSE, FALSE, 0);
 	} else
-		title_box = gtk_dialog_get_content_area(GTK_DIALOG(lv->window));
+		title_box = GTK_DIALOG(lv->window)->vbox;
 
 	/* Label ************/
 	lv->label = gtk_label_new(NULL);
@@ -614,8 +606,7 @@ static PidginLogViewer *display_log_view
 	/* Pane *************/
 	pane = gtk_hpaned_new();
 	gtk_container_set_border_width(GTK_CONTAINER(pane), PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))),
-	                   pane, TRUE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lv->window)->vbox), pane, TRUE, TRUE, 0);
 
 	/* List *************/
 	lv->treestore = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
@@ -625,7 +616,7 @@ static PidginLogViewer *display_log_view
 	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);
@@ -650,8 +641,7 @@ static PidginLogViewer *display_log_view
 		gtk_label_set_markup(GTK_LABEL(size_label), text);
 		/*		gtk_paned_add1(GTK_PANED(pane), size_label); */
 		gtk_misc_set_alignment(GTK_MISC(size_label), 0, 0);
-		gtk_box_pack_end(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))),
-		                 size_label, FALSE, FALSE, 0);
+		gtk_box_pack_end(GTK_BOX(GTK_DIALOG(lv->window)->vbox), size_label, FALSE, FALSE, 0);
 		g_free(sz_txt);
 		g_free(text);
 	}
@@ -661,9 +651,9 @@ static PidginLogViewer *display_log_view
 	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);
 
============================================================
--- pidgin/gtklog.h	beebb1eb384edcdea9fb0073e342b726f7dd685b
+++ pidgin/gtklog.h	4d1aba0e2c716bb1bf9d0f489b9d85f9100f7ff2
@@ -43,7 +43,7 @@ struct _PidginLogViewer {
 	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         */
============================================================
--- pidgin/plugins/relnot.c	30675a6b92b8487e3947b1cfe7b4c63bfc54e2a8
+++ pidgin/plugins/relnot.c	f216199b90052352208721f75a6d981131829853
@@ -152,7 +152,7 @@ do_check(void)
 				url,
 				host);
 
-		purple_util_fetch_url_request_len(NULL, url, TRUE, NULL, FALSE,
+		purple_util_fetch_url_request(NULL, url, TRUE, NULL, FALSE,
 			request, TRUE, -1, version_fetch_cb, NULL);
 
 		g_free(request);
============================================================
--- libpurple/protocols/yahoo/yahoo_filexfer.c	2741fc87c0c9e738c5ff23283f88523f06bc4c05
+++ libpurple/protocols/yahoo/yahoo_filexfer.c	ea8f468385912a16ae26f05a17da5f588716e732
@@ -43,7 +43,7 @@ struct yahoo_xfer_data {
 	PurpleConnection *gc;
 	long expires;
 	gboolean started;
-	gchar *txbuf;
+	guchar *txbuf;
 	gsize txbuflen;
 	gsize txbuf_written;
 	guint tx_handler;
@@ -85,7 +85,7 @@ static void yahoo_xfer_data_free(struct 
 	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 @@ static void yahoo_receivefile_send_cb(gp
 {
 	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 @@ static void yahoo_receivefile_connected(
 
 	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 @@ static void yahoo_sendfile_send_cb(gpoin
 {
 	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 @@ static void yahoo_sendfile_connected(gpo
 
 	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 @@ static void yahoo_sendfile_connected(gpo
 	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 @@ static void yahoo_xfer_init(PurpleXfer *
 	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 @@ static void yahoo_xfer_init(PurpleXfer *
 			}
 		}
 	} 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 @@ static void yahoo_xfer_init_15(PurpleXfe
 	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 @@ static void yahoo_xfer_init_15(PurpleXfe
 							   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 @@ static void yahoo_xfer_init_15(PurpleXfe
 
 			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 @@ static void yahoo_xfer_init_15(PurpleXfe
 
 			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 @@ static void yahoo_xfer_start(PurpleXfer 
 	/* 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 @@ static gssize yahoo_xfer_read(guchar **b
 	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 guc
 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 @@ static gssize yahoo_xfer_write(const guc
 		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 @@ static void yahoo_xfer_cancel_send(Purpl
 {
 	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 @@ static void yahoo_xfer_cancel_send(Purpl
 		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 @@ static void yahoo_xfer_cancel_send(Purpl
 								   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 @@ static void yahoo_xfer_cancel_send(Purpl
 								   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 @@ static void yahoo_xfer_cancel_send(Purpl
 
 	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 @@ static void yahoo_xfer_cancel_recv(Purpl
 		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 @@ static void yahoo_xfer_cancel_recv(Purpl
 								   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 @@ static void yahoo_xfer_cancel_recv(Purpl
 								   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 @@ static void yahoo_xfer_cancel_recv(Purpl
 
 	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 @@ static void yahoo_p2p_ft_server_send_OK(
 {
 	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 @@ static void yahoo_p2p_ft_server_send_OK(
 		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 @@ static void yahoo_xfer_end(PurpleXfer *x
 	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 @@ static void yahoo_xfer_end(PurpleXfer *x
 		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 @@ static void yahoo_xfer_end(PurpleXfer *x
 			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 @@ static void yahoo_xfer_end(PurpleXfer *x
 				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 @@ static void yahoo_xfer_end(PurpleXfer *x
 	}
 	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 @@ void yahoo_process_filetransfer(PurpleCo
 	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 @@ void yahoo_process_filetransfer(PurpleCo
 			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 @@ void yahoo_process_filetransfer(PurpleCo
 	                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 @@ PurpleXfer *yahoo_new_xfer(PurpleConnect
 	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 @@ static void yahoo_xfer_dns_connected_15(
 
 	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 @@ static void yahoo_xfer_dns_connected_15(
 
 	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 *g
 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 @@ void yahoo_send_file(PurpleConnection *g
 	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 @@ static void yahoo_xfer_recv_cb_15(gpoint
 	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 @@ static void yahoo_xfer_send_cb_15(gpoint
 	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 @@ static void yahoo_xfer_send_cb_15(gpoint
 	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 @@ static void yahoo_xfer_send_cb_15(gpoint
 		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 @@ static void yahoo_xfer_connected_15(gpoi
 
 	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 @@ static void yahoo_xfer_connected_15(gpoi
 	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 @@ static void yahoo_xfer_connected_15(gpoi
 			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 @@ static void yahoo_xfer_connected_15(gpoi
 			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 @@ static void yahoo_xfer_connected_15(gpoi
 			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 @@ static void yahoo_xfer_connected_15(gpoi
 						"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 @@ static void yahoo_xfer_connected_15(gpoi
 			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 @@ static void yahoo_xfer_connected_15(gpoi
 			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 @@ static void yahoo_xfer_connected_15(gpoi
 			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 @@ static void yahoo_p2p_ft_POST_cb(gpointe
 	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 @@ static void yahoo_p2p_ft_HEAD_GET_cb(gpo
 	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 @@ static void yahoo_p2p_ft_HEAD_GET_cb(gpo
 	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 @@ static void yahoo_p2p_ft_server_send_con
 	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 @@ static void yahoo_p2p_ft_server_send_con
 	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 @@ static void yahoo_p2p_ft_server_listen_c
 	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 @@ static void yahoo_p2p_ft_server_listen_c
 		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 @@ static void yahoo_p2p_ft_server_listen_c
 			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 @@ static void yahoo_p2p_client_send_ft_inf
 	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 @@ static void yahoo_p2p_client_send_ft_inf
 
 	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 @@ void yahoo_process_filetrans_15(PurpleCo
 	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 @@ void yahoo_process_filetrans_15(PurpleCo
 		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 @@ void yahoo_process_filetrans_15(PurpleCo
 	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 @@ void yahoo_process_filetrans_15(PurpleCo
 	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 @@ void yahoo_process_filetrans_15(PurpleCo
 
 	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 @@ void yahoo_process_filetrans_info_15(Pur
 	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 @@ void yahoo_process_filetrans_info_15(Pur
 		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 @@ void yahoo_process_filetrans_info_15(Pur
 			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 @@ void yahoo_process_filetrans_info_15(Pur
 		}
 	}
 	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 @@ void yahoo_process_filetrans_acc_15(Purp
 	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 @@ void yahoo_process_filetrans_acc_15(Purp
 		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);
 
============================================================
--- COPYRIGHT	ac32c81db327a1c5a9d1e57c06ed3ca5337b374f
+++ COPYRIGHT	9365e9f27d791f96def355c73ff0ff8b050e3271
@@ -107,6 +107,7 @@ Brian Chu
 Ka-Hing Cheung
 Sadrul Habib Chowdhury
 Brian Chu
+Howard Chu
 Arturo Cisneros, Jr.
 Vincas Ciziunas
 Jonathan Clark
@@ -428,6 +429,7 @@ Noa Resare
 David Reiss
 Luoh Ren-Shan
 Noa Resare
+Tim Retout
 Daniele Ricci
 Kristian Rietveld
 Pekka Riikonen
============================================================
--- pidgin/gtkroomlist.c	7ffda00445fd2b0052908119af2203bcc1f621d7
+++ pidgin/gtkroomlist.c	39e1ed8da7e977f6bd7b622b4a0ae6f39687eab7
@@ -91,7 +91,7 @@ static gint delete_win_cb(GtkWidget *w, 
 		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 @@ static void dialog_select_account_cb(GOb
 	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 @@ static void list_button_cb(GtkButton *bu
 		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 @@ static void list_button_cb(GtkButton *bu
 	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 @@ selection_changed_cb(GtkTreeSelection *s
 		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,
 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(GtkButt
 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 *bu
 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
 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 @@ static void row_activated_cb(GtkTreeView
 	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 
 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 @@ static gboolean room_click_cb(GtkWidget 
 	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 @@ static void row_expanded_cb(GtkTreeView 
 	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,14 +355,13 @@ pidgin_roomlist_paint_tooltip(GtkWidget 
 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;
 	GtkTextDirection dir = gtk_widget_get_direction(GTK_WIDGET(grl->tree));
-	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(grl->tipwindow));
 
-	style = gtk_widget_get_style(grl->tipwindow);
+	style = grl->tipwindow->style;
 
 	max_text_width = MAX(grl->tip_width, grl->tip_name_width);
 	max_width = TOOLTIP_BORDER + SMALL_SPACE + max_text_width + TOOLTIP_BORDER;
@@ -369,34 +369,32 @@ pidgin_roomlist_paint_tooltip(GtkWidget 
 	current_height = 12;
 
 	if (dir == GTK_TEXT_DIR_RTL) {
-		gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
-				grl->tipwindow, "tooltip",
+		gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+				NULL, grl->tipwindow, "tooltip",
 				max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000),
 				current_height, grl->tip_name_layout);
 	} else {
-		gtk_paint_layout (style, cr, GTK_STATE_NORMAL, FALSE,
-				grl->tipwindow, "tooltip",
+		gtk_paint_layout (style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+				NULL, grl->tipwindow, "tooltip",
 				TOOLTIP_BORDER + SMALL_SPACE, current_height, grl->tip_name_layout);
 	}
 	if (dir != GTK_TEXT_DIR_RTL) {
-		gtk_paint_layout (style, cr, GTK_STATE_NORMAL, FALSE,
-				grl->tipwindow, "tooltip",
+		gtk_paint_layout (style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+				NULL, grl->tipwindow, "tooltip",
 				TOOLTIP_BORDER + SMALL_SPACE, current_height + grl->tip_name_height, grl->tip_layout);
 	} else {
-		gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
-				grl->tipwindow, "tooltip",
+		gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+				NULL, grl->tipwindow, "tooltip",
 				max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000),
 				current_height + grl->tip_name_height,
 				grl->tip_layout);
 	}
-	cairo_destroy(cr);
-
 	return FALSE;
 }
 
 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;
@@ -417,19 +415,23 @@ static gboolean pidgin_roomlist_create_t
 	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;
@@ -481,7 +483,7 @@ pidgin_roomlist_create_tooltip(GtkWidget
 		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;
@@ -500,7 +502,7 @@ static gboolean account_filter_func(Purp
 	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);
 }
@@ -625,7 +627,7 @@ static void pidgin_roomlist_new(PurpleRo
 {
 	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);
 
@@ -688,7 +690,7 @@ static void pidgin_roomlist_set_fields(P
 
 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;
@@ -710,7 +712,7 @@ static void pidgin_roomlist_set_fields(P
 	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;
@@ -752,18 +754,19 @@ static void pidgin_roomlist_set_fields(P
 	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,
@@ -792,7 +795,7 @@ static gboolean pidgin_progress_bar_puls
 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)
@@ -808,7 +811,7 @@ static void pidgin_roomlist_add_room(Pur
 
 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;
@@ -817,7 +820,7 @@ static void pidgin_roomlist_add_room(Pur
 	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) {
@@ -829,8 +832,8 @@ static void pidgin_roomlist_add_room(Pur
 			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;
@@ -851,24 +854,28 @@ static void pidgin_roomlist_add_room(Pur
 	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);
 	}
@@ -876,7 +883,7 @@ static void pidgin_roomlist_in_progress(
 
 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;
@@ -898,7 +905,7 @@ static void pidgin_roomlist_destroy(Purp
 
 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);
 
@@ -906,7 +913,7 @@ static void pidgin_roomlist_destroy(Purp
 
 	g_hash_table_destroy(rl->cats);
 	g_free(rl);
-	list->ui_data = NULL;
+	purple_roomlist_set_ui_data(list, NULL);
 }
 
 static PurpleRoomlistUiOps ops = {
============================================================
--- libpurple/roomlist.c	1946bbe953c69bdf2acfa1ebd0690d908287cbcc
+++ libpurple/roomlist.c	2f2565304f822914d9ba0d9dd912f9c715b69e92
@@ -32,7 +32,40 @@
 #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 @@ void purple_roomlist_unref(PurpleRoomlis
 		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 @@ GList * purple_roomlist_get_fields(Purpl
 	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,8 +397,22 @@ PurpleRoomlistRoom * purple_roomlist_roo
 	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;
 }
 
============================================================
--- libpurple/roomlist.h	4a338ddccc4e0a04fa0eb0590475e10b4abff12c
+++ libpurple/roomlist.h	a9488ea8f08ee5985cab0edb2deb6998c16cea13
@@ -64,40 +64,6 @@ typedef enum
 /**************************************************************************/
 
 /**
- * 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(PurpleRoomlis
 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,12 +215,49 @@ void purple_roomlist_expand_category(Pur
 /**
  * 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);
+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.
+ */
+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 @@ void purple_roomlist_room_join(PurpleRoo
  * 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 @@ PurpleRoomlistRoomType purple_roomlist_r
  * 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 @@ const char * purple_roomlist_room_get_na
  * 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 @@ PurpleRoomlistField *purple_roomlist_fie
  * @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 @@ PurpleRoomlistFieldType purple_roomlist_
  * @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 @@ const char * purple_roomlist_field_get_l
  * @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);
 
============================================================
--- libpurple/protocols/msn/nexus.c	3fdfb40d70dba287aa7341a5f69c9ffb57b2ff92
+++ libpurple/protocols/msn/nexus.c	9e67013ee05a64ffc50542de9e6b04830586c7f7
@@ -390,7 +390,7 @@ msn_nexus_connect(MsnNexus *nexus)
 	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];
============================================================
--- libpurple/network.c	157a020a2d0f90e144a1de465be40848bb51df7c
+++ libpurple/network.c	b278d275420201ae15ddcef7a617dbe73ac1fd74
@@ -391,14 +391,9 @@ purple_network_finish_pmp_map_cb(gpointe
 	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 @@ purple_network_do_listen(unsigned short 
 	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 *
 }
 
 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 @@ purple_network_listen_range_family(unsig
 	}
 
 	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 @@ purple_network_listen_range_family(unsig
 	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)
@@ -833,8 +811,20 @@ purple_network_is_available(void)
 			purple_debug_warning("network", "NetworkManager not active. Assuming connection exists.\n");
 	}
 
-	if (nm_state == NM_STATE_UNKNOWN || nm_state == NM_STATE_CONNECTED)
-		return TRUE;
+	switch (nm_state)
+	{
+		case NM_STATE_UNKNOWN:
+#if NM_CHECK_VERSION(0,8,992)
+		case NM_STATE_CONNECTED_LOCAL:
+		case NM_STATE_CONNECTED_SITE:
+		case NM_STATE_CONNECTED_GLOBAL:
+#else
+		case NM_STATE_CONNECTED:
+#endif
+			return TRUE;
+		default:
+			break;
+	}
 
 	return FALSE;
 
@@ -991,7 +981,7 @@ purple_network_set_stun_server(const gch
 	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 +999,7 @@ purple_network_set_turn_server(const gch
 	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 {
@@ -1171,9 +1161,14 @@ purple_network_init(void)
 		                                     NM_DBUS_SERVICE,
 		                                     NM_DBUS_PATH,
 		                                     NM_DBUS_INTERFACE);
+		/* NM 0.6 signal */
 		dbus_g_proxy_add_signal(nm_proxy, "StateChange", G_TYPE_UINT, G_TYPE_INVALID);
 		dbus_g_proxy_connect_signal(nm_proxy, "StateChange",
 		                            G_CALLBACK(nm_state_change_cb), NULL, NULL);
+		/* NM 0.7 and later signal */
+		dbus_g_proxy_add_signal(nm_proxy, "StateChanged", G_TYPE_UINT, G_TYPE_INVALID);
+		dbus_g_proxy_connect_signal(nm_proxy, "StateChanged",
+		                            G_CALLBACK(nm_state_change_cb), NULL, NULL);
 
 		dbus_proxy = dbus_g_proxy_new_for_name(nm_conn,
 		                                       DBUS_SERVICE_DBUS,
@@ -1208,6 +1203,7 @@ purple_network_uninit(void)
 #ifdef HAVE_NETWORKMANAGER
 	if (nm_proxy) {
 		dbus_g_proxy_disconnect_signal(nm_proxy, "StateChange", G_CALLBACK(nm_state_change_cb), NULL);
+		dbus_g_proxy_disconnect_signal(nm_proxy, "StateChanged", G_CALLBACK(nm_state_change_cb), NULL);
 		g_object_unref(G_OBJECT(nm_proxy));
 	}
 	if (dbus_proxy) {
============================================================
--- libpurple/network.h	632920aae6e16738708a7e3bae2b9077a5410e79
+++ libpurple/network.h	4d5b843e10702d86e4effc4c4d52a9226927396f
@@ -92,7 +92,6 @@ const char *purple_network_get_local_sys
  *
  * @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
 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 @@ void purple_network_listen_map_external(
  * 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,30 +155,10 @@ PurpleNetworkListenData *purple_network_
  *         socket to listen on.
  */
 PurpleNetworkListenData *purple_network_listen(unsigned short port,
-		int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data);
+	int socket_family, int socket_type, gboolean map_external,
+	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);
-
-/**
  * Opens a listening port selected from a range of ports.  The range of
  * ports used is chosen in the following manner:
  * If a range is specified in preferences, these values are used.
@@ -192,13 +172,26 @@ PurpleNetworkListenData *purple_network_
  * 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 @@ PurpleNetworkListenData *purple_network_
  *         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 @@ gboolean purple_network_is_available(voi
  * 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 @@ void *purple_network_get_handle(void);
  * 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 @@ void purple_network_set_stun_server(cons
  * 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 @@ const gchar *purple_network_get_stun_ip(
  * 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 @@ void purple_network_set_turn_server(cons
  * 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 @@ const gchar *purple_network_get_turn_ip(
  * 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 @@ void purple_network_remove_port_mapping(
  *                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);
 
============================================================
--- libpurple/eventloop.h	89501d488af90d218670a6e62fd7bd772eac717e
+++ libpurple/eventloop.h	b02d72c5ce4fa2064c69891ee6faa57803890256
@@ -145,7 +145,6 @@ struct _PurpleEventLoopUiOps
 	 * #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 @@ guint purple_timeout_add(guint interval,
  * @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);
 
============================================================
--- libpurple/protocols/jabber/disco.c	2b5e3edcf38d4fe902d67b4c4325c49bc621fe23
+++ libpurple/protocols/jabber/disco.c	a94d897aebf3173cabbaf2cf23b55d4066e45e95
@@ -387,7 +387,7 @@ jabber_disco_finish_server_info_result_c
 	}
 
 	/* 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 @@ jabber_disco_stun_srv_resolve_cb(PurpleS
 			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 @@ jabber_disco_server_info_result_cb(Jabbe
 		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 @@ jabber_disco_server_info_result_cb(Jabbe
 		} 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);
============================================================
--- pidgin/gtkimhtmltoolbar.c	b65ae86e247720af3d414a55b8e061a612efede8
+++ pidgin/gtkimhtmltoolbar.c	0d3b61dc27b5c708f67a26776e6549d3c2b378fb
@@ -43,6 +43,11 @@
 
 #include <gdk/gdkkeysyms.h>
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
+#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x)
+#endif
+
 static GtkHBoxClass *parent_class = NULL;
 
 static void toggle_button_set_active_block(GtkToggleButton *button,
@@ -124,15 +129,11 @@ realize_toolbar_font(GtkWidget *widget, 
 {
 	GtkFontSelection *sel;
 
-	sel = GTK_FONT_SELECTION(
-		gtk_font_selection_dialog_get_font_selection(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)));
-	gtk_widget_hide(gtk_widget_get_parent(
-		gtk_font_selection_get_size_entry(sel)));
-	gtk_widget_show_all(gtk_font_selection_get_family_list(sel));
-	gtk_widget_show(gtk_widget_get_parent(
-		gtk_font_selection_get_family_list(sel)));
-	gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent(
-		gtk_font_selection_get_family_list(sel))));
+	sel = GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)->fontsel);
+	gtk_widget_hide_all(gtk_widget_get_parent(sel->size_entry));
+	gtk_widget_show_all(sel->family_list);
+	gtk_widget_show(gtk_widget_get_parent(sel->family_list));
+	gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent(sel->family_list)));
 }
 
 static void
@@ -195,12 +196,10 @@ toggle_font(GtkWidget *font, GtkIMHtmlTo
 
 			g_signal_connect(G_OBJECT(toolbar->font_dialog), "delete_event",
 							 G_CALLBACK(destroy_toolbar_font), toolbar);
-			g_signal_connect(G_OBJECT(
-				gtk_font_selection_dialog_get_ok_button(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog))),
-				"clicked", G_CALLBACK(apply_font), toolbar->font_dialog);
-			g_signal_connect(G_OBJECT(
-				gtk_font_selection_dialog_get_cancel_button(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog))),
-				"clicked", G_CALLBACK(cancel_toolbar_font), toolbar);
+			g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)->ok_button), "clicked",
+							 G_CALLBACK(apply_font), toolbar->font_dialog);
+			g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)->cancel_button), "clicked",
+							 G_CALLBACK(cancel_toolbar_font), toolbar);
 			g_signal_connect_after(G_OBJECT(toolbar->font_dialog), "realize",
 							 G_CALLBACK(realize_toolbar_font), toolbar);
 		}
@@ -259,12 +258,9 @@ toggle_fg_color(GtkWidget *color, GtkIMH
 		char *color = gtk_imhtml_get_current_forecolor(GTK_IMHTML(toolbar->imhtml));
 
 		if (!toolbar->fgcolor_dialog) {
-			GtkWidget *ok_button;
-			GtkWidget *cancel_button;
 
 			toolbar->fgcolor_dialog = gtk_color_selection_dialog_new(_("Select Text Color"));
-			colorsel =
-				gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog));
+			colorsel = GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)->colorsel;
 			if (color) {
 				gdk_color_parse(color, &fgcolor);
 				gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &fgcolor);
@@ -273,13 +269,12 @@ toggle_fg_color(GtkWidget *color, GtkIMH
 
 			g_object_set_data(G_OBJECT(colorsel), "purple_toolbar", toolbar);
 
-			g_object_get(G_OBJECT(toolbar->fgcolor_dialog), "ok-button", &ok_button, NULL);
-			g_object_get(G_OBJECT(toolbar->fgcolor_dialog), "cancel-button", &cancel_button, NULL);
 			g_signal_connect(G_OBJECT(toolbar->fgcolor_dialog), "delete_event",
 							 G_CALLBACK(destroy_toolbar_fgcolor), toolbar);
-			g_signal_connect(G_OBJECT(ok_button), "clicked", G_CALLBACK(do_fgcolor), colorsel);
-			g_signal_connect(G_OBJECT(cancel_button), "clicked",
-			                 G_CALLBACK(cancel_toolbar_fgcolor), toolbar);
+			g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)->ok_button), "clicked",
+							 G_CALLBACK(do_fgcolor), colorsel);
+			g_signal_connect(G_OBJECT (GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)->cancel_button), "clicked",
+							 G_CALLBACK(cancel_toolbar_fgcolor), toolbar);
 		}
 		gtk_window_present(GTK_WINDOW(toolbar->fgcolor_dialog));
 	} else {
@@ -343,13 +338,9 @@ toggle_bg_color(GtkWidget *color, GtkIMH
 		char *color = gtk_imhtml_get_current_backcolor(GTK_IMHTML(toolbar->imhtml));
 
 		if (!toolbar->bgcolor_dialog) {
-			GtkWidget *ok_button;
-			GtkWidget *cancel_button;
 
 			toolbar->bgcolor_dialog = gtk_color_selection_dialog_new(_("Select Background Color"));
-			colorsel =
-				gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog));
-
+			colorsel = GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)->colorsel;
 			if (color) {
 				gdk_color_parse(color, &bgcolor);
 				gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &bgcolor);
@@ -358,14 +349,11 @@ toggle_bg_color(GtkWidget *color, GtkIMH
 
 			g_object_set_data(G_OBJECT(colorsel), "purple_toolbar", toolbar);
 
-			g_object_get(G_OBJECT(toolbar->bgcolor_dialog), "ok-button", &ok_button, NULL);
-			g_object_get(G_OBJECT(toolbar->bgcolor_dialog), "cancel-button",
-			             &cancel_button, NULL);
 			g_signal_connect(G_OBJECT(toolbar->bgcolor_dialog), "delete_event",
 							 G_CALLBACK(destroy_toolbar_bgcolor), toolbar);
-			g_signal_connect(G_OBJECT(ok_button), "clicked",
-			                 G_CALLBACK(do_bgcolor), colorsel);
-			g_signal_connect(G_OBJECT(cancel_button), "clicked",
+			g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)->ok_button), "clicked",
+							 G_CALLBACK(do_bgcolor), colorsel);
+			g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)->cancel_button), "clicked",
 							 G_CALLBACK(cancel_toolbar_bgcolor), toolbar);
 
 		}
@@ -478,12 +466,12 @@ static void insert_hr_cb(GtkWidget *widg
 
 static void insert_hr_cb(GtkWidget *widget, GtkIMHtmlToolbar *toolbar)
 {
-	GtkTextIter iter;
-	GtkTextMark *ins;
+        GtkTextIter iter;
+        GtkTextMark *ins;
 	GtkIMHtmlScalable *hr;
 
-	ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)));
-	gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins);
+        ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)));
+        gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins);
 	hr = gtk_imhtml_hr_new();
 	gtk_imhtml_hr_add_to(hr, GTK_IMHTML(toolbar->imhtml), &iter);
 }
@@ -739,7 +727,7 @@ smiley_dialog_input_cb(GtkWidget *dialog
 static gboolean
 smiley_dialog_input_cb(GtkWidget *dialog, GdkEvent *event, GtkIMHtmlToolbar *toolbar)
 {
-	if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Escape) ||
+	if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape) ||
 	    (event->type == GDK_BUTTON_PRESS && event->button.button == 1))
 	{
 		close_smiley_dialog(toolbar);
@@ -929,7 +917,7 @@ static void send_attention_cb(GtkWidget 
 	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);
@@ -1109,21 +1097,19 @@ menu_position_func (GtkMenu           *m
 {
 	GtkWidget *widget = GTK_WIDGET(data);
 	GtkRequisition menu_req;
-	GtkAllocation allocation;
-	gint ythickness = gtk_widget_get_style(widget)->ythickness;
+	gint ythickness = widget->style->ythickness;
 	int savy;
 
-	gtk_widget_get_allocation(widget, &allocation);    
 	gtk_widget_size_request(GTK_WIDGET (menu), &menu_req);
-	gdk_window_get_origin(gtk_widget_get_window(widget), x, y);
-	*x += allocation.x;
-	*y += allocation.y + allocation.height;
+	gdk_window_get_origin(widget->window, x, y);
+	*x += widget->allocation.x;
+	*y += widget->allocation.y + widget->allocation.height;
 	savy = *y;
 
 	pidgin_menu_position_func_helper(menu, x, y, push_in, data);
 
 	if (savy > *y + ythickness + 1)
-		*y -= allocation.height;
+		*y -= widget->allocation.height;
 }
 
 static gboolean
@@ -1268,6 +1254,7 @@ static void gtk_imhtmltoolbar_create_old
 		{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;
@@ -1290,18 +1277,6 @@ static void gtk_imhtmltoolbar_create_old
 			button = gtk_vseparator_new();
 		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
 	}
-	/* create the attention button (this is a bit hacky to not break ABI) */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION);
-	g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(gtk_imhtmltoolbar_popup_menu), toolbar);
-	g_signal_connect(G_OBJECT(button), "clicked",
-		G_CALLBACK(send_attention_cb), toolbar);
-	g_object_set_data(G_OBJECT(toolbar), "attention", button);
-#if GTK_CHECK_VERSION(2,12,0)
-	gtk_widget_set_tooltip_text(button, _("Send Attention"));
-#else
-	gtk_tooltips_set_tip(toolbar->tooltips, button, _("Send Attention"), NULL);
-#endif
-	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
 
 	gtk_box_pack_start(GTK_BOX(toolbar), hbox, FALSE, FALSE, 0);
 	g_object_set_data(G_OBJECT(toolbar), "wide-view", hbox);
@@ -1319,7 +1294,7 @@ button_sensitiveness_changed(GtkWidget *
 static void
 button_sensitiveness_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item)
 {
-	gtk_widget_set_sensitive(item, gtk_widget_get_sensitive(button));
+	gtk_widget_set_sensitive(item, gtk_widget_is_sensitive(button));
 }
 
 static void
@@ -1342,10 +1317,10 @@ imhtmltoolbar_view_pref_changed(const ch
 		gconstpointer value, gpointer toolbar)
 {
 	if (value) {
-		gtk_widget_hide(g_object_get_data(G_OBJECT(toolbar), "lean-view"));
+		gtk_widget_hide_all(g_object_get_data(G_OBJECT(toolbar), "lean-view"));
 		gtk_widget_show_all(g_object_get_data(G_OBJECT(toolbar), "wide-view"));
 	} else {
-		gtk_widget_hide(g_object_get_data(G_OBJECT(toolbar), "wide-view"));
+		gtk_widget_hide_all(g_object_get_data(G_OBJECT(toolbar), "wide-view"));
 		gtk_widget_show_all(g_object_get_data(G_OBJECT(toolbar), "lean-view"));
 	}
 }
@@ -1364,7 +1339,6 @@ static void gtk_imhtmltoolbar_init (GtkI
 	GtkWidget *insert_menu;
 	GtkWidget *menuitem;
 	GtkWidget *sep;
-	GObject *wide_attention_button;
 	int i;
 	struct {
 		const char *label;
@@ -1517,8 +1491,6 @@ static void gtk_imhtmltoolbar_init (GtkI
 	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);
@@ -1530,16 +1502,16 @@ static void gtk_imhtmltoolbar_init (GtkI
 	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);
@@ -1620,16 +1592,14 @@ void gtk_imhtmltoolbar_switch_active_con
 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);
 }
============================================================
--- pidgin/gtkimhtmltoolbar.h	bd8e251e6f0959f95343cf162ffe6425163b2d3d
+++ pidgin/gtkimhtmltoolbar.h	002a7da0242a81f1c83b11441e84de3eabd08f1f
@@ -69,6 +69,7 @@ struct _GtkIMHtmlToolbar {
 	GtkWidget *image;
 	GtkWidget *link;
 	GtkWidget *smiley;
+	GtkWidget *attention;
 
 	GtkWidget *font_dialog;
 	GtkWidget *fgcolor_dialog;
@@ -94,9 +95,6 @@ void gtk_imhtmltoolbar_associate_smileys
 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);
 
============================================================
--- libpurple/protocols/irc/dcc_send.c	bd2b2fbcd89eba1bb4c59a83e3a9c9dde80fc47d
+++ libpurple/protocols/irc/dcc_send.c	69632df896d2f68e56e0712b1fef6293b20348fa
@@ -34,11 +34,12 @@ struct irc_xfer_rx_data {
 
 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(PurpleX
  */
 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(Purple
 }
 
 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 @@ void irc_dccsend_recv(struct irc_conn *i
 	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(Pur
 
 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(gpoint
 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(con
 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(g
 
 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 @@ static void irc_dccsend_send_connected(g
 		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 @@ irc_dccsend_network_listen_cb(int sock, 
 	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 @@ irc_dccsend_network_listen_cb(int sock, 
 		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 @@ irc_dccsend_network_listen_cb(int sock, 
 	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(Purple
  */
 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 @@ PurpleXfer *irc_dccsend_new_xfer(PurpleC
 	{
 		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);
============================================================
--- libpurple/protocols/novell/novell.c	1eadb18d6040bed8931e12b1638227f57c60cf9e
+++ libpurple/protocols/novell/novell.c	792e92e183e2bd5e5c4634a8149f2c9db3c7f0f7
@@ -131,8 +131,8 @@ _login_resp_cb(NMUser * user, NMERR_T re
 				/* Don't attempt to auto-reconnect if our
 				 * password was invalid.
 				 */
-				if (!purple_account_get_remember_password(gc->account))
-					purple_account_set_password(gc->account, NULL);
+				if (!purple_account_get_remember_password(purple_connection_get_account(gc)))
+					purple_account_set_password(purple_connection_get_account(gc), NULL);
 				reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 				break;
 			default:
@@ -741,16 +741,16 @@ _get_details_resp_add_privacy_item(NMUse
 
 		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 @@ _create_privacy_item_deny_resp_cb(NMUser
 
 		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 @@ _create_privacy_item_permit_resp_cb(NMUs
 
 		if (display_id) {
 
-			if (!g_slist_find_custom(gc->account->permit,
+			if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 									 display_id,
 									 (GCompareFunc)purple_utf8_strcasecmp)) {
 
-				purple_privacy_permit_add(gc->account, display_id, TRUE);
+				purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE);
 			}
 
 		} else {
@@ -1177,7 +1177,6 @@ _update_buddy_status(NMUser *user, Purpl
 	const char *dn;
 	const char *name;
 	int idle = 0;
-	gboolean loggedin = TRUE;
 
 	account = purple_buddy_get_account(buddy);
 	name = purple_buddy_get_name(buddy);
@@ -1194,7 +1193,6 @@ _update_buddy_status(NMUser *user, Purpl
 			break;
 		case NM_STATUS_OFFLINE:
 			status_id = NOVELL_STATUS_TYPE_OFFLINE;
-			loggedin = FALSE;
 			break;
 		case NM_STATUS_AWAY_IDLE:
 			status_id = NOVELL_STATUS_TYPE_AWAY;
@@ -1202,7 +1200,6 @@ _update_buddy_status(NMUser *user, Purpl
 			break;
 		default:
 			status_id = NOVELL_STATUS_TYPE_OFFLINE;
-			loggedin = FALSE;
 			break;
 	}
 
@@ -1404,15 +1401,15 @@ _sync_privacy_lists(NMUser *user)
 	/* 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 +1421,9 @@ _sync_privacy_lists(NMUser *user)
 		else
 			name =(char *)node->data;
 
-		if (!g_slist_find_custom(gc->account->permit,
+		if (!g_slist_find_custom(purple_connection_get_account(gc)->permit,
 								 name, (GCompareFunc)purple_utf8_strcasecmp)) {
-			purple_privacy_permit_add(gc->account, name , TRUE);
+			purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE);
 		}
 	}
 
@@ -1437,15 +1434,15 @@ _sync_privacy_lists(NMUser *user)
 		else
 			name =(char *)node->data;
 
-		if (!g_slist_find_custom(gc->account->deny,
+		if (!g_slist_find_custom(purple_connection_get_account(gc)->deny,
 								 name, (GCompareFunc)purple_utf8_strcasecmp)) {
-			purple_privacy_deny_add(gc->account, name, TRUE);
+			purple_privacy_deny_add(purple_connection_get_account(gc), name, TRUE);
 		}
 	}
 
 
 	/*  Remove stuff */
-	for (node = gc->account->permit; node; node = node->next) {
+	for (node = purple_connection_get_account(gc)->permit; node; node = node->next) {
 		dn = nm_lookup_dn(user, (char *)node->data);
 		if (dn != NULL &&
 			!g_slist_find_custom(user->allow_list,
@@ -1456,13 +1453,13 @@ _sync_privacy_lists(NMUser *user)
 
 	if (rem_list) {
 		for (node = rem_list; node; node = node->next) {
-			purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
+			purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE);
 		}
 		g_slist_free(rem_list);
 		rem_list = NULL;
 	}
 
-	for (node = gc->account->deny; node; node = node->next) {
+	for (node = purple_connection_get_account(gc)->deny; node; node = node->next) {
 		dn = nm_lookup_dn(user, (char *)node->data);
 		if (dn != NULL &&
 			!g_slist_find_custom(user->deny_list,
@@ -1473,7 +1470,7 @@ _sync_privacy_lists(NMUser *user)
 
 	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);
 	}
@@ -1629,7 +1626,7 @@ _initiate_conference_cb(PurpleBlistNode 
 	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;
 
@@ -1685,7 +1682,7 @@ novell_ssl_connect_error(PurpleSslConnec
 	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);
@@ -1702,7 +1699,7 @@ novell_ssl_recv_cb(gpointer data, Purple
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -1736,7 +1733,7 @@ novell_ssl_connected_cb(gpointer data, P
 	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;
 
@@ -2206,7 +2203,7 @@ novell_login(PurpleAccount * account)
 	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"),
@@ -2238,7 +2235,7 @@ novell_close(PurpleConnection * gc)
 	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) {
@@ -2246,7 +2243,7 @@ novell_close(PurpleConnection * gc)
 		}
 		nm_deinitialize_user(user);
 	}
-	gc->proto_data = NULL;
+	purple_connection_set_protocol_data(gc, NULL);
 }
 
 static int
@@ -2266,7 +2263,7 @@ novell_send_im(PurpleConnection * gc, co
 		message_body == NULL || *message_body == '\0')
 		return 0;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return 0;
 
@@ -2352,7 +2349,7 @@ novell_send_typing(PurpleConnection * gc
 	if (gc == NULL || name == NULL)
 		return 0;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return 0;
 
@@ -2386,7 +2383,7 @@ novell_convo_closed(PurpleConnection * g
 	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) {
@@ -2408,7 +2405,7 @@ novell_chat_leave(PurpleConnection * gc,
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2440,7 +2437,7 @@ novell_chat_invite(PurpleConnection *gc,
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2479,7 +2476,7 @@ novell_chat_send(PurpleConnection * gc, 
 	if (gc == NULL || text == NULL)
 		return -1;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return -1;
 
@@ -2545,7 +2542,7 @@ static void
 }
 
 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;
@@ -2619,7 +2616,7 @@ novell_remove_buddy(PurpleConnection *gc
 	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) {
@@ -2651,7 +2648,7 @@ novell_remove_group(PurpleConnection * g
 	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));
 
@@ -2676,7 +2673,7 @@ novell_alias_buddy(PurpleConnection * gc
 	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 */
@@ -2735,7 +2732,7 @@ novell_group_buddy(PurpleConnection * gc
 		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 */
@@ -2793,7 +2790,7 @@ novell_rename_group(PurpleConnection * g
 		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? */
@@ -2839,7 +2836,7 @@ novell_tooltip_text(PurpleBuddy * buddy,
 		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)) {
@@ -2891,7 +2888,7 @@ novell_set_idle(PurpleConnection * gc, i
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2920,7 +2917,7 @@ novell_get_info(PurpleConnection * gc, c
 	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);
@@ -2949,17 +2946,19 @@ novell_status_text(PurpleBuddy * buddy)
 	if (buddy && account) {
 		PurpleConnection *gc = purple_account_get_connection(account);
 
-		if (gc && gc->proto_data) {
-			NMUser *user = gc->proto_data;
+		if (gc) {
+			NMUser *user = purple_connection_get_protocol_data(gc);
 
-			dn = nm_lookup_dn(user, purple_buddy_get_name(buddy));
-			if (dn) {
-				NMUserRecord *user_record = nm_find_user_record(user, dn);
+			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);
+					if (user_record) {
+						text = nm_user_record_get_status_text(user_record);
+						if (text)
+							return g_strdup(text);
+					}
 				}
 			}
 		}
@@ -3035,7 +3034,7 @@ novell_set_status(PurpleAccount *account
 		return;
 
 	gc = purple_account_get_connection(account);
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3082,14 +3081,14 @@ novell_add_permit(PurpleConnection *gc, 
 	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);
@@ -3126,14 +3125,14 @@ novell_add_deny(PurpleConnection *gc, co
 	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);
@@ -3170,7 +3169,7 @@ novell_rem_permit(PurpleConnection *gc, 
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3200,7 +3199,7 @@ novell_rem_deny(PurpleConnection *gc, co
 	if (gc == NULL || who == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3235,7 +3234,7 @@ novell_set_permit_deny(PurpleConnection 
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3251,7 +3250,7 @@ novell_set_permit_deny(PurpleConnection 
 		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,
@@ -3307,14 +3306,14 @@ novell_set_permit_deny(PurpleConnection 
 					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) {
@@ -3328,7 +3327,7 @@ novell_set_permit_deny(PurpleConnection 
 															 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);
 					}
 				}
 			}
@@ -3349,14 +3348,14 @@ novell_set_permit_deny(PurpleConnection 
 					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);
@@ -3371,7 +3370,7 @@ novell_set_permit_deny(PurpleConnection 
 															 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);
 					}
 				}
 
@@ -3463,7 +3462,7 @@ novell_keepalive(PurpleConnection *gc)
 	if (gc == NULL)
 		return;
 
-	user = gc->proto_data;
+	user = purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -3472,6 +3471,7 @@ static PurplePluginProtocolInfo prpl_inf
 }
 
 static PurplePluginProtocolInfo prpl_info = {
+	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	0,
 	NULL,						/* user_splits */
 	NULL,						/* protocol_options */
@@ -3512,7 +3512,6 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
@@ -3537,15 +3536,12 @@ static PurplePluginProtocolInfo prpl_inf
 	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 = {
============================================================
--- libpurple/protocols/silc/buddy.c	f1de313190053bd43d1dad332cdb0df703822fa9
+++ libpurple/protocols/silc/buddy.c	d60f89c7dc3a8ea189662509b32d4424937d55cb
@@ -72,7 +72,7 @@ silcpurple_buddy_keyagr_cb(SilcClient cl
 			   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(PurpleConnect
 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 @@ void silcpurple_buddy_keyagr_request(Sil
 	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 @@ silcpurple_buddy_resetkey(PurpleBlistNod
 
 	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 @@ silcpurple_buddy_privkey(PurpleConnectio
 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 @@ silcpurple_buddy_privkey(PurpleConnectio
 	                     _("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 @@ silcpurple_buddy_getkey(PurpleConnection
 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 @@ silcpurple_buddy_showkey(PurpleBlistNode
 
 	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(PurpleConnectio
 
 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 @@ void silcpurple_get_info(PurpleConnectio
 	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 @@ silcpurple_add_buddy_i(PurpleConnection 
 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 @@ silcpurple_add_buddy_i(PurpleConnection 
 	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 @@ void silcpurple_idle_set(PurpleConnectio
 	const char *server;
 	int port;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (sg == NULL)
 		return;
 
@@ -1467,7 +1467,7 @@ char *silcpurple_status_text(PurpleBuddy
 {
 	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 @@ void silcpurple_tooltip_text(PurpleBuddy
 {
 	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);
@@ -1629,7 +1629,7 @@ silcpurple_buddy_kill(PurpleBlistNode *n
 
 	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",
@@ -1653,7 +1653,7 @@ GList *silcpurple_buddy_menu(PurpleBuddy
 {
 	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;
@@ -1719,7 +1719,7 @@ void silcpurple_buddy_set_icon(PurpleCon
 
 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;
============================================================
--- libpurple/protocols/silc/chat.c	ea6c53dd81fef7750bcfcb5b05fb23b6b6c19e8d
+++ libpurple/protocols/silc/chat.c	c385b245c4e25af9e2613574f77b1f5f7684b66f
@@ -91,7 +91,7 @@ silcpurple_chat_getinfo(PurpleConnection
 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 @@ silcpurple_chat_chauth(PurpleBlistNode *
 
 	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 @@ silcpurple_chat_prv(PurpleBlistNode *nod
 
 	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 @@ silcpurple_chat_permanent_reset(PurpleBl
 
 	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 @@ silcpurple_chat_permanent(PurpleBlistNod
 
 	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 @@ silcpurple_chat_ulimit(PurpleBlistNode *
 
 	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 @@ silcpurple_chat_resettopic(PurpleBlistNo
 
 	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 @@ silcpurple_chat_settopic(PurpleBlistNode
 
 	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 @@ silcpurple_chat_resetprivate(PurpleBlist
 
 	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 @@ silcpurple_chat_setprivate(PurpleBlistNo
 
 	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 @@ silcpurple_chat_resetsecret(PurpleBlistN
 
 	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 @@ silcpurple_chat_setsecret(PurpleBlistNod
 
 	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 @@ GList *silcpurple_chat_menu(PurpleChat *
 {
 	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(PurpleConnecti
 
 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(PurpleConnec
 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(PurpleConnect
 
 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(PurpleConnectio
 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(PurpleCon
 
 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_
 
 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(PurpleRo
 
 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) {
============================================================
--- libpurple/protocols/silc/ft.c	cf0beb6d503ea6d119fbd40ad2ffd6e9dab0e0e1
+++ libpurple/protocols/silc/ft.c	3d2b7ca51875652109d5a2a710bb03a360b73f16
@@ -76,7 +76,7 @@ silcpurple_ftp_monitor(SilcClient client
 
 	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 @@ silcpurple_ftp_monitor(SilcClient client
 		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 @@ silcpurple_ftp_monitor(SilcClient client
 					  _("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 @@ silcpurple_ftp_monitor(SilcClient client
 	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 @@ silcpurple_ftp_cancel(PurpleXfer *x)
 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 @@ silcpurple_ftp_ask_name_cancel(PurpleXfe
 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 @@ silcpurple_ftp_ask_name_ok(PurpleXfer *x
 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 @@ silcpurple_ftp_request_result(PurpleXfer
 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 @@ void silcpurple_ftp_request(SilcClient c
 			    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 @@ void silcpurple_ftp_request(SilcClient c
 	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 @@ silcpurple_ftp_send_cancel(PurpleXfer *x
 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 @@ silcpurple_ftp_send(PurpleXfer *x)
 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(Purp
 
 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 @@ PurpleXfer *silcpurple_ftp_new_xfer(Purp
 	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);
 
============================================================
--- libpurple/protocols/silc/ops.c	ebfa3b56a12fe493cd9c109896cc607b49466f33
+++ libpurple/protocols/silc/ops.c	c61cd3e7439158833e4866c73abce37cc2a5f796
@@ -88,7 +88,7 @@ silcpurple_mime_message(SilcClient clien
 			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;
@@ -224,7 +224,6 @@ silcpurple_mime_message(SilcClient clien
 					    tmp, cflags, time(NULL));
 
 			purple_imgstore_unref_by_id(imgid);
-			cflags = 0;
 			ret = TRUE;
 		}
 		goto out;
@@ -264,7 +263,7 @@ silc_channel_message(SilcClient client, 
 		     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;
 
@@ -332,10 +331,17 @@ silc_channel_message(SilcClient client, 
 	}
 
 	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		tmp = g_markup_escape_text((const char *)message, -1);
+		const char *msg = (const char *)message;
+		char *salvaged = NULL;
+		if (!g_utf8_validate((const char *)message, -1, NULL)) {
+			salvaged = purple_utf8_salvage((const char *)message);
+			msg = salvaged;
+		}
+		tmp = g_markup_escape_text(msg, -1);
 		/* Send to Purple */
 		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
 				 sender->nickname, 0, tmp, time(NULL));
+		g_free(salvaged);
 		g_free(tmp);
 	}
 }
@@ -354,7 +360,7 @@ silc_private_message(SilcClient client, 
 		     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;
 
@@ -408,9 +414,16 @@ silc_private_message(SilcClient client, 
 	}
 
 	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		tmp = g_markup_escape_text((const char *)message, -1);
+		const char *msg = (const char *)message;
+		char *salvaged = NULL;
+		if (!g_utf8_validate((const char *)message, -1, NULL)) {
+			salvaged = purple_utf8_salvage((const char *)message);
+			msg = salvaged;
+		}
+		tmp = g_markup_escape_text(msg, -1);
 		/* Send to Purple */
 		serv_got_im(gc, sender->nickname, tmp, 0, time(NULL));
+		g_free(salvaged);
 		g_free(tmp);
 	}
 }
@@ -431,7 +444,7 @@ silc_notify(SilcClient client, SilcClien
 {
 	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;
@@ -941,7 +954,7 @@ silc_command(SilcClient client, SilcClie
 	     SilcUInt32 argc, unsigned char **argv)
 {
 	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
+	SilcPurple sg = purple_connection_get_protocol_data(gc);
 
 	switch (command) {
 
@@ -1078,7 +1091,7 @@ silc_command_reply(SilcClient client, Si
 		   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) {
@@ -1724,7 +1737,7 @@ silc_get_auth_method(SilcClient client, 
 		     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;
 
@@ -1775,7 +1788,7 @@ silc_verify_public_key(SilcClient client
 		       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)) {
============================================================
--- libpurple/protocols/silc/pk.c	124760e306d7f6f8021b7be37b9d41eeadefe022
+++ libpurple/protocols/silc/pk.c	f14d90e29e609b83d577c5139eae71ee18830da9
@@ -79,7 +79,7 @@ static void silcpurple_verify_details(Pu
 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),
============================================================
--- libpurple/protocols/silc/silc.c	d521e3cf8c4cf75b4e8ffc1e6af24bb4c3ae4307
+++ libpurple/protocols/silc/silc.c	f61e37b261cb14ec31c5b91b493f788894826433
@@ -78,7 +78,7 @@ silcpurple_set_status(PurpleAccount *acc
 	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 @@ silcpurple_keepalive(PurpleConnection *g
 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 @@ silcpurple_scheduler(SilcSchedule schedu
 {
 	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 @@ silcpurple_connect_cb(SilcClient client,
 	struct utsname u;
 #endif
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	switch (status) {
 	case SILC_CLIENT_CONN_SUCCESS:
@@ -367,7 +367,7 @@ silcpurple_stream_created(SilcSocketStre
 	SilcClientConnectionParams params;
 	const char *dfile;
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (status != SILC_SOCKET_OK) {
 		purple_connection_error(gc,
@@ -376,7 +376,7 @@ silcpurple_stream_created(SilcSocketStre
 		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;
 	}
 
@@ -400,7 +400,7 @@ silcpurple_stream_created(SilcSocketStre
 	}
 
 	/* Perform SILC Key Exchange. */
-	silc_client_key_exchange(sg->client, &params, sg->public_key,
+	silc_client_key_exchange(client, &params, sg->public_key,
 				 sg->private_key, stream, SILC_CONN_SERVER,
 				 silcpurple_connect_cb, gc);
 
@@ -415,7 +415,7 @@ silcpurple_login_connected(gpointer data
 
 	g_return_if_fail(gc != NULL);
 
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
 		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -423,7 +423,7 @@ silcpurple_login_connected(gpointer data
 		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;
 	}
 
@@ -449,7 +449,7 @@ static void silcpurple_continue_running(
 	{
 		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(P
 
 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 @@ static void silcpurple_got_password_cb(P
 	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;
 	}
@@ -492,7 +492,7 @@ static void silcpurple_got_password_cb(P
 				&sg->public_key, &sg->private_key)) {
 		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 @@ static void silcpurple_no_password_cb(Pu
 	/* The password prompt dialog doesn't get disposed if the account disconnects */
 	if (!PURPLE_CONNECTION_IS_VALID(gc))
 		return;
-	sg = gc->proto_data;
+	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,7 +528,7 @@ static void silcpurple_running(SilcClien
 	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),
@@ -537,7 +537,7 @@ static void silcpurple_running(SilcClien
 		}
 		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 @@ silcpurple_login(PurpleAccount *account)
 	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");
@@ -612,14 +612,14 @@ silcpurple_login(PurpleAccount *account)
 	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(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);
@@ -632,7 +632,7 @@ silcpurple_login(PurpleAccount *account)
 	if (!silcpurple_check_silc_dir(gc)) {
 		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 @@ silcpurple_close(PurpleConnection *gc)
 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 @@ silcpurple_attrs_cb(PurpleConnection *gc
 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 @@ silcpurple_attrs_cb(PurpleConnection *gc
 	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 *act
 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 @@ silcpurple_attrs(PurplePluginAction *act
 	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 @@ silcpurple_attrs(PurplePluginAction *act
 			    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 @@ silcpurple_detach(PurplePluginAction *ac
 
 	if (!gc)
 		return;
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -1090,7 +1090,7 @@ silcpurple_view_motd(PurplePluginAction 
 
 	if (!gc)
 		return;
-	sg = gc->proto_data;
+	sg = purple_connection_get_protocol_data(gc);
 	if (!sg)
 		return;
 
@@ -1125,7 +1125,7 @@ silcpurple_create_keypair_cb(PurpleConne
 	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(PurplePluginAc
 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 @@ silcpurple_create_keypair(PurplePluginAc
 	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 @@ silcpurple_create_keypair(PurplePluginAc
 			      _("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 @@ silcpurple_change_passwd(PurpleConnectio
 {
 	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 @@ silcpurple_send_im_resolved(SilcClient c
 			    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,
 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 @@ static PurpleCmdRet silcpurple_cmd_chat_
 	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 @@ static PurpleCmdRet silcpurple_cmd_chat_
 	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 @@ static PurpleCmdRet silcpurple_cmd_chat_
 			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 @@ static PurpleCmdRet silcpurple_cmd_chat_
 	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 @@ static PurpleCmdRet silcpurple_cmd_chat_
         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 @@ static PurpleCmdRet silcpurple_cmd_whois
 {
 	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 @@ static PurpleCmdRet silcpurple_cmd_msg(P
 	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 @@ static PurpleCmdRet silcpurple_cmd_query
 		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 @@ static PurpleCmdRet silcpurple_cmd_motd(
 	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 @@ static PurpleCmdRet silcpurple_cmd_detac
 	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 @@ static PurpleCmdRet silcpurple_cmd_cmode
 	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 @@ static PurpleCmdRet silcpurple_cmd_gener
 	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 @@ static PurpleCmdRet silcpurple_cmd_quit(
 	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 @@ static PurpleCmdRet silcpurple_cmd_call(
 	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_inf
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- libpurple/protocols/silc/silcpurple.h	bcf02c313fbf4eae43623d3171690b1eebde81f5
+++ libpurple/protocols/silc/silcpurple.h	3fa4cd75d2a1af6fc6e9b5bfcf60aee5b6263a17
@@ -105,7 +105,7 @@ GList *silcpurple_buddy_menu(PurpleBuddy
 				  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,
============================================================
--- libpurple/protocols/silc/util.c	4462ecbaa7259da78c059e9633985232fd41fec1
+++ libpurple/protocols/silc/util.c	1999cd429db593341dc76cfba20ef68062d12d29
@@ -198,9 +198,9 @@ gboolean silcpurple_check_silc_dir(Purpl
 	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
 	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
 	g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(gc->account, "public-key", pkd));
+		   purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd));
 	g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(gc->account, "private-key", prd));
+		   purple_account_get_string(purple_connection_get_account(gc), "private-key", prd));
 
 	if ((g_stat(file_public_key, &st)) == -1) {
 		/* If file doesn't exist */
@@ -210,8 +210,7 @@ gboolean silcpurple_check_silc_dir(Purpl
 						  SILCPURPLE_DEF_PKCS_LEN,
 						  file_public_key,
 						  file_private_key, NULL,
-						  (gc->password == NULL)
-						  ? "" : gc->password,
+						  (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
 						  NULL, NULL, FALSE)) {
 				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				                             _("Unable to create SILC key pair"));
@@ -253,8 +252,7 @@ gboolean silcpurple_check_silc_dir(Purpl
 						  SILCPURPLE_DEF_PKCS_LEN,
 						  file_public_key,
 						  file_private_key, NULL,
-						  (gc->password == NULL)
-						  ? "" : gc->password,
+						  (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
 						  NULL, NULL, FALSE)) {
 				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
 				                             _("Unable to create SILC key pair"));
============================================================
--- doc/gtkconv-signals.dox	c8a35f342ee12c2b6fb030994e50cd91ed9589ce
+++ doc/gtkconv-signals.dox	070f58f56bc9cfbac75757da732406ac3e477cef
@@ -129,7 +129,6 @@ void (*conversation_hiding)(PidginConver
   @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 @@ void (*conversation_displayed)(PidginCon
   @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
 
 */
============================================================
--- ChangeLog.API	9a6c3ca09547cc2894354ca1dcdcb0dfea4d6aa8
+++ ChangeLog.API	c1edf9f8d5fa2f64f6fbf4efae641c1be1803f93
@@ -3,25 +3,117 @@ version 3.0.0 (??/??/????):
 version 3.0.0 (??/??/????):
 	libpurple:
 		Added:
-		* purple_notify_searchresult_column_set_visible
+		* pidgin_create_webview
+		* purple_account_is_disconnecting
+		* purple_account_get_ui_data
+		* purple_account_set_ui_data
+		* purple_account_register_completed
+		* purple_conv_chat_cb_get_alias
+		* purple_conv_chat_cb_get_flags
+		* purple_conv_chat_cb_is_buddy
+		* purple_conv_chat_cb_get_ui_data
+		* purple_conv_chat_cb_set_ui_data
+		* purple_connection_get_flags
+		* purple_connection_set_flags
+		* purple_connection_update_last_received
+		* purple_conversation_get_ui_data
+		* purple_conversation_set_ui_data
+		* purple_conversation_message_get_alias
+		* purple_conversation_message_get_conv
+		* purple_contact_get_contact_size
+		* purple_notify_searchresult_column_get_title
 		* purple_notify_searchresult_column_is_visible
+		* purple_notify_searchresult_column_set_visible
 		* purple_notify_user_info_prepend_pair_plaintext
+		* 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_field_get_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_util_fetch_url_request_len now takes a PurpleAccount as
+		* 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
@@ -43,28 +135,114 @@ version 3.0.0 (??/??/????):
 		* _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_len, insetad.
+		  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.1:
+	* No changes
+
 version 2.10.0:
 	libpurple:
 		Added:
============================================================
--- libpurple/cmds.c	f2e052a4f379bb397a19af573c691abf8b8f952b
+++ libpurple/cmds.c	5ebbe96a265411706c45d55a361e394d24d662a9
@@ -385,5 +385,10 @@ void purple_cmds_uninit(void)
 void purple_cmds_uninit(void)
 {
 	purple_signals_unregister_by_instance(purple_cmds_get_handle());
+
+	while (cmds) {
+		purple_cmd_free(cmds->data);
+		cmds = g_list_delete_link(cmds, cmds);
+	}
 }
 
============================================================
--- libpurple/cmds.h	bec0c741e6c534d1614e835d6994c387e967eedc
+++ libpurple/cmds.h	0a8d713282bfe229eb7754bd3ed095ccbd49a707
@@ -225,19 +225,16 @@ GList *purple_cmd_help(PurpleConversatio
 /**
  * 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);
 
============================================================
--- libpurple/protocols/yahoo/yahoo_profile.c	45c4628e0fe695b04377da2061a22c473636f724
+++ libpurple/protocols/yahoo/yahoo_profile.c	571edbc65ccd76c72a79929aeed698d3f7e9f7b3
@@ -789,7 +789,7 @@ static void yahoo_got_info(PurpleUtilFet
 
 	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();
@@ -940,7 +940,7 @@ static void yahoo_got_info(PurpleUtilFet
 		 * 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 @@ yahoo_got_photo(PurpleUtilFetchUrlData *
 	/* 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>");
@@ -1262,7 +1262,7 @@ void yahoo_get_info(PurpleConnection *gc
 
 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 @@ void yahoo_get_info(PurpleConnection *gc
 	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 {
============================================================
--- libpurple/protocols/msn/object.c	6b22e0106c25a790cf9b997ba57ba326d285751b
+++ libpurple/protocols/msn/object.c	543caec73eba08c01cd096480e4b5efbfe32b56f
@@ -103,7 +103,7 @@ msn_object_new_from_string(const char *s
 	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 @@ msn_object_new_from_string(const char *s
 		/* 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
 }
 
 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);
============================================================
--- libpurple/protocols/msn/object.h	5ca32b4557df44c385c09545653b2ff2559b1b2b
+++ libpurple/protocols/msn/object.h	e883c365a98d74b5a96600cb1aef2967c9f3695a
@@ -86,9 +86,10 @@ MsnObject *msn_object_new_from_image(Pur
 /**
  * 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.
============================================================
--- libpurple/protocols/msn/slp.c	1b96a2bb84d01ea73ca3b71579df4a3841244f0d
+++ libpurple/protocols/msn/slp.c	f5bee17cef81f6a9dccebbcc5e1c793cdc00e5f2
@@ -253,7 +253,7 @@ msn_request_user_display(MsnUser *user)
 			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 @@ gen_context(PurpleXfer *xfer, const char
 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 @@ gen_context(PurpleXfer *xfer, const char
 
 	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 @@ gen_context(PurpleXfer *xfer, const char
 	}
 	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 @@ msn_request_ft(PurpleXfer *xfer)
 	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 @@ msn_request_ft(PurpleXfer *xfer)
 	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);
 
============================================================
--- libpurple/protocols/msn/slpcall.c	cebfaa918ffb28c9fd14de096ab241e8247d53c9
+++ libpurple/protocols/msn/slpcall.c	7ec33fbce2fa84f8d059fb65b1a91e68256fe6bd
@@ -113,7 +113,7 @@ msn_slpcall_destroy(MsnSlpCall *slpcall)
 	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 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 			if (img)
 				purple_imgstore_ref(img);
 		}
-		msn_object_destroy(obj);
+		msn_object_destroy(obj, FALSE);
 
 		if (img != NULL) {
 			/* DATA PREP */
@@ -512,7 +512,6 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 		MsnFileContext *file_context;
 		char *buf;
 		gsize bin_len;
-		guint32 file_size;
 		char *file_name;
 
 		account = slpcall->slplink->session->account;
@@ -529,8 +528,6 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 		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 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 
 			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 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 			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 @@ got_invite(MsnSlpCall *slpcall,
 
 			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 @@ got_ok(MsnSlpCall *slpcall,
 
 		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 @@ msn_slp_process_msg(MsnSlpLink *slplink,
 
 			if (slpcall->cb)
 				slpcall->cb(slpcall, body, body_len);
-
-			slpcall->wasted = TRUE;
 		}
 	}
 	else if (msn_p2p_info_is_ack(slpmsg->p2p_info))
============================================================
--- libpurple/protocols/msn/slplink.c	50b0eaf0d91d344af8f71eb71216e4b8c55d54c7
+++ libpurple/protocols/msn/slplink.c	a1ef23e2a474ebbb24a3e63129e4cd3a380c85e9
@@ -465,7 +465,7 @@ init_first_msg(MsnSlpLink *slplink, MsnP
 					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);
============================================================
--- libpurple/protocols/msn/slpmsg.c	0698820d787f33ab443f6e6134b08f9b346f9b3f
+++ libpurple/protocols/msn/slpmsg.c	be6f13130e77323d88cc0961c69d738876753ac4
@@ -239,7 +239,7 @@ MsnSlpMessage *msn_slpmsg_dataprep_new(M
 
 }
 
-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
+MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, goffset size)
 {
 	MsnSlpMessage *slpmsg;
 
============================================================
--- libpurple/protocols/msn/slpmsg.h	4a85ea8244a35459680a62cc74dc168ba1c2d4ed
+++ libpurple/protocols/msn/slpmsg.h	2f67320f3c1efb7746733bac8beff89bb73836bd
@@ -133,7 +133,7 @@ MsnSlpMessage *msn_slpmsg_dataprep_new(M
  *
  * @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
============================================================
--- libpurple/protocols/msn/userlist.c	5a7275f182155b4030b83239285c9a5fa1123993
+++ libpurple/protocols/msn/userlist.c	cb24415e8b55fef50375e748b60456da12d03f84
@@ -54,7 +54,7 @@ msn_accept_add_cb(gpointer data)
 
 	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 @@ msn_cancel_add_cb(gpointer data)
 
 	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);
 
============================================================
--- libpurple/protocols/yahoo/yahoo_friend.c	647746bd3f6dd25f368d44ebca8e14fea66c9ee1
+++ libpurple/protocols/yahoo/yahoo_friend.c	e7262f9a39ad9bb7f95018a259ba9b4858432408
@@ -46,9 +46,10 @@ YahooFriend *yahoo_friend_find(PurpleCon
 	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 @@ YahooFriend *yahoo_friend_find_or_new(Pu
 	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(Purple
 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;
============================================================
--- libpurple/protocols/yahoo/yahoo_picture.c	07dd300f6c6820faad574d4567ebd8b7480022e0
+++ libpurple/protocols/yahoo/yahoo_picture.c	bf6a28c006da60144f4a308518c579a64d348e7a
@@ -52,7 +52,7 @@ yahoo_fetch_picture_cb(PurpleUtilFetchUr
 	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) {
@@ -123,26 +123,19 @@ void yahoo_process_picture(PurpleConnect
 		/* TODO: make this work p2p, try p2p before the url */
 		PurpleUtilFetchUrlData *url_data;
 		struct yahoo_fetch_picture_data *data;
-		PurpleBuddy *b = purple_find_buddy(gc->account, who);
-		const char *locksum = NULL;
 		/* use whole URL if using HTTP Proxy */
 		gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
 
-		/* FIXME: Cleanup this strtol() stuff if possible. */
-		if (b && (locksum = purple_buddy_icons_get_checksum_for_user(b)) != NULL &&
-				(checksum == strtol(locksum, NULL, 10)))
-			return;
-
 		data = g_new0(struct yahoo_fetch_picture_data, 1);
 		data->gc = gc;
 		data->who = g_strdup(who);
 		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);
@@ -177,7 +170,7 @@ void yahoo_process_picture_checksum(Purp
 	}
 
 	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. */
@@ -192,7 +185,7 @@ void yahoo_process_picture_upload(Purple
 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;
 
@@ -258,7 +251,7 @@ void yahoo_process_avatar_update(PurpleC
 			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);
@@ -268,7 +261,7 @@ void yahoo_send_picture_info(PurpleConne
 
 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) {
@@ -285,7 +278,7 @@ void yahoo_send_picture_request(PurpleCo
 
 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);
@@ -297,7 +290,7 @@ void yahoo_send_picture_checksum(PurpleC
 
 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);
@@ -308,7 +301,7 @@ void yahoo_send_picture_update_to_user(P
 
 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);
@@ -333,7 +326,7 @@ void yahoo_send_picture_update(PurpleCon
 
 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;
@@ -432,7 +425,7 @@ static void yahoo_buddy_icon_upload_conn
 	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;
@@ -497,7 +490,7 @@ void yahoo_buddy_icon_upload(PurpleConne
 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 */
@@ -542,8 +535,8 @@ void yahoo_set_buddy_icon(PurpleConnecti
 
 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);
============================================================
--- libpurple/protocols/yahoo/ycht.c	e592a3fe8e9efab5c47868008397a15eb021f889
+++ libpurple/protocols/yahoo/ycht.c	7bd032eb05f1bde61084dc0daf43a08171d9317d
@@ -53,7 +53,7 @@ static void ycht_process_login(YchtConn 
 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
 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 @@ static void ycht_progress_online_friends
 {
 #if 0
 	PurpleConnection *gc = ycht->gc;
-	YahooData *yd = gc->proto_data;
+	YahooData *yd = purple_connection_get_protocol_data(gc);
 
 	if (ycht->logged_in)
 		return;
@@ -429,7 +429,7 @@ void ycht_connection_close(YchtConn *ych
 
 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 @@ static void ycht_got_connected(gpointer 
 {
 	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(PurpleConnecti
 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);
============================================================
--- pidgin/gtkdialogs.c	9eba5361c45a5fe75aef93a796fcf98b665f2a33
+++ pidgin/gtkdialogs.c	f57cc733e7fd5e4b90a72697fc4ff0af1bf9bc9f
@@ -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 @@ static const struct translator translato
 	{N_("Assamese"),            "as", "Amitakhya Phukan", "aphukan at fedoraproject.org"},
 	{N_("Belarusian Latin"),    "be at latin", "Ihar Hrachyshka", "ihar.hrachyshka at gmail.com"},
 	{N_("Bulgarian"),           "bg", "Vladimira Girginova", "missing at here.is"},
-	{N_("Bulgarian"),           "bg", "Vladimir (Kaladan) Petkov", "vpetkov at i-space.org"},
+	{N_("Bulgarian"),           "bg", "Vladimir (Kaladan) Petkov", "kaladan at gmail.com"},
 	{N_("Bengali"),             "bn", "Israt Jahan", "israt at ankur.org.bd"},
 	{N_("Bengali"),             "bn", "Jamil Ahmed", "jamil at bengalinux.org"},
 	{N_("Bengali"),             "bn", "Samia Nimatullah", "mailsamia2001 at yahoo.com"},
@@ -222,7 +221,6 @@ static const struct translator translato
 	{N_("Oriya"),               "or", "Manoj Kumar Giri", "giri.manojkr at gmail.com"},
 	{N_("Punjabi"),             "pa", "Amanpreet Singh Alam", "aalam at users.sf.net"},
 	{N_("Polish"),              "pl", "Piotr Dr?g", "piotrdrag at gmail.com"},
-	{N_("Polish"),              "pl", "Piotr Makowski", "pmakowski at aviary.pl"},
 	{N_("Portuguese"),          "pt", "Duarte Henriques", "duarte_henriques at myrealbox.com"},
 	{N_("Portuguese-Brazil"),   "pt_BR", "Rodrigo Luiz Marques Flores", "rodrigomarquesflores at gmail.com"},
 	{N_("Pashto"),              "ps", "Kashif Masood", "masudmails at yahoo.com"},
@@ -304,6 +302,7 @@ static const struct translator past_tran
 	{N_("Polish"),              "pl", "Emil Nowak", "emil5 at go2.pl"},
 	{N_("Polish"),              "pl", "Pawe? Godlewski", "pawel at bajk.pl"},
 	{N_("Polish"),              "pl", "Krzysztof Foltman", "krzysztof at 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 at gmail.com"},
 	{N_("Russian"),             "ru", "Dmitry Beloglazov", "dmaa at users.sf.net"},
@@ -422,9 +421,8 @@ pidgin_build_help_dialog(const char *tit
 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,18 +449,24 @@ pidgin_build_help_dialog(const char *tit
 	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);
 
+#if GTK_CHECK_VERSION(2,18,0)
 	gtk_widget_set_can_default(button, TRUE);
+#else
+	GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+#endif
 	gtk_widget_grab_default(button);
 
 	gtk_widget_show_all(win);
@@ -947,15 +951,14 @@ pidgin_dialogs_ee(const char *ee)
 
 	gtk_container_set_border_width (GTK_CONTAINER(window), PIDGIN_HIG_BOX_SPACE);
 	gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
-	/* TODO: figure out how to set no separator in a dialog in GTK+ 3.0 */
-	/*gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE);*/
-	gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(window))),
-	                    PIDGIN_HIG_BORDER);
-	gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(window))),
-	                               PIDGIN_HIG_BOX_SPACE);
+#if !GTK_CHECK_VERSION(2,22,0)
+	gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE);
+#endif
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(window)->vbox), PIDGIN_HIG_BORDER);
+	gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(window)->vbox), PIDGIN_HIG_BOX_SPACE);
 
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(window))), hbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), hbox);
 	img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_COOL, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
 	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
 
@@ -1130,10 +1133,10 @@ pidgin_dialogs_alias_buddy(PurpleBuddy *
 
 	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,
@@ -1158,7 +1161,7 @@ pidgin_dialogs_alias_chat(PurpleChat *ch
 					   chat->alias, FALSE, FALSE, NULL,
 					   _("Alias"), G_CALLBACK(pidgin_dialogs_alias_chat_cb),
 					   _("Cancel"), NULL,
-					   chat->account, NULL, NULL,
+					   purple_chat_get_account(chat), NULL, NULL,
 					   chat);
 }
 
@@ -1172,8 +1175,8 @@ pidgin_dialogs_remove_contact_cb(PurpleC
 	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);
 }
@@ -1198,8 +1201,8 @@ pidgin_dialogs_remove_contact(PurpleCont
 						"want to continue?",
 						"You are about to remove the contact containing %s "
 						"and %d other buddies from your buddy list.  Do you "
-						"want to continue?", contact->totalsize - 1),
-					buddy->name, contact->totalsize - 1);
+						"want to continue?", purple_contact_get_contact_size(contact, TRUE) - 1),
+					purple_buddy_get_name(buddy), purple_contact_get_contact_size(contact, TRUE) - 1);
 
 		purple_request_action(contact, NULL, _("Remove Contact"), text, 0,
 				NULL, purple_contact_get_alias(contact), NULL,
@@ -1236,7 +1239,7 @@ pidgin_dialogs_merge_groups(PurpleGroup 
 
 	text = g_strdup_printf(
 				_("You are about to merge the group called %s into the group "
-				"called %s. Do you want to continue?"), source->name, new_name);
+				"called %s. Do you want to continue?"), purple_group_get_name(source), new_name);
 
 	ggp = g_new(struct _PidginGroupMergeObject, 1);
 	ggp->parent = source;
@@ -1267,8 +1270,8 @@ pidgin_dialogs_remove_group_cb(PurpleGro
 				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 {
@@ -1278,7 +1281,7 @@ pidgin_dialogs_remove_group_cb(PurpleGro
 		} else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) {
 			PurpleChat *chat = (PurpleChat *)cnode;
 			cnode = cnode->next;
-			if (purple_account_is_connected(chat->account))
+			if (purple_account_is_connected(purple_chat_get_account(chat)))
 				purple_blist_remove_chat(chat);
 		} else {
 			cnode = cnode->next;
@@ -1296,7 +1299,7 @@ pidgin_dialogs_remove_group(PurpleGroup 
 	g_return_if_fail(group != NULL);
 
 	text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list.  Do you want to continue?"),
-						   group->name);
+						   purple_group_get_name(group));
 
 	purple_request_action(group, NULL, _("Remove Group"), text, 0,
 						NULL, NULL, NULL,
@@ -1316,10 +1319,10 @@ pidgin_dialogs_remove_buddy_cb(PurpleBud
 	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);
@@ -1335,7 +1338,7 @@ pidgin_dialogs_remove_buddy(PurpleBuddy 
 	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,
@@ -1365,7 +1368,7 @@ pidgin_dialogs_remove_chat(PurpleChat *c
 			name ? name : "");
 
 	purple_request_action(chat, NULL, _("Remove Chat"), text, 0,
-						chat->account, NULL, NULL,
+						purple_chat_get_account(chat), NULL, NULL,
 						chat, 2,
 						_("_Remove Chat"), G_CALLBACK(pidgin_dialogs_remove_chat_cb),
 						_("Cancel"), NULL);
============================================================
--- pidgin/gtkdialogs.h	46ba5bc90aa00af11b9f04cb2cc5db1ad21e88b3
+++ pidgin/gtkdialogs.h	475f600318d4506ecf7339e9cac158edcc3872c3
@@ -51,6 +51,6 @@ void pidgin_dialogs_merge_groups(PurpleG
 void pidgin_dialogs_merge_groups(PurpleGroup *, const char *);
 
 /* This macro should probably be moved elsewhere */
-#define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(x))) & GDK_WINDOW_STATE_ICONIFIED)
+#define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED)
 
 #endif /* _PIDGINDIALOGS_H_ */
============================================================
--- libpurple/version.h.in	7efcc324b64b08cc6b78b4f7bdaea90cef660a8c
+++ libpurple/version.h.in	2ff700ee399bd0310242e081259e87690ac93827
@@ -56,8 +56,6 @@ const char *purple_version_check(guint r
  * 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 @@ extern const guint purple_major_version;
  * 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 @@ extern const guint purple_minor_version;
  * 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;
 
============================================================
--- pidgin/gtkthemes.c	6e5954a00bd142e33ed6f5d42877f7735ee381a9
+++ pidgin/gtkthemes.c	6f40a62c6138855d33c366bd1c15349d2edb6bfd
@@ -122,6 +122,8 @@ static void _pidgin_themes_smiley_themei
 
 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 @@ static void _pidgin_themes_smiley_themei
 
 		list = list->next;
 	}
+#endif /* if 0 */
 }
 
 void pidgin_themes_smiley_themeize(GtkWidget *imhtml)
@@ -278,6 +281,8 @@ void pidgin_themes_load_smiley_theme(con
 		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 @@ void pidgin_themes_load_smiley_theme(con
 				} 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 @@ void pidgin_themes_load_smiley_theme(con
 
 			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);
 			}
 		}
============================================================
--- pidgin/pidginstock.c	d7212f9e443c795d34f122ee6ace78f60fd0ce57
+++ pidgin/pidginstock.c	27d760196319bd34c9099b911489e268beed07f8
@@ -95,7 +95,7 @@ typedef struct {
 
 typedef struct {
 	const char *name;
-	const char *dir;
+ 	const char *dir;
 	const char *filename;
 	gboolean microscopic;
 	gboolean extra_small;
============================================================
--- pidgin/gtkdnd-hints.c	5cdf91bb56f62595582bb941ab5fb391016e24aa
+++ pidgin/gtkdnd-hints.c	1f93eb44772b2bf4c500975a976813f8b0f63792
@@ -57,34 +57,29 @@ dnd_hints_init_window(const gchar *fname
 static GtkWidget *
 dnd_hints_init_window(const gchar *fname)
 {
-  /* TODO: this is likely very broken right now, I think this needs to be
-     Cairo-ified */
 	GdkPixbuf *pixbuf;
-	/*GdkPixmap *pixmap;*/
-	/*GdkBitmap *bitmap;*/
+	GdkPixmap *pixmap;
+	GdkBitmap *bitmap;
 	GtkWidget *pix;
 	GtkWidget *win;
+	GdkColormap *colormap;
 
 	pixbuf = gdk_pixbuf_new_from_file(fname, NULL);
 	g_return_val_if_fail(pixbuf, NULL);
 
-  /*
-	gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &bitmap, 128);
+	win = gtk_window_new(GTK_WINDOW_POPUP);
+	colormap = gtk_widget_get_colormap(win);
+	gdk_pixbuf_render_pixmap_and_mask_for_colormap(pixbuf, colormap,
+	                                               &pixmap, &bitmap, 128);
 	g_object_unref(G_OBJECT(pixbuf));
-  */
-  
-	/*gtk_widget_push_colormap(gdk_rgb_get_colormap());*/
-	win = gtk_window_new(GTK_WINDOW_POPUP);
-	pix = gtk_image_new_from_pixbuf(pixbuf);
+
+	pix = gtk_image_new_from_pixmap(pixmap, bitmap);
 	gtk_container_add(GTK_CONTAINER(win), pix);
-	/*gtk_widget_shape_combine_mask(win, bitmap, 0, 0);
-	gtk_widget_pop_colormap();*/
+	gtk_widget_shape_combine_mask(win, bitmap, 0, 0);
 
-  /*
 	g_object_unref(G_OBJECT(pixmap));
 	g_object_unref(G_OBJECT(bitmap));
-  */
-  
+
 	gtk_widget_show_all(pix);
 
 	return win;
@@ -94,22 +89,17 @@ get_widget_coords(GtkWidget *w, gint *x1
 get_widget_coords(GtkWidget *w, gint *x1, gint *y1, gint *x2, gint *y2)
 {
 	gint ox, oy, width, height;
-  GtkWidget *parent = gtk_widget_get_parent(w);
-    
-	if (parent && gtk_widget_get_window(parent) == gtk_widget_get_window(w))
-	{
-    GtkAllocation allocation;
 
-    gtk_widget_get_allocation(w, &allocation);
-		get_widget_coords(parent, &ox, &oy, NULL, NULL);
-		height = allocation.height;
-		width = allocation.width;
+	if (w->parent && w->parent->window == w->window)
+	{
+		get_widget_coords(w->parent, &ox, &oy, NULL, NULL);
+		height = w->allocation.height;
+		width = w->allocation.width;
 	}
 	else
 	{
-		gdk_window_get_origin(gtk_widget_get_window(w), &ox, &oy);
-    width = gdk_window_get_width(gtk_widget_get_window(w));
-    height = gdk_window_get_height(gtk_widget_get_window(w));
+		gdk_window_get_origin(w->window, &ox, &oy);
+		gdk_drawable_get_size(w->window, &width, &height);
 	}
 
 	if (x1) *x1 = ox;
@@ -182,13 +172,10 @@ dnd_hints_show_relative(DndHintWindowId 
 {
 	gint x1, x2, y1, y2;
 	gint x = 0, y = 0;
-  GtkAllocation allocation;
 
-  gtk_widget_get_allocation(widget, &allocation);
-
 	get_widget_coords(widget, &x1, &y1, &x2, &y2);
-	x1 += allocation.x;	x2 += allocation.x;
-	y1 += allocation.y;	y2 += allocation.y;
+	x1 += widget->allocation.x;	x2 += widget->allocation.x;
+	y1 += widget->allocation.y;	y2 += widget->allocation.y;
 
 	switch (horiz)
 	{
============================================================
--- pidgin/gtksavedstatuses.c	c769668ae4ef36a23bbeff82ca1a39b95ce40b33
+++ pidgin/gtksavedstatuses.c	f6982dc2c237ab48f1bec14d3ca059cb8e061ed3
@@ -524,7 +524,11 @@ configure_cb(GtkWidget *widget, GdkEvent
 static gboolean
 configure_cb(GtkWidget *widget, GdkEventConfigure *event, StatusWindow *dialog)
 {
+#if GTK_CHECK_VERSION(2,18,0)
 	if (gtk_widget_get_visible(widget))
+#else
+	if (GTK_WIDGET_VISIBLE(widget))
+#endif
 	{
 		purple_prefs_set_int(PIDGIN_PREFS_ROOT "/status/dialog/width",  event->width);
 		purple_prefs_set_int(PIDGIN_PREFS_ROOT "/status/dialog/height", event->height);
============================================================
--- libpurple/savedstatuses.c	115d99392e191c50bac181448aa5ddf5ff0513ea
+++ libpurple/savedstatuses.c	5ea5e47856b232da944af4f8af188d65ba6a81a3
@@ -403,7 +403,7 @@ parse_substatus(xmlnode *substatus)
 	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);
 	}
 
============================================================
--- libpurple/protocols/msn/httpconn.c	eb77536bdfa7a2901f12fc98a106a165687936c2
+++ libpurple/protocols/msn/httpconn.c	5268bda268a2dba1c2296988c73f330485639fec
@@ -285,8 +285,10 @@ read_cb(gpointer data, gint source, Purp
 	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)
============================================================
--- pidgin/gtkstatusbox.c	a184c4e5249c1b45d034ccbf224fb2711ace0632
+++ pidgin/gtkstatusbox.c	74f9a87f6a5a62121920297003b53f9b750f8084
@@ -70,6 +70,16 @@
 /* Timeout for typing notifications in seconds */
 #define TYPING_TIMEOUT 4
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x)
+#define gtk_widget_set_has_window(x, y) do { \
+	if (y) \
+		GTK_WIDGET_UNSET_FLAGS(x, GTK_WIDGET_NO_WINDOW); \
+	else \
+		GTK_WIDGET_SET_FLAGS(x, GTK_WIDGET_NO_WINDOW); \
+} while (0)
+#endif
+
 static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data);
 static void imhtml_format_changed_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, void *data);
 static void remove_typing_cb(PidginStatusBox *box);
@@ -82,10 +92,9 @@ static void pidgin_status_box_changed(Pi
 static void status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed);
 static void pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed);
 static void pidgin_status_box_changed(PidginStatusBox *box);
-static void pidgin_status_box_get_preferred_height (GtkWidget *widget,
-	gint *minimum_height, gint *natural_height);
+static void pidgin_status_box_size_request (GtkWidget *widget, GtkRequisition *requisition);
 static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
-static gboolean pidgin_status_box_draw (GtkWidget *widget, cairo_t *cr);
+static gboolean pidgin_status_box_expose_event (GtkWidget *widget, GdkEventExpose *event);
 static void pidgin_status_box_redisplay_buddy_icon(PidginStatusBox *status_box);
 static void pidgin_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
 static void pidgin_status_box_popup(PidginStatusBox *box);
@@ -283,7 +292,7 @@ update_to_reflect_account_status(PidginS
 
 		if (!message || !*message)
 		{
-			gtk_widget_hide(status_box->vbox);
+			gtk_widget_hide_all(status_box->vbox);
 			status_box->imhtml_visible = FALSE;
 		}
 		else
@@ -344,10 +353,9 @@ icon_box_dnd_cb(GtkWidget *widget, GdkDr
 icon_box_dnd_cb(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
 		GtkSelectionData *sd, guint info, guint t, PidginStatusBox *box)
 {
-	gchar *name = (gchar *) gtk_selection_data_get_data(sd);
+	gchar *name = (gchar *)sd->data;
 
-	if ((gtk_selection_data_get_length(sd) >= 0)
-      && (gtk_selection_data_get_format(sd) == 8)) {
+	if ((sd->length >= 0) && (sd->format == 8)) {
 		/* Well, it looks like the drag event was cool.
 		 * Let's do something with it */
 		if (!g_ascii_strncasecmp(name, "file://", 7)) {
@@ -414,14 +422,14 @@ statusbox_uri_handler(const char *proto,
 	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;
 }
 
 static gboolean
 icon_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, PidginStatusBox *box)
 {
-	gdk_window_set_cursor(gtk_widget_get_window(widget), box->hand_cursor);
+	gdk_window_set_cursor(widget->window, box->hand_cursor);
 	gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon_hover);
 	return FALSE;
 }
@@ -429,7 +437,7 @@ icon_box_leave_cb(GtkWidget *widget, Gdk
 static gboolean
 icon_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, PidginStatusBox *box)
 {
-	gdk_window_set_cursor(gtk_widget_get_window(widget), box->arrow_cursor);
+	gdk_window_set_cursor(widget->window, box->arrow_cursor);
 	gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon) ;
 	return FALSE;
 }
@@ -617,9 +625,9 @@ pidgin_status_box_class_init (PidginStat
 	parent_class = g_type_class_peek_parent(klass);
 
 	widget_class = (GtkWidgetClass*)klass;
-	widget_class->get_preferred_height = pidgin_status_box_get_preferred_height;
+	widget_class->size_request = pidgin_status_box_size_request;
 	widget_class->size_allocate = pidgin_status_box_size_allocate;
-  	widget_class->draw = pidgin_status_box_draw;
+	widget_class->expose_event = pidgin_status_box_expose_event;
 
 	container_class->child_type = pidgin_status_box_child_type;
 	container_class->forall = pidgin_status_box_forall;
@@ -933,7 +941,7 @@ status_menu_refresh_iter(PidginStatusBox
 		if (!purple_savedstatus_is_transient(saved_status) || !message || !*message)
 		{
 			status_box->imhtml_visible = FALSE;
-			gtk_widget_hide(status_box->vbox);
+			gtk_widget_hide_all(status_box->vbox);
 		}
 		else
 		{
@@ -1137,7 +1145,7 @@ static gboolean imhtml_remove_focus(GtkW
 
 static gboolean imhtml_remove_focus(GtkWidget *w, GdkEventKey *event, PidginStatusBox *status_box)
 {
-	if (event->keyval == GDK_KEY_Tab || event->keyval == GDK_KEY_KP_Tab || event->keyval == GDK_KEY_ISO_Left_Tab)
+	if (event->keyval == GDK_Tab || event->keyval == GDK_KP_Tab || event->keyval == GDK_ISO_Left_Tab)
 	{
 		/* If last inserted character is a tab, then remove the focus from here */
 		GtkWidget *top = gtk_widget_get_toplevel(w);
@@ -1150,7 +1158,7 @@ static gboolean imhtml_remove_focus(GtkW
 		return FALSE;
 
 	/* Reset the status if Escape was pressed */
-	if (event->keyval == GDK_KEY_Escape)
+	if (event->keyval == GDK_Escape)
 	{
 		purple_timeout_remove(status_box->typing);
 		status_box->typing = 0;
@@ -1301,15 +1309,13 @@ pidgin_status_box_list_position (PidginS
   GdkRectangle monitor;
   GtkRequisition popup_req;
   GtkPolicyType hpolicy, vpolicy;
-  GtkAllocation allocation;
 
-  gtk_widget_get_allocation(GTK_WIDGET(status_box), &allocation);
-  gdk_window_get_origin (gtk_widget_get_window(GTK_WIDGET(status_box)), x, y);
+  gdk_window_get_origin (GTK_WIDGET(status_box)->window, x, y);
 
-  *x += allocation.x;
-  *y += allocation.y;
+  *x += GTK_WIDGET(status_box)->allocation.x;
+  *y += GTK_WIDGET(status_box)->allocation.y;
 
-  *width = allocation.width;
+  *width = GTK_WIDGET(status_box)->allocation.width;
 
   hpolicy = vpolicy = GTK_POLICY_NEVER;
 	g_object_set(G_OBJECT(status_box->scrolled_window),
@@ -1332,7 +1338,7 @@ pidgin_status_box_list_position (PidginS
 
   screen = gtk_widget_get_screen (GTK_WIDGET (status_box));
   monitor_num = gdk_screen_get_monitor_at_window (screen,
-						  gtk_widget_get_window(GTK_WIDGET (status_box)));
+						  GTK_WIDGET (status_box)->window);
   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
 
   if (*x < monitor.x)
@@ -1340,13 +1346,13 @@ pidgin_status_box_list_position (PidginS
   else if (*x + *width > monitor.x + monitor.width)
     *x = monitor.x + monitor.width - *width;
 
-  if (*y + allocation.height + *height <= monitor.y + monitor.height)
-	  *y += allocation.height;
+  if (*y + GTK_WIDGET(status_box)->allocation.height + *height <= monitor.y + monitor.height)
+	  *y += GTK_WIDGET(status_box)->allocation.height;
   else if (*y - *height >= monitor.y)
 	  *y -= *height;
-  else if (monitor.y + monitor.height - (*y + allocation.height) > *y - monitor.y)
+  else if (monitor.y + monitor.height - (*y + GTK_WIDGET(status_box)->allocation.height) > *y - monitor.y)
     {
-	    *y += allocation.height;
+	    *y += GTK_WIDGET(status_box)->allocation.height;
 	    *height = monitor.y + monitor.height - *y;
     }
   else
@@ -1379,7 +1385,7 @@ popup_grab_on_window (GdkWindow *window,
 		if (!grab_keyboard || gdk_keyboard_grab (window, TRUE, activate_time) == 0)
 			return TRUE;
 		else {
-			gdk_display_pointer_ungrab (gdk_window_get_display (window), activate_time);
+			gdk_display_pointer_ungrab (gdk_drawable_get_display (window), activate_time);
 			return FALSE;
 		}
 	}
@@ -1398,7 +1404,7 @@ pidgin_status_box_popup(PidginStatusBox 
 	gtk_window_move (GTK_WINDOW (box->popup_window), x, y);
 	gtk_widget_show(box->popup_window);
 	gtk_widget_grab_focus (box->tree_view);
-	if (!popup_grab_on_window (gtk_widget_get_window(box->popup_window),
+	if (!popup_grab_on_window (box->popup_window->window,
 				   GDK_CURRENT_TIME, TRUE)) {
 		gtk_widget_hide (box->popup_window);
 		return;
@@ -1429,10 +1435,10 @@ toggle_key_press_cb(GtkWidget *widget, G
 toggle_key_press_cb(GtkWidget *widget, GdkEventKey *event, PidginStatusBox *box)
 {
 	switch (event->keyval) {
-		case GDK_KEY_Return:
-		case GDK_KEY_KP_Enter:
-		case GDK_KEY_KP_Space:
-		case GDK_KEY_space:
+		case GDK_Return:
+		case GDK_KP_Enter:
+		case GDK_KP_Space:
+		case GDK_space:
 			if (!box->popup_in_progress) {
 				pidgin_status_box_popup (box);
 				box->popup_in_progress = TRUE;
@@ -1664,7 +1670,7 @@ treeview_key_press_event(GtkWidget *widg
 			GdkEventKey *event, PidginStatusBox *box)
 {
 	if (box->popup_in_progress) {
-		if (event->keyval == GDK_KEY_Escape) {
+		if (event->keyval == GDK_Escape) {
 			pidgin_status_box_popdown(box);
 			return TRUE;
 		} else {
@@ -1675,9 +1681,9 @@ treeview_key_press_event(GtkWidget *widg
 			if (gtk_tree_selection_get_selected(sel, NULL, &iter)) {
 				gboolean ret = TRUE;
 				path = gtk_tree_model_get_path(GTK_TREE_MODEL(box->dropdown_store), &iter);
-				if (event->keyval == GDK_KEY_Return) {
+				if (event->keyval == GDK_Return) {
 					treeview_activate_current_selection(box, path);
-				} else if (event->keyval == GDK_KEY_Delete) {
+				} else if (event->keyval == GDK_Delete) {
 					tree_view_delete_current_selection(box, path);
 				} else
 					ret = FALSE;
@@ -1929,27 +1935,24 @@ static void
 }
 
 static void
-pidgin_status_box_get_preferred_height(GtkWidget *widget, gint *minimum_height,
-                                       gint *natural_height)
+pidgin_status_box_size_request(GtkWidget *widget,
+								 GtkRequisition *requisition)
 {
-	gint box_min_height, box_nat_height;
-	gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget));
-	
-	gtk_widget_get_preferred_height(PIDGIN_STATUS_BOX(widget)->toggle_button,
-		minimum_height, natural_height);
+	GtkRequisition box_req;
+	gint border_width = GTK_CONTAINER (widget)->border_width;
 
-	*minimum_height = MAX(*minimum_height, 34) + border_width * 2;
-	*natural_height = MAX(*natural_height, 34) + border_width * 2;
+	gtk_widget_size_request(PIDGIN_STATUS_BOX(widget)->toggle_button, requisition);
 
+	/* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */
+	requisition->height = MAX(requisition->height, 34);
+	requisition->height += border_width * 2;
+
 	/* If the gtkimhtml is visible, then add some additional padding */
-	gtk_widget_get_preferred_height(PIDGIN_STATUS_BOX(widget)->vbox,
-		&box_min_height, &box_nat_height);
+	gtk_widget_size_request(PIDGIN_STATUS_BOX(widget)->vbox, &box_req);
+	if (box_req.height > 1)
+		requisition->height += box_req.height + border_width * 2;
 
-	if (box_min_height > 1)
-		*minimum_height += box_min_height + border_width * 2;
-
-	if (box_nat_height > 1)
-		*natural_height += box_nat_height + border_width * 2;
+	requisition->width = 1;
 }
 
 /* From gnome-panel */
@@ -1997,9 +2000,9 @@ pidgin_status_box_size_allocate(GtkWidge
 				  GtkAllocation *allocation)
 {
 	PidginStatusBox *status_box = PIDGIN_STATUS_BOX(widget);
-	GtkRequisition req = {0,40};
+	GtkRequisition req = {0,0};
 	GtkAllocation parent_alc, box_alc, icon_alc;
-	gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget));
+	gint border_width = GTK_CONTAINER (widget)->border_width;
 
 	gtk_widget_size_request(status_box->toggle_button, &req);
 	/* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */
@@ -2038,24 +2041,19 @@ pidgin_status_box_size_allocate(GtkWidge
 		gtk_widget_size_allocate(status_box->icon_box, &icon_alc);
 	}
 	gtk_widget_size_allocate(status_box->toggle_button, &parent_alc);
-  	gtk_widget_set_allocation(GTK_WIDGET(status_box), allocation);
-	purple_debug_info("pidgin", "statusbox allocation: width = %d, height = %d\n",
-	                  allocation->width, allocation->height);
+	widget->allocation = *allocation;
 }
 
 static gboolean
-pidgin_status_box_draw(GtkWidget *widget, cairo_t *cr)
+pidgin_status_box_expose_event(GtkWidget *widget,
+				 GdkEventExpose *event)
 {
 	PidginStatusBox *status_box = PIDGIN_STATUS_BOX(widget);
-	gtk_widget_draw(status_box->vbox, cr);
-	gtk_widget_draw(status_box->toggle_button, cr);
-
+	gtk_container_propagate_expose(GTK_CONTAINER(widget), status_box->vbox, event);
+	gtk_container_propagate_expose(GTK_CONTAINER(widget), status_box->toggle_button, event);
 	if (status_box->icon_box && status_box->icon_opaque) {
-		GtkAllocation allocation;
-
-		gtk_widget_get_allocation(status_box->icon_box, &allocation);
-		gtk_paint_box(gtk_widget_get_style(widget), cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-				status_box->icon_box, "button", allocation.x-1, allocation.y-1,
+		gtk_paint_box(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL,
+				status_box->icon_box, "button", status_box->icon_box->allocation.x-1, status_box->icon_box->allocation.y-1,
 				34, 34);
 	}
 	return FALSE;
@@ -2365,7 +2363,7 @@ activate_currently_selected_status(Pidgi
 	message = pidgin_status_box_get_message(status_box);
 	if (!message || !*message)
 	{
-		gtk_widget_hide(status_box->vbox);
+		gtk_widget_hide_all(status_box->vbox);
 		status_box->imhtml_visible = FALSE;
 		if (message != NULL)
 		{
@@ -2637,7 +2635,7 @@ static void pidgin_status_box_changed(Pi
 		purple_timeout_remove(status_box->typing);
 	status_box->typing = 0;
 
-	if (gtk_widget_get_sensitive(GTK_WIDGET(status_box)))
+	if (gtk_widget_is_sensitive(GTK_WIDGET(status_box)))
 	{
 		if (type == PIDGIN_STATUS_BOX_TYPE_POPULAR || type == PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR)
 		{
@@ -2699,7 +2697,7 @@ static void pidgin_status_box_changed(Pi
 	}
 	g_list_free(accounts);
 
-	if (gtk_widget_get_sensitive(GTK_WIDGET(status_box)))
+	if (gtk_widget_is_sensitive(GTK_WIDGET(status_box)))
 	{
 		if (status_box->imhtml_visible)
 		{
@@ -2719,7 +2717,7 @@ static void pidgin_status_box_changed(Pi
 		}
 		else
 		{
-			gtk_widget_hide(status_box->vbox);
+			gtk_widget_hide_all(status_box->vbox);
 			activate_currently_selected_status(status_box); /* This is where we actually set the status */
 		}
 	}
@@ -2755,7 +2753,7 @@ static void imhtml_changed_cb(GtkTextBuf
 static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data)
 {
 	PidginStatusBox *status_box = (PidginStatusBox*)data;
-	if (gtk_widget_get_sensitive(GTK_WIDGET(status_box)))
+	if (gtk_widget_is_sensitive(GTK_WIDGET(status_box)))
 	{
 		if (status_box->typing != 0) {
 			pidgin_status_box_pulse_typing(status_box);
============================================================
--- libpurple/protocols/sametime/sametime.c	93d12d579831ca6ea9f24770b9bf7a2ee563696f
+++ libpurple/protocols/sametime/sametime.c	efb59ed06510303bd2754592d14bb11286784094
@@ -171,10 +171,10 @@ enum blist_choice {
 
 
 /* debugging output */
-#define DEBUG_ERROR(a...)  purple_debug_error(G_LOG_DOMAIN, a)
-#define DEBUG_INFO(a...)   purple_debug_info(G_LOG_DOMAIN, a)
-#define DEBUG_MISC(a...)   purple_debug_misc(G_LOG_DOMAIN, a)
-#define DEBUG_WARN(a...)   purple_debug_warning(G_LOG_DOMAIN, a)
+#define DEBUG_ERROR(...)  purple_debug_error(G_LOG_DOMAIN, __VA_ARGS__)
+#define DEBUG_INFO(...)   purple_debug_info(G_LOG_DOMAIN, __VA_ARGS__)
+#define DEBUG_MISC(...)   purple_debug_misc(G_LOG_DOMAIN, __VA_ARGS__)
+#define DEBUG_WARN(...)   purple_debug_warning(G_LOG_DOMAIN, __VA_ARGS__)
 
 
 /** ensure non-null strings */
@@ -197,7 +197,7 @@ static guint log_handler[2] = { 0, 0 };
 
 
 /** 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 @@ struct mwPurplePluginData {
 
   /** 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 @@ static struct mwSession *gc_to_session(P
 
   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;
@@ -449,9 +450,9 @@ static void mw_session_io_close(struct m
     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 @@ static void mw_aware_list_on_aware(struc
   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(PurpleC
 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);
 
@@ -927,6 +928,11 @@ static PurpleGroup *group_ensure(PurpleC
     return NULL;
   }
 
+  if (!name) {
+    DEBUG_WARN("Can't ensure a null group\n");
+    return NULL;
+  }
+
   DEBUG_INFO("attempting to ensure group %s, called %s\n",
 	     NSTR(name), NSTR(alias));
 
@@ -968,7 +974,7 @@ static PurpleGroup *group_ensure(PurpleC
 
   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;
@@ -1274,7 +1280,7 @@ static void conversation_created_cb(Purp
   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 */
 
@@ -1398,7 +1404,7 @@ static void blist_init(PurpleAccount *ac
   }
 
   if(add_buds) {
-    purple_account_add_buddies(acct, add_buds);
+    purple_account_add_buddies(acct, add_buds, NULL);
     g_list_free(add_buds);
   }
 }
@@ -1755,9 +1761,9 @@ static void read_cb(gpointer data, gint 
     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) {
@@ -1786,7 +1792,6 @@ static void connect_cb(gpointer data, gi
 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 */
@@ -1814,7 +1819,7 @@ static void connect_cb(gpointer data, gi
   }
 
   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);
@@ -2139,7 +2144,7 @@ static void ft_incoming_cancel(PurpleXfe
 
 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);
 }
 
@@ -2155,9 +2160,9 @@ static void ft_incoming_init(PurpleXfer 
   struct mwFileTransfer *ft;
   FILE *fp;
 
-  ft = xfer->data;
+  ft = purple_xfer_get_protocol_data(xfer);
 
-  fp = g_fopen(xfer->local_filename, "wb");
+  fp = g_fopen(purple_xfer_get_local_filename(xfer), "wb");
   if(! fp) {
     mwFileTransfer_cancel(ft);
     return;
@@ -2202,7 +2207,7 @@ static void mw_ft_offered(struct mwFileT
   {
 	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);
@@ -2219,7 +2224,7 @@ static void ft_send(struct mwFileTransfe
 
 static void ft_send(struct mwFileTransfer *ft, FILE *fp) {
   guchar buf[MW_FT_LEN];
-  struct mwOpaque o = { .data = buf, .len = MW_FT_LEN };
+  struct mwOpaque o = { MW_FT_LEN, buf };
   guint32 rem;
   PurpleXfer *xfer;
 
@@ -2231,8 +2236,7 @@ static void ft_send(struct mwFileTransfe
   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);
@@ -2264,7 +2268,7 @@ static void mw_ft_opened(struct mwFileTr
   }
 
   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);
   }
 }
@@ -2281,7 +2285,7 @@ static void mw_ft_closed(struct mwFileTr
 
   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);
@@ -2334,8 +2338,7 @@ static void mw_ft_recv(struct mwFileTran
   }
 
   /* 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 */
@@ -2348,7 +2351,7 @@ static void mw_ft_ack(struct mwFileTrans
 
   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);
@@ -2482,12 +2485,12 @@ static void convo_error(struct mwConvers
   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);
   }
 
@@ -2525,10 +2528,10 @@ static void convo_nofeatures(struct mwCo
   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));
 }
 
 
@@ -3194,7 +3197,7 @@ static struct mwPurplePluginData *mwPurp
   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;
 }
@@ -3203,7 +3206,7 @@ static void mwPurplePluginData_free(stru
 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);
@@ -3265,7 +3268,7 @@ static char *mw_prpl_status_text(PurpleB
   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;
@@ -3328,7 +3331,7 @@ static void mw_prpl_tooltip_text(PurpleB
   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);
@@ -3405,7 +3408,7 @@ static void conf_create_prompt_join(Purp
 
   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);
@@ -3571,7 +3574,7 @@ static void blist_menu_conf(PurpleBlistN
   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);
 
   /*
@@ -3610,7 +3613,7 @@ static void blist_menu_announce(PurpleBl
   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);
@@ -3687,49 +3690,6 @@ static void mw_prpl_login(PurpleAccount 
 static void mw_prpl_login(PurpleAccount *acct);
 
 
-static void prompt_host_cancel_cb(PurpleConnection *gc) {
-  const char *msg = _("No Sametime Community Server specified");
-  purple_connection_error(gc,
-                                 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-                                 msg);
-}
-
-
-static void prompt_host_ok_cb(PurpleConnection *gc, const char *host) {
-  if(host && *host) {
-    PurpleAccount *acct = purple_connection_get_account(gc);
-    purple_account_set_string(acct, MW_KEY_HOST, host);
-    mw_prpl_login(acct);
-
-  } else {
-    prompt_host_cancel_cb(gc);
-  }
-}
-
-
-static void prompt_host(PurpleConnection *gc) {
-  PurpleAccount *acct;
-  const char *msgA;
-  char *msg;
-
-  acct = purple_connection_get_account(gc);
-  msgA = _("No host or IP address has been configured for the"
-	  " Meanwhile account %s. Please enter one below to"
-	  " continue logging in.");
-  msg = g_strdup_printf(msgA, NSTR(purple_account_get_username(acct)));
-
-  purple_request_input(gc, _("Meanwhile Connection Setup"),
-		     _("No Sametime Community Server Specified"), msg,
-		     MW_PLUGIN_DEFAULT_HOST, FALSE, FALSE, NULL,
-		     _("Connect"), G_CALLBACK(prompt_host_ok_cb),
-		     _("Cancel"), G_CALLBACK(prompt_host_cancel_cb),
-			 acct, NULL, NULL,
-		     gc);
-
-  g_free(msg);
-}
-
-
 static void mw_prpl_login(PurpleAccount *account) {
   PurpleConnection *gc;
   struct mwPurplePluginData *pd;
@@ -3741,7 +3701,7 @@ static void mw_prpl_login(PurpleAccount 
   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));
 
@@ -3761,7 +3721,9 @@ static void mw_prpl_login(PurpleAccount 
     /* 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);
-    prompt_host(gc);
+    purple_connection_error(gc,
+            PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
+            _("A server is required to connect this account"));
     return;
   }
 
@@ -3815,7 +3777,7 @@ static void mw_prpl_close(PurpleConnecti
 
   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 */
@@ -3829,12 +3791,12 @@ static void mw_prpl_close(PurpleConnecti
   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 */
@@ -4020,7 +3982,7 @@ static int mw_prpl_send_im(PurpleConnect
   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);
 
@@ -4095,7 +4057,7 @@ static unsigned int mw_prpl_send_typing(
   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);
 
@@ -4191,7 +4153,7 @@ static void mw_prpl_get_info(PurpleConne
   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);
@@ -4436,7 +4398,7 @@ static void add_buddy_resolved(struct mw
   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;
@@ -4515,9 +4477,10 @@ static void mw_prpl_add_buddy(PurpleConn
 
 static void mw_prpl_add_buddy(PurpleConnection *gc,
 			      PurpleBuddy *buddy,
-			      PurpleGroup *group) {
+			      PurpleGroup *group,
+			      const char *message) {
 
-  struct mwPurplePluginData *pd = gc->proto_data;
+  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
   struct mwServiceResolve *srvc;
   GList *query;
   enum mwResolveFlag flags;
@@ -4562,13 +4525,14 @@ static void mw_prpl_add_buddies(PurpleCo
 
 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);
@@ -4619,7 +4583,7 @@ static void mw_prpl_remove_buddy(PurpleC
 
   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);
 
@@ -4666,13 +4630,13 @@ static void mw_prpl_set_permit_deny(Purp
   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);
@@ -4696,7 +4660,7 @@ static void mw_prpl_set_permit_deny(Purp
     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;
   }
 
@@ -4750,7 +4714,7 @@ static void mw_prpl_join_chat(PurpleConn
   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);
@@ -4792,7 +4756,7 @@ static void mw_prpl_reject_chat(PurpleCo
   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)) {
@@ -4824,7 +4788,7 @@ static void mw_prpl_chat_invite(PurpleCo
   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);
@@ -4848,7 +4812,7 @@ static void mw_prpl_chat_leave(PurpleCon
   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);
@@ -4884,7 +4848,7 @@ static int mw_prpl_chat_send(PurpleConne
   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);
@@ -4922,7 +4886,7 @@ static void mw_prpl_alias_buddy(PurpleCo
 				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
@@ -4940,7 +4904,7 @@ static void mw_prpl_group_buddy(PurpleCo
   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;
 
@@ -4966,7 +4930,7 @@ static void mw_prpl_rename_group(PurpleC
 				 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
@@ -4986,7 +4950,7 @@ static void mw_prpl_convo_closed(PurpleC
 
 
 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 };
@@ -5021,7 +4985,7 @@ static void mw_prpl_remove_group(PurpleC
   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);
 
@@ -5045,7 +5009,7 @@ static gboolean mw_prpl_can_receive_file
 
   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;
@@ -5077,12 +5041,12 @@ static void ft_outgoing_init(PurpleXfer 
 
   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);
 
@@ -5091,7 +5055,7 @@ static void ft_outgoing_init(PurpleXfer 
   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;
   }
@@ -5106,14 +5070,14 @@ static void ft_outgoing_init(PurpleXfer 
 
   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");
 
@@ -5154,67 +5118,77 @@ static PurplePluginProtocolInfo mw_prpl_
 
 
 static PurplePluginProtocolInfo mw_prpl_info = {
-  .options                   = OPT_PROTO_IM_IMAGE,
-  .user_splits               = NULL, /*< set in mw_plugin_init */
-  .protocol_options          = NULL, /*< set in mw_plugin_init */
-  .icon_spec                 = NO_BUDDY_ICONS,
-  .list_icon                 = mw_prpl_list_icon,
-  .list_emblem               = mw_prpl_list_emblem,
-  .status_text               = mw_prpl_status_text,
-  .tooltip_text              = mw_prpl_tooltip_text,
-  .status_types              = mw_prpl_status_types,
-  .blist_node_menu           = mw_prpl_blist_node_menu,
-  .chat_info                 = mw_prpl_chat_info,
-  .chat_info_defaults        = mw_prpl_chat_info_defaults,
-  .login                     = mw_prpl_login,
-  .close                     = mw_prpl_close,
-  .send_im                   = mw_prpl_send_im,
-  .set_info                  = NULL,
-  .send_typing               = mw_prpl_send_typing,
-  .get_info                  = mw_prpl_get_info,
-  .set_status                = mw_prpl_set_status,
-  .set_idle                  = mw_prpl_set_idle,
-  .change_passwd             = NULL,
-  .add_buddy                 = mw_prpl_add_buddy,
-  .add_buddies               = mw_prpl_add_buddies,
-  .remove_buddy              = mw_prpl_remove_buddy,
-  .remove_buddies            = NULL,
-  .add_permit                = mw_prpl_add_permit,
-  .add_deny                  = mw_prpl_add_deny,
-  .rem_permit                = mw_prpl_rem_permit,
-  .rem_deny                  = mw_prpl_rem_deny,
-  .set_permit_deny           = mw_prpl_set_permit_deny,
-  .join_chat                 = mw_prpl_join_chat,
-  .reject_chat               = mw_prpl_reject_chat,
-  .get_chat_name             = mw_prpl_get_chat_name,
-  .chat_invite               = mw_prpl_chat_invite,
-  .chat_leave                = mw_prpl_chat_leave,
-  .chat_whisper              = mw_prpl_chat_whisper,
-  .chat_send                 = mw_prpl_chat_send,
-  .keepalive                 = mw_prpl_keepalive,
-  .register_user             = NULL,
-  .get_cb_info               = NULL,
-  .get_cb_away               = NULL,
-  .alias_buddy               = mw_prpl_alias_buddy,
-  .group_buddy               = mw_prpl_group_buddy,
-  .rename_group              = mw_prpl_rename_group,
-  .buddy_free                = mw_prpl_buddy_free,
-  .convo_closed              = mw_prpl_convo_closed,
-  .normalize                 = mw_prpl_normalize,
-  .set_buddy_icon            = NULL,
-  .remove_group              = mw_prpl_remove_group,
-  .get_cb_real_name          = NULL,
-  .set_chat_topic            = NULL,
-  .find_blist_chat           = NULL,
-  .roomlist_get_list         = NULL,
-  .roomlist_expand_category  = NULL,
-  .can_receive_file          = mw_prpl_can_receive_file,
-  .send_file                 = mw_prpl_send_file,
-  .new_xfer                  = mw_prpl_new_xfer,
-  .offline_message           = NULL,
-  .whiteboard_prpl_ops       = NULL,
-  .send_raw                  = NULL,
-  .struct_size               = sizeof(PurplePluginProtocolInfo)
+  sizeof(PurplePluginProtocolInfo),
+  OPT_PROTO_IM_IMAGE,
+  NULL, /*< set in mw_plugin_init */
+  NULL, /*< set in mw_plugin_init */
+  NO_BUDDY_ICONS,
+  mw_prpl_list_icon,
+  mw_prpl_list_emblem,
+  mw_prpl_status_text,
+  mw_prpl_tooltip_text,
+  mw_prpl_status_types,
+  mw_prpl_blist_node_menu,
+  mw_prpl_chat_info,
+  mw_prpl_chat_info_defaults,
+  mw_prpl_login,
+  mw_prpl_close,
+  mw_prpl_send_im,
+  NULL,
+  mw_prpl_send_typing,
+  mw_prpl_get_info,
+  mw_prpl_set_status,
+  mw_prpl_set_idle,
+  NULL,
+  mw_prpl_add_buddy,
+  mw_prpl_add_buddies,
+  mw_prpl_remove_buddy,
+  NULL,
+  mw_prpl_add_permit,
+  mw_prpl_add_deny,
+  mw_prpl_rem_permit,
+  mw_prpl_rem_deny,
+  mw_prpl_set_permit_deny,
+  mw_prpl_join_chat,
+  mw_prpl_reject_chat,
+  mw_prpl_get_chat_name,
+  mw_prpl_chat_invite,
+  mw_prpl_chat_leave,
+  mw_prpl_chat_whisper,
+  mw_prpl_chat_send,
+  mw_prpl_keepalive,
+  NULL,
+  NULL,
+  mw_prpl_alias_buddy,
+  mw_prpl_group_buddy,
+  mw_prpl_rename_group,
+  mw_prpl_buddy_free,
+  mw_prpl_convo_closed,
+  mw_prpl_normalize,
+  NULL,
+  mw_prpl_remove_group,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  mw_prpl_can_receive_file,
+  mw_prpl_send_file,
+  mw_prpl_new_xfer,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL
 };
 
 
@@ -5536,7 +5510,7 @@ static void remote_group_action_cb(Purpl
   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);
@@ -5661,7 +5635,7 @@ static void search_action_cb(PurpleConne
   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);
@@ -5791,6 +5765,7 @@ static void mw_plugin_init(PurplePlugin 
 
 
 static void mw_plugin_init(PurplePlugin *plugin) {
+  PurpleAccountUserSplit *split;
   PurpleAccountOption *opt;
   GList *l = NULL;
 
@@ -5801,15 +5776,15 @@ static void mw_plugin_init(PurplePlugin 
   purple_prefs_add_none(MW_PRPL_OPT_BASE);
   purple_prefs_add_int(MW_PRPL_OPT_BLIST_ACTION, BLIST_CHOICE_DEFAULT);
 
+  /* set up account ID as user:server */
+  split = purple_account_user_split_new(_("Server"),
+                                        MW_PLUGIN_DEFAULT_HOST, ':');
+  mw_prpl_info.user_splits = g_list_append(mw_prpl_info.user_splits, split);
+
   /* remove dead preferences */
   purple_prefs_remove(MW_PRPL_OPT_PSYCHIC);
   purple_prefs_remove(MW_PRPL_OPT_SAVE_DYNAMIC);
 
-  /* host to connect to */
-  opt = purple_account_option_string_new(_("Server"), MW_KEY_HOST,
-				       MW_PLUGIN_DEFAULT_HOST);
-  l = g_list_append(l, opt);
-
   /* port to connect to */
   opt = purple_account_option_int_new(_("Port"), MW_KEY_PORT,
 				    MW_PLUGIN_DEFAULT_PORT);
============================================================
--- libpurple/dbus-server.c	2ba309612c9538f946061f6f8bab1e35d15816c6
+++ libpurple/dbus-server.c	42111b87610fa45ee3af8e31d77351fd98579437
@@ -300,7 +300,7 @@ dbus_int32_t *
 }
 
 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 @@ purple_dbusify_GList(GList *list, gboole
 	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 @@ purple_dbusify_GSList(GSList *list, gboo
 	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 @@ purple_GList_to_array(GList *list, gbool
 	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 @@ purple_GSList_to_array(GSList *list, gbo
 	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 @@ purple_dbus_message_append_purple_values
 			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:
============================================================
--- libpurple/dbus-server.h	b3d30a7bc5ae8a2c2d5e00747d74c0337592bad4
+++ libpurple/dbus-server.h	a9cde0bb516c150b2edd122ee8639f668e7a6788
@@ -173,8 +173,6 @@ void *purple_dbus_get_handle(void);
 
 /**
  * Determines whether this instance owns the DBus service name
- *
- * @since 2.1.0
  */
 gboolean purple_dbus_is_owner(void);
 
============================================================
--- pidgin/plugins/musicmessaging/musicmessaging.c	5197d9c886e489e77e4ef4f2ff763aec3a1198cd
+++ pidgin/plugins/musicmessaging/musicmessaging.c	b30aae9f2d30f4a41b4595a739d3754814b569f3
@@ -104,7 +104,7 @@ void music_messaging_change_request(cons
 	{
 		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 @@ intercept_received(PurpleAccount *accoun
 				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 @@ intercept_received(PurpleAccount *accoun
 				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 
 
 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);
 }
============================================================
--- libpurple/plugins/perl/common/FT.xs	9e6ae8f0b81a5fcc618d505f7a24f8855cb32402
+++ libpurple/plugins/perl/common/FT.xs	9511e96eb38934f9f2a4adab68d035f6c7375a72
@@ -113,7 +113,7 @@ gboolean 
 	Purple::Xfer xfer
 
 gboolean 
-purple_xfer_is_canceled(xfer)
+purple_xfer_is_cancelled(xfer)
 	Purple::Xfer xfer
 
 gboolean 
============================================================
--- libpurple/plugins/perl/common/Network.xs	33be31409873a5822c7a3363b87b9ad1d621170c
+++ libpurple/plugins/perl/common/Network.xs	72efac700fe94ae2733782d1b407dbce0dc9f0ba
@@ -23,17 +23,21 @@ Purple::NetworkListenData
 	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
 
============================================================
--- libpurple/plugins/perl/common/Request.xs	ce85162d4264019b9d27d08534bb16cce748431c
+++ libpurple/plugins/perl/common/Request.xs	5dc1f14763e30723bddbe5df5da6282e2ed8f0b3
@@ -374,12 +374,6 @@ void
 	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
============================================================
--- libpurple/plugins/perl/common/SSLConn.xs	d9a4f2bccbf141bd8cc3c0e7734707ec5e886d90
+++ libpurple/plugins/perl/common/SSLConn.xs	557f67d0ed45d426346f6b6ff72e8181b49f7b6e
@@ -16,13 +16,6 @@ purple_ssl_input_add(gsc, func, data)
 	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_
============================================================
--- libpurple/plugins/perl/common/Status.xs	69fa64a67143cf1ee01709ebe65f3a3a169d8269
+++ libpurple/plugins/perl/common/Status.xs	7d060137e9e408b2f5dae818b81dd5fc74fc5938
@@ -74,28 +74,6 @@ BOOT:
 		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_set_active(status, active)
 	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
 
============================================================
--- libpurple/plugins/perl/common/Util.xs	ac3d9ea652a79066c672e262d6f99d5949186a1a
+++ libpurple/plugins/perl/common/Util.xs	070be8c6e1335d58f180f4dfc772f94469214a12
@@ -202,6 +202,14 @@ purple_ip_address_is_valid(ip)
 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 @@ void
 
  #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 @@ PPCODE:
 	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 {
============================================================
--- libpurple/dbus-analyze-functions.py	131c3493db95f5025976e3de5497b92823228caa
+++ libpurple/dbus-analyze-functions.py	bdd1d7154be6c8290d8ff1970dbd6bf326825166
@@ -29,8 +29,12 @@ excluded = [\
     # 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.
     "purple_blist_get_ui_data",
@@ -491,7 +495,7 @@ class ServerBinding (Binding):
         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 @@ class ServerBinding (Binding):
         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:])
============================================================
--- libpurple/dbus-useful.c	121af7c96cfa2087f961dc8ad2d8d20a3dcab904
+++ libpurple/dbus-useful.c	d1f02a0b6b85605efe46457908c394e2c9c23486
@@ -25,7 +25,7 @@ purple_accounts_find_ext(const char *nam
 		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))
============================================================
--- libpurple/dbus-bindings.h	55b8c581bc82b5fa70ee12d1b6e827ba16eb0b0e
+++ libpurple/dbus-bindings.h	bebbe1122b524f649d0f49dee33ac45381c66db1
@@ -84,14 +84,10 @@ purple_dbus_message_iter_get_args_valist
 					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);
============================================================
--- libpurple/protocols/simple/simple.c	2f073d2b31def0b301a975251323f25bde18be00
+++ libpurple/protocols/simple/simple.c	63bdc5aa575fcca526458dffc8d0f3e5f46e706c
@@ -67,7 +67,7 @@ static void simple_keep_alive(PurpleConn
 }
 
 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(PurpleAcco
 }
 
 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 connection_free_all(struct s
 	}
 }
 
-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 @@ static void simple_get_buddies(PurpleCon
 	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(PurpleCo
 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 
 
 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;
 
@@ -457,7 +458,7 @@ static void send_later_cb(gpointer data,
 		return;
 	}
 
-	sip = gc->proto_data;
+	sip = purple_connection_get_protocol_data(gc);
 	sip->fd = source;
 	sip->connecting = FALSE;
 
@@ -474,7 +475,7 @@ static void sendlater(PurpleConnection *
 
 
 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);
@@ -491,7 +492,7 @@ static void sendout_pkt(PurpleConnection
 }
 
 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(PurpleConne
 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(PurpleConnecti
 }
 
 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,8 +1121,8 @@ gboolean process_register_response(struc
 			if(sip->registerstatus != SIMPLE_REGISTER_RETRY) {
 				purple_debug_info("simple", "REGISTER retries %d\n", sip->registrar.retries);
 				if(sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) {
-					if (!purple_account_get_remember_password(sip->gc->account))
-						purple_account_set_password(sip->gc->account, NULL);
+					if (!purple_account_get_remember_password(purple_connection_get_account(sip->gc)))
+						purple_account_set_password(purple_connection_get_account(sip->gc), NULL);
 					purple_connection_error(sip->gc,
 						PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
 						_("Incorrect password"));
@@ -1285,7 +1286,7 @@ static unsigned int simple_typing(Purple
 }
 
 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 
 
 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 dat
 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 @@ static void simple_input_cb(gpointer dat
 		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 @@ static void simple_newconn_cb(gpointer d
 /* 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;
 
@@ -1745,7 +1746,7 @@ static void login_cb(gpointer data, gint
 		return;
 	}
 
-	sip = gc->proto_data;
+	sip = purple_connection_get_protocol_data(gc);
 	sip->fd = source;
 
 	conn = connection_create(sip, source);
@@ -1822,7 +1823,7 @@ static void simple_udp_host_resolved(GSL
 	}
 
 	/* 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(sip->gc,
@@ -1892,7 +1893,7 @@ static void srvresolved(PurpleSrvRespons
 	/* 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(sip->gc,
@@ -1903,7 +1904,7 @@ static void srvresolved(PurpleSrvRespons
 	} 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(sip->gc,
@@ -1930,7 +1931,8 @@ static void simple_login(PurpleAccount *
 		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;
@@ -1968,13 +1970,13 @@ static void simple_login(PurpleAccount *
 		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 @@ static void simple_close(PurpleConnectio
 		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 @@ static void simple_close(PurpleConnectio
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
 };
 
 
============================================================
--- libpurple/upnp.c	f9a9b04bf11b70f3c05d402c95dd91087242fe1b
+++ libpurple/upnp.c	662d56d2b1e549d039c1414f8ab4fca00f08507f
@@ -464,7 +464,7 @@ purple_upnp_parse_description(const gcha
 	purple_timeout_remove(dd->tima);
 	dd->tima = 0;
 
-	purple_util_fetch_url_request_len(NULL, 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 @@ purple_upnp_generate_action_message_and_
 	g_free(pathOfControl);
 	g_free(soapMessage);
 
-	gfud = purple_util_fetch_url_request_len(NULL, 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);
============================================================
--- libpurple/stun.c	f22c2ce3d2d7f5c685f889a4602c910ae6e19945
+++ libpurple/stun.c	5d17b53067f34846fab9ae4cd91a234c51d56632
@@ -338,7 +338,7 @@ static void hbn_cb(GSList *hosts, gpoint
 		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 @@ static void do_test1(PurpleSrvResponse *
 	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 @@ PurpleStunNatDiscovery *purple_stun_disc
 	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;
============================================================
--- libpurple/protocols/gg/lib/common.c	07308be3629d7b020ecad9cc87eb006d42802cff
+++ libpurple/protocols/gg/lib/common.c	69a0857e43441368dc3ac61ba1643ad475e8e88c
@@ -24,22 +24,14 @@
  *
  * \brief Funkcje wykorzystywane przez r??ne modu?y biblioteki
  */
-#ifndef _WIN32
-#  include <sys/types.h>
-#  include <sys/ioctl.h>
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  ifdef sun
-#    include <sys/filio.h>
-#  endif
+#include "compat.h"
+#include <sys/types.h>
+#ifdef sun
+#  include <sys/filio.h>
 #endif
 
 #include <errno.h>
 #include <fcntl.h>
-#ifndef _WIN32
-#  include <netdb.h>
-#endif
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -92,7 +84,7 @@ char *gg_vsaprintf(const char *format, v
 			}
 			buf = tmp;
 			res = vsnprintf(buf, size, format, ap);
-		} while (res == size - 1 || res == -1);
+		} while (res >= size - 1 || res == -1);
 	}
 #else
 	{
============================================================
--- libpurple/protocols/gg/lib/compat.h	296e21e553d08f3c02f03d3f68b05fc4e08e519a
+++ libpurple/protocols/gg/lib/compat.h	06c6a58a53a886475f6865a56bd6ee8d8b8aecd1
@@ -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
============================================================
--- libpurple/protocols/gg/lib/dcc.c	50362473e6df324ed3e566c5e72f2d2bc166bf94
+++ libpurple/protocols/gg/lib/dcc.c	d42d9518b54f4b04f84a03e85e509f57fb69e840
@@ -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 gg_event *gg_dcc_watch_fd(struct 
 		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_event *gg_dcc_watch_fd(struct 
 		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 {
============================================================
--- libpurple/protocols/gg/lib/events.c	05da5230649347d4674632763e577b7ae6204075
+++ libpurple/protocols/gg/lib/events.c	ddeb1042e5bf21cd3c886d92fbddf4f7e7339dbb
@@ -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"
============================================================
--- libpurple/protocols/gg/lib/http.c	f9c0de253c74a60682844fc563cb69551f65a16b
+++ libpurple/protocols/gg/lib/http.c	b9ef871cde686b481ba6d57d78d05522d6679cfb
@@ -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 @@ int gg_http_watch_fd(struct gg_http *h)
 	}
 
 	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);
============================================================
--- libpurple/protocols/gg/lib/libgadu-config.h	bb5b8a51459d6647e400380ef06526ab3a75ad8b
+++ libpurple/protocols/gg/lib/libgadu-config.h	6fd391496e380baa14a305ae20686fa0ff39f83c
@@ -8,9 +8,31 @@
 /* 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 */
============================================================
--- libpurple/protocols/gg/lib/libgadu.c	c9d29e6893c4ccaf09a643074b5ee67d14941cb3
+++ libpurple/protocols/gg/lib/libgadu.c	8e5f5be394259b7663c0e0dbf55af293b3d5abc2
@@ -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 @@ void gg_logoff(struct gg_session *sess)
 	sess->resolver_cleanup(&sess->resolver, 1);
 
 	if (sess->fd != -1) {
-		shutdown(sess->fd, SHUT_RDWR);
 		close(sess->fd);
 		sess->fd = -1;
 	}
============================================================
--- libpurple/protocols/gg/lib/libgadu.h	3a16d1d0be02034a431087507866d7df145a5f83
+++ libpurple/protocols/gg/lib/libgadu.h	156dccaab9aae4d3f04bd5e002b78f09237e642b
@@ -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 @@ extern "C" {
 /* 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 @@ extern "C" {
 /* 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 @@ extern "C" {
 #        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 @@ typedef enum {
 	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 *r
 
 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 @@ struct gg_dcc7_dunno1 {
 #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 */
============================================================
--- libpurple/protocols/gg/lib/pubdir.c	ef0f7c330a64ee8eefc1272d76084befc5e6111d
+++ libpurple/protocols/gg/lib/pubdir.c	78b3122f5af432bb7df7cb3fd1eb27077abfefd1
@@ -35,7 +35,6 @@
 #include <unistd.h>
 
 #include "libgadu.h"
-#include "libgadu-config.h"
 
 /**
  * Rejestruje nowego u?ytkownika.
@@ -194,7 +193,7 @@ struct gg_http *gg_unregister3(uin_t uin
 		return NULL;
 	}
     
-	__pwd = gg_saprintf("%ld", random());
+	__pwd = gg_saprintf("%d", rand());
 	__fmpwd = gg_urlencode(password);
 	__tokenid = gg_urlencode(tokenid);
 	__tokenval = gg_urlencode(tokenval);
============================================================
--- libpurple/protocols/gg/lib/pubdir50.c	947ddc5ce92d647a77cbd3d621f5d62125067419
+++ libpurple/protocols/gg/lib/pubdir50.c	ec44588e0c8e9cac3045672349fa6feed6d30f0d
@@ -31,7 +31,6 @@
 #include <time.h>
 
 #include "libgadu.h"
-#include "libgadu-config.h"
 #include "libgadu-internal.h"
 #include "encoding.h"
 
============================================================
--- libpurple/dnssrv.c	01fb6d6cae9c7671c89b1df6a3598159342ba0f9
+++ libpurple/dnssrv.c	e57cc009c50cd3044064ed71b5e7a380219723fc
@@ -725,15 +725,7 @@ PurpleSrvTxtQueryData *
 #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)
 {
@@ -869,13 +861,7 @@ purple_srv_resolve_account(PurpleAccount
 #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)
 {
@@ -1006,18 +992,6 @@ PurpleSrvTxtQueryData *purple_txt_resolv
 #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)
 {
============================================================
--- libpurple/dnssrv.h	d510de4d1637f436682f0cd146c67160e68f0837
+++ libpurple/dnssrv.h	825eeaed2a50a30082cb00795b997d0ee7de808b
@@ -70,7 +70,7 @@ typedef struct
 
 	/** 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);
 
@@ -99,86 +99,40 @@ typedef void (*PurpleTxtCallback)(GList 
 /**
  * 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);
+PurpleSrvTxtQueryData *purple_srv_resolve(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);
-
-/**
  * 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);
+PurpleSrvTxtQueryData *purple_txt_resolve(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);
-
-/**
  * 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);
 
@@ -186,7 +140,6 @@ const gchar *purple_txt_response_get_con
  * Destroy a TXT DNS response object.
  *
  * @param response The PurpleTxtResponse to destroy.
- * @since 2.6.0
  */
 void purple_txt_response_destroy(PurpleTxtResponse *response);
 
@@ -216,7 +169,7 @@ PurpleSrvTxtQueryUiOps *purple_srv_txt_q
 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.
@@ -224,7 +177,7 @@ char *purple_srv_txt_query_get_query(Pur
 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.
@@ -236,3 +189,4 @@ int purple_srv_txt_query_get_type(Purple
 #endif
 
 #endif /* _PURPLE_DNSSRV_H */
+
============================================================
--- libpurple/protocols/gg/buddylist.c	c631da14f7e92be7a74e58f5c63ff61974c5e3a8
+++ libpurple/protocols/gg/buddylist.c	b0646ea0f8f7ba4d741b738c69249bdfcd573c7c
@@ -38,7 +38,7 @@ void ggp_buddylist_send(PurpleConnection
 /* 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;
============================================================
--- libpurple/protocols/gg/confer.c	d565bfce32db3a7dd991bf9aae27e9e1490702c8
+++ libpurple/protocols/gg/confer.c	46308bfd4f8d3d252a835cdd3ab6a7157efe7c72
@@ -42,7 +42,7 @@ void ggp_confer_participants_add_uin(Pur
 							 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(PurpleC
 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_participa
 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(PurpleCon
 /* 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);
============================================================
--- libpurple/protocols/gg/gg.h	174220d8802b40f910662633c10a5312f041bec6
+++ libpurple/protocols/gg/gg.h	4ddeccbabe2125cb49d2c18fe0495056f64d7031
@@ -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 {
 typedef struct {
 
 	struct gg_session *session;
+	guint inpa;
 	GGPToken *token;
 	GList *chats;
 	GGPSearches *searches;
============================================================
--- libpurple/protocols/gg/search.c	4d0b0e6fbc1df100a9295e26ef66b7d670e5bf72
+++ libpurple/protocols/gg/search.c	28effe6d7ddc1f71c1b50a982e0a34457a4b2fca
@@ -135,7 +135,7 @@ guint32 ggp_search_start(PurpleConnectio
 /* 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;
 
============================================================
--- libpurple/protocols/gg/gg-utils.c	eb707940da9b935f2d757dbf03bf4c5f049464d6
+++ libpurple/protocols/gg/gg-utils.c	a3c001533a7e7da874e10db724203989e8832e7d
@@ -143,5 +143,18 @@ void ggp_status_fake_to_self(PurpleAccou
 				    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: */
============================================================
--- libpurple/protocols/gg/gg-utils.h	3c97606755256a643037fcd3f075f9819622b0df
+++ libpurple/protocols/gg/gg-utils.h	4e0e8f4418fc5fdf051ea77dc022c2c70ae30200
@@ -101,6 +101,21 @@ ggp_status_fake_to_self(PurpleAccount *a
 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: */
============================================================
--- libpurple/plugins/log_reader.c	1602ce008ed5b6d27c121e6ffc6c06193273cbbd
+++ libpurple/plugins/log_reader.c	9e44268d47feb41f6f024bb0bbb5c52e6287e7bf
@@ -92,7 +92,7 @@ static GList *adium_logger_list(PurpleLo
 
 	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 @@ static GList *msn_logger_list(PurpleLogT
 	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 @@ static GList *msn_logger_list(PurpleLogT
 			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 @@ static char * msn_logger_read (PurpleLog
 
 		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 @@ static char * msn_logger_read (PurpleLog
 				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 @@ static char * msn_logger_read (PurpleLog
 			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 @@ static GList *qip_logger_list(PurpleLogT
 	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 @@ static GList *qip_logger_list(PurpleLogT
 	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);
@@ -2206,7 +2203,6 @@ static GList *amsn_logger_parse_file(cha
 			log->logger = amsn_logger;
 			log->logger_data = data;
 			list = g_list_prepend(list, log);
-			found_start = FALSE;
 
 			purple_debug_info("aMSN logger",
 			                  "Found log for %s:"
@@ -2241,10 +2237,10 @@ static GList *amsn_logger_list(PurpleLog
 		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);
 
============================================================
--- pidgin/gtkwhiteboard.c	b519e3decb17abc894289605cf46514b6bb40c72
+++ pidgin/gtkwhiteboard.c	15130faa0225d3608af0755d8b9bbc3a1fc00f7d
@@ -125,7 +125,7 @@ static void pidgin_whiteboard_create(Pur
 	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 @@ static void pidgin_whiteboard_create(Pur
 	/* 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,19 +274,19 @@ static void pidgin_whiteboard_destroy(Pu
 	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 */
 
 	/* Clear graphical memory */
-	if(gtkwb->pixbuf)
+	if(gtkwb->pixmap)
 	{
-		cairo_t *cr = g_object_get_data(G_OBJECT(gtkwb->pixbuf), "cairo-context");
+		cairo_t *cr = g_object_get_data(G_OBJECT(gtkwb->pixmap), "cairo-context");
 		if (cr)
 			cairo_destroy(cr);
-		g_object_unref(gtkwb->pixbuf);
-		gtkwb->pixbuf = NULL;
+		g_object_unref(gtkwb->pixmap);
+		gtkwb->pixmap = NULL;
 	}
 
 	colour_dialog = g_object_get_data(G_OBJECT(gtkwb->window), "colour-dialog");
@@ -301,7 +301,7 @@ static void pidgin_whiteboard_destroy(Pu
 		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)
@@ -356,32 +356,28 @@ static gboolean pidgin_whiteboard_config
 static gboolean pidgin_whiteboard_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
 {
 	PidginWhiteboard *gtkwb = (PidginWhiteboard*)data;
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	GdkPixmap *pixmap = gtkwb->pixmap;
 	cairo_t *cr;
-	GdkWindow *window = gtk_widget_get_window(widget);
-	GtkAllocation allocation;
 
-	if (pixbuf) {
-		cr = g_object_get_data(G_OBJECT(pixbuf), "cairo-context");
+	if (pixmap) {
+		cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
 		if (cr)
 			cairo_destroy(cr);
-		g_object_unref(pixbuf);
+		g_object_unref(pixmap);
 	}
 
-	gtk_widget_get_allocation(widget, &allocation);
+	pixmap = gdk_pixmap_new(widget->window,
+							widget->allocation.width,
+							widget->allocation.height,
+							-1);
+	gtkwb->pixmap = pixmap;
 
-	pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
-	    	                FALSE, gdk_visual_get_depth(GDK_VISUAL(window)),
-	    	                allocation.width, allocation.height);
-
-	gtkwb->pixbuf = pixbuf;
-
-	cr = gdk_cairo_create(gtk_widget_get_window(widget));
-	g_object_set_data(G_OBJECT(pixbuf), "cairo-context", cr);
-	gdk_cairo_set_source_color(cr, &gtk_widget_get_style(widget)->white);
+	cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
+	g_object_set_data(G_OBJECT(pixmap), "cairo-context", cr);
+	gdk_cairo_set_source_color(cr, &widget->style->white);
 	cairo_rectangle(cr,
 	                0, 0,
-	                allocation.width, allocation.height);
+	                widget->allocation.width, widget->allocation.height);
 	cairo_fill(cr);
 
 	return TRUE;
@@ -390,11 +386,11 @@ static gboolean pidgin_whiteboard_expose
 static gboolean pidgin_whiteboard_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
 {
 	PidginWhiteboard *gtkwb = (PidginWhiteboard*)(data);
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	GdkPixmap *pixmap = gtkwb->pixmap;
 	cairo_t *cr;
 
-	cr = gdk_cairo_create(gtk_widget_get_window(widget));
-	gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
+	cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
+	gdk_cairo_set_source_pixmap(cr, pixmap, 0, 0);
 	cairo_rectangle(cr,
 	                event->area.x, event->area.y,
 	                event->area.width, event->area.height);
@@ -407,10 +403,10 @@ static gboolean pidgin_whiteboard_brush_
 static gboolean pidgin_whiteboard_brush_down(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
 	PidginWhiteboard *gtkwb = (PidginWhiteboard*)data;
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	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)
 	{
@@ -422,7 +418,7 @@ static gboolean pidgin_whiteboard_brush_
 
 	BrushState = BRUSH_STATE_DOWN;
 
-	if(event->button == 1 && pixbuf != NULL)
+	if(event->button == 1 && pixmap != NULL)
 	{
 		/* Check if draw_list has contents; if so, clear it */
 		if(draw_list)
@@ -445,7 +441,7 @@ static gboolean pidgin_whiteboard_brush_
 											 gtkwb->brush_color, gtkwb->brush_size);
 	}
 
-	wb->draw_list = draw_list;
+	purple_whiteboard_set_draw_list(wb, draw_list);
 
 	return TRUE;
 }
@@ -460,10 +456,10 @@ static gboolean pidgin_whiteboard_brush_
 	GdkModifierType state;
 
 	PidginWhiteboard *gtkwb = (PidginWhiteboard*)data;
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	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);
@@ -474,7 +470,7 @@ static gboolean pidgin_whiteboard_brush_
 		state = event->state;
 	}
 
-	if(state & GDK_BUTTON1_MASK && pixbuf != NULL)
+	if(state & GDK_BUTTON1_MASK && pixmap != NULL)
 	{
 		if((BrushState != BRUSH_STATE_DOWN) && (BrushState != BRUSH_STATE_MOTION))
 		{
@@ -532,7 +528,7 @@ static gboolean pidgin_whiteboard_brush_
 		LastY = y;
 	}
 
-	wb->draw_list = draw_list;
+	purple_whiteboard_set_draw_list(wb, draw_list);
 
 	return TRUE;
 }
@@ -540,10 +536,10 @@ static gboolean pidgin_whiteboard_brush_
 static gboolean pidgin_whiteboard_brush_up(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
 	PidginWhiteboard *gtkwb = (PidginWhiteboard*)data;
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	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))
 	{
@@ -555,7 +551,7 @@ static gboolean pidgin_whiteboard_brush_
 	}
 	BrushState = BRUSH_STATE_UP;
 
-	if(event->button == 1 && pixbuf != NULL)
+	if(event->button == 1 && pixmap != NULL)
 	{
 		/* If the brush was never moved, express two sets of two deltas That's a
 		 * 'point,' but not for Yahoo!
@@ -587,7 +583,7 @@ static gboolean pidgin_whiteboard_brush_
 		if(draw_list)
 			purple_whiteboard_draw_list_destroy(draw_list);
 
-		wb->draw_list = NULL;
+		purple_whiteboard_set_draw_list(wb, NULL);
 	}
 
 	return TRUE;
@@ -595,11 +591,11 @@ static void pidgin_whiteboard_draw_brush
 
 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;
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	GdkPixmap *pixmap = gtkwb->pixmap;
 
-	cairo_t *gfx_con = g_object_get_data(G_OBJECT(pixbuf), "cairo-context");
+	cairo_t *gfx_con = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
 	GdkColor col;
 
 	/* Interpret and convert color */
@@ -688,7 +684,7 @@ static void pidgin_whiteboard_set_dimens
 
 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;
@@ -696,7 +692,7 @@ static void pidgin_whiteboard_set_brush(
 
 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;
@@ -704,25 +700,22 @@ static void pidgin_whiteboard_clear(Purp
 
 static void pidgin_whiteboard_clear(PurpleWhiteboard *wb)
 {
-	PidginWhiteboard *gtkwb = wb->ui_data;
-	GdkPixbuf *pixbuf = gtkwb->pixbuf;
+	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(pixbuf), "cairo-context");
-	GtkAllocation allocation;
+	cairo_t *cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context");
 
-	gtk_widget_get_allocation(drawing_area, &allocation);
-
-	gdk_cairo_set_source_color(cr, &gtk_widget_get_style(drawing_area)->white);
+	gdk_cairo_set_source_color(cr, &drawing_area->style->white);
 	cairo_rectangle(cr,
 	                0, 0,
-	                allocation.width,
-	                allocation.height);
+	                drawing_area->allocation.width,
+	                drawing_area->allocation.height);
 	cairo_fill(cr);
 
 	gtk_widget_queue_draw_area(drawing_area,
 							   0, 0,
-							   allocation.width,
-							   allocation.height);
+							   drawing_area->allocation.width,
+							   drawing_area->allocation.height);
 }
 
 static void pidgin_whiteboard_button_clear_press(GtkWidget *widget, gpointer data)
@@ -788,15 +781,12 @@ static void pidgin_whiteboard_button_sav
 		gtk_widget_destroy(dialog);
 
 		/* Makes an icon from the whiteboard's canvas 'image' */
-		pixbuf = gtkwb->pixbuf;
-/*
 		pixbuf = gdk_pixbuf_get_from_drawable(NULL,
 											  (GdkDrawable*)(gtkwb->pixmap),
 											  gdk_drawable_get_colormap(gtkwb->pixmap),
 											  0, 0,
 											  0, 0,
 											  gtkwb->width, gtkwb->height);
-*/
 
 		if(gdk_pixbuf_save(pixbuf, filename, "jpeg", NULL, "quality", "100", NULL))
 			purple_debug_info("gtkwhiteboard", "File Saved...\n");
@@ -817,15 +807,12 @@ static void pidgin_whiteboard_set_canvas
 	GdkPixbuf *pixbuf;
 
 	/* Makes an icon from the whiteboard's canvas 'image' */
-	pixbuf = gtkwb->pixbuf;
-/*
 	pixbuf = gdk_pixbuf_get_from_drawable(NULL,
 										  (GdkDrawable*)(gtkwb->pixmap),
 										  gdk_drawable_get_colormap(gtkwb->pixmap),
 										  0, 0,
 										  0, 0,
 										  gtkwb->width, gtkwb->height);
-*/
 
 	gtk_window_set_icon((GtkWindow*)(gtkwb->window), pixbuf);
 }
@@ -866,28 +853,23 @@ static void color_select_dialog(GtkWidge
 {
 	GdkColor color;
 	GtkColorSelectionDialog *dialog;
-	GtkWidget *ok_button;
 
 	dialog = (GtkColorSelectionDialog *)gtk_color_selection_dialog_new(_("Select color"));
 	g_object_set_data(G_OBJECT(gtkwb->window), "colour-dialog", dialog);
 
-	g_signal_connect(G_OBJECT(gtk_color_selection_dialog_get_color_selection(dialog)),
-	                 "color-changed", G_CALLBACK(change_color_cb), gtkwb);
+	g_signal_connect(G_OBJECT(dialog->colorsel), "color-changed",
+					G_CALLBACK(change_color_cb), gtkwb);
 
-/*
 	gtk_widget_destroy(dialog->cancel_button);
 	gtk_widget_destroy(dialog->help_button);
-*/
-	g_object_get(G_OBJECT(dialog), "ok-button", &ok_button, NULL);
 
-	g_signal_connect(G_OBJECT(ok_button), "clicked",
+	g_signal_connect(G_OBJECT(dialog->ok_button), "clicked",
 					G_CALLBACK(color_selection_dialog_destroy), gtkwb);
 
-	gtk_color_selection_set_has_palette(GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(dialog)), TRUE);
+	gtk_color_selection_set_has_palette(GTK_COLOR_SELECTION(dialog->colorsel), TRUE);
 
 	pidgin_whiteboard_rgb24_to_rgb48(gtkwb->brush_color, &color);
-	gtk_color_selection_set_current_color(
-		GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(dialog)), &color);
+	gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(dialog->colorsel), &color);
 
 	gtk_widget_show_all(GTK_WIDGET(dialog));
 }
============================================================
--- pidgin/gtkwhiteboard.h	b9af6817b89f3360ad4968b6791040fd18abae9b
+++ pidgin/gtkwhiteboard.h	6cb904c7e3deb11c432b82fa674357d2609befbb
@@ -51,7 +51,7 @@ typedef struct _PidginWhiteboard
 	GtkWidget *window;       /**< Window for the Doodle session */
 	GtkWidget *drawing_area; /**< Drawing area */
 
-	GdkPixbuf *pixbuf;       /**< Memory for drawing area */
+	GdkPixmap *pixmap;       /**< Memory for drawing area */
 
 	int  width;              /**< Canvas width */
 	int  height;             /**< Canvas height */
============================================================
--- libpurple/protocols/yahoo/yahoo_doodle.c	d75e8392b7b33f3ad4a3070f844f6b11bd2f97ff
+++ libpurple/protocols/yahoo/yahoo_doodle.c	09a8b3f663e4e5c90efdcafca3ee9866b5ea410e
@@ -161,7 +161,7 @@ static void yahoo_doodle_command_got_req
 		*/
 
 		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 @@ static void yahoo_doodle_command_got_rea
 	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 @@ static void yahoo_doodle_command_got_rea
 	 * 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 @@ static void yahoo_doodle_command_got_cle
 	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 @@ static void yahoo_doodle_command_got_con
 	/* 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 @@ static void yahoo_doodle_command_got_con
 	}*/
 
 	/* 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 @@ void yahoo_doodle_command_got_shutdown(P
 
 	/* 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 @@ static void yahoo_doodle_command_send_ge
 
 	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 @@ void yahoo_doodle_start(PurpleWhiteboard
 	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(PurpleW
 
 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 Purple
 
 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;
 
============================================================
--- libpurple/whiteboard.c	f0b3552b97ebdb869cdbc32342f6e010028d707e
+++ libpurple/whiteboard.c	7e3b0c8bcbd8959dd9caed16cea8dfced9e0a4af
@@ -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 @@ void purple_whiteboard_destroy(PurpleWhi
 	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 @@ void purple_whiteboard_set_brush(PurpleW
 		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;
+}
============================================================
--- libpurple/whiteboard.h	1c248a7d0309e7c03f3f27e30818ab2f2cd7c4e0
+++ libpurple/whiteboard.h	95273da6e3fcb7cd06a9006d802fe210ed69a232
@@ -26,6 +26,9 @@
 #ifndef _PURPLE_WHITEBOARD_H_
 #define _PURPLE_WHITEBOARD_H_
 
+/** @copydoc _PurpleWhiteboard */
+typedef struct _PurpleWhiteboard PurpleWhiteboard;
+
 /**
  * Whiteboard PRPL Operations
  */
@@ -33,23 +36,7 @@ typedef struct _PurpleWhiteboardPrplOps 
 
 #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(PurpleWhi
 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(PurpleW
  */
 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
============================================================
--- libpurple/protocols/bonjour/bonjour.c	a35cb3fab8c4877f943c31f64fad53a6d95e1bcb
+++ libpurple/protocols/bonjour/bonjour.c	20d08bfffae6d5d3119fb70a405854c8b0e09662
@@ -51,7 +51,7 @@ bonjour_get_jid(PurpleAccount *account)
 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;
 }
 
@@ -102,8 +102,9 @@ bonjour_login(PurpleAccount *account)
 	}
 #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);
@@ -157,7 +158,7 @@ bonjour_close(PurpleConnection *connecti
 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 @@ bonjour_close(PurpleConnection *connecti
 	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 @@ bonjour_send_im(PurpleConnection *connec
 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 @@ bonjour_set_status(PurpleAccount *accoun
 	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 @@ static void
  * 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 @@ bonjour_convo_closed(PurpleConnection *c
 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 @@ void bonjour_set_buddy_icon(PurpleConnec
 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);
 }
 
@@ -436,7 +439,7 @@ bonjour_group_buddy(PurpleConnection *co
 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);
 
@@ -461,7 +464,7 @@ bonjour_can_receive_file(PurpleConnectio
 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);
 }
@@ -481,6 +484,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	sizeof(PurplePluginProtocolInfo),                        /* struct_size */
 	OPT_PROTO_NO_PASSWORD,
 	NULL,                                                    /* user_splits */
 	NULL,                                                    /* protocol_options */
@@ -521,7 +525,6 @@ static PurplePluginProtocolInfo prpl_inf
 	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 */
@@ -546,15 +549,12 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- libpurple/protocols/bonjour/jabber.c	32bccc4ccc1b1d62971ce596dad35325bde4f513
+++ libpurple/protocols/bonjour/jabber.c	21b4f89a5915c1664decd12f486c2452271defc9
@@ -206,7 +206,9 @@ _jabber_parse_and_write_message_to_ui(xm
 						g_string_append_printf(str, " face='%s'", font_face);
 					if (font_size)
 						g_string_append_printf(str, " size='%s'", font_size);
-					if (ichat_text_color)
+					if (font_color)
+						g_string_append_printf(str, " color='%s'", font_color);
+					else if (ichat_text_color)
 						g_string_append_printf(str, " color='%s'", ichat_text_color);
 					if (ichat_balloon_color)
 						g_string_append_printf(str, " back='%s'", ichat_balloon_color);
@@ -665,9 +667,13 @@ _server_socket_handler(gpointer data, in
 
 	/* Look for the buddy that has opened the conversation and fill information */
 #ifdef HAVE_INET_NTOP
-	if (their_addr.ss_family == AF_INET6)
+	if (their_addr.ss_family == AF_INET6) {
 		address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in6 *)&their_addr)->sin6_addr,
 			addrstr, sizeof(addrstr));
+
+		append_iface_if_linklocal(addrstr,
+			((struct sockaddr_in6 *)&their_addr)->sin6_scope_id);
+	}
 	else
 		address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in *)&their_addr)->sin_addr,
 			addrstr, sizeof(addrstr));
@@ -744,7 +750,7 @@ start_serversocket_listening(int port, i
 
 #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 +935,9 @@ bonjour_jabber_conv_match_by_name(Bonjou
 		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 +970,9 @@ bonjour_jabber_conv_match_by_ip(BonjourJ
 
 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 +1132,9 @@ async_bonjour_jabber_close_conversation(
 
 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 +1154,9 @@ bonjour_jabber_close_conversation(Bonjou
 	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 +1170,7 @@ bonjour_jabber_close_conversation(Bonjou
 				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 +1228,7 @@ bonjour_jabber_stop(BonjourJabber *jdata
 		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);
@@ -1442,3 +1455,19 @@ bonjour_jabber_get_local_ips(int fd)
 
 	return ips;
 }
+
+void
+append_iface_if_linklocal(char *ip, guint32 interface_param) {
+	struct in6_addr in6_addr;
+	int len_remain = INET6_ADDRSTRLEN - strlen(ip);
+
+	if (len_remain <= 1)
+		return;
+
+	if (inet_pton(AF_INET6, ip, &in6_addr) != 1 ||
+	    !IN6_IS_ADDR_LINKLOCAL(&in6_addr))
+		return;
+
+	snprintf(ip + strlen(ip), len_remain, "%%%d",
+		 interface_param);
+}
============================================================
--- libpurple/protocols/bonjour/jabber.h	c2277098331059135ab10da92ebe8c3d9ff4f75e
+++ libpurple/protocols/bonjour/jabber.h	da76d25a77cb86d6715411aa34d44a1d7a26547e
@@ -111,4 +111,6 @@ GSList * bonjour_jabber_get_local_ips(in
 int xep_iq_send_and_free(XepIq *iq);
 GSList * bonjour_jabber_get_local_ips(int fd);
 
+void append_iface_if_linklocal(char *ip, guint32 interface_param);
+
 #endif /* _BONJOUR_JABBER_H_ */
============================================================
--- pidgin/gtkthemes.h	50544ee7490c1c79c030e02198b42905a232a706
+++ pidgin/gtkthemes.h	d1facc025da4f4aa42008582aa76ceabea37f855
@@ -29,6 +29,7 @@ struct smiley_list {
 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(GtkWi
 
 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);
============================================================
--- pidgin/gtkmenutray.c	bfcc90a598274cc27b1e4824783ff22f6dc386ae
+++ pidgin/gtkmenutray.c	f07a230cf8c60c93d564b7dc567fd301cda0fe81
@@ -40,11 +40,15 @@ static GObjectClass *parent_class = NULL
  * Internal Stuff
  *****************************************************************************/
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x)
+#endif
+
 /******************************************************************************
  * Item Stuff
  *****************************************************************************/
 static void
-pidgin_menu_tray_select(GtkMenuItem *widget) {
+pidgin_menu_tray_select(GtkItem *item) {
 	/* this may look like nothing, but it's really overriding the
 	 * GtkMenuItem's select function so that it doesn't get highlighted like
 	 * a normal menu item would.
@@ -52,7 +56,7 @@ static void
 }
 
 static void
-pidgin_menu_tray_deselect(GtkMenuItem *widget) {
+pidgin_menu_tray_deselect(GtkItem *item) {
 	/* Probably not necessary, but I'd rather be safe than sorry.  We're
 	 * overridding the select, so it makes sense to override deselect as well.
 	 */
@@ -92,7 +96,9 @@ pidgin_menu_tray_finalize(GObject *obj)
 static void
 pidgin_menu_tray_finalize(GObject *obj)
 {
+#if !GTK_CHECK_VERSION(2,12,0)
 	PidginMenuTray *tray = PIDGIN_MENU_TRAY(obj);
+#endif
 #if 0
 	/* This _might_ be leaking, but I have a sneaking suspicion that the widget is
 	 * getting destroyed in GtkContainer's finalize function.  But if were are
@@ -116,7 +122,7 @@ pidgin_menu_tray_class_init(PidginMenuTr
 static void
 pidgin_menu_tray_class_init(PidginMenuTrayClass *klass) {
 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
-	GtkMenuItemClass *menu_item_class = GTK_MENU_ITEM_CLASS(klass);
+	GtkItemClass *item_class = GTK_ITEM_CLASS(klass);
 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
 	GParamSpec *pspec;
 
@@ -125,8 +131,8 @@ pidgin_menu_tray_class_init(PidginMenuTr
 	object_class->finalize = pidgin_menu_tray_finalize;
 	object_class->get_property = pidgin_menu_tray_get_property;
 
-	menu_item_class->select = pidgin_menu_tray_select;
-	menu_item_class->deselect = pidgin_menu_tray_deselect;
+	item_class->select = pidgin_menu_tray_select;
+	item_class->deselect = pidgin_menu_tray_deselect;
 
 	widget_class->map = pidgin_menu_tray_map;
 
@@ -255,7 +261,7 @@ pidgin_menu_tray_set_tooltip(PidginMenuT
 	 * not on the widget itself.
 	 */
 	if (!gtk_widget_get_has_window(widget))
-		widget = gtk_widget_get_parent(widget);
+		widget = widget->parent;
 
 #if GTK_CHECK_VERSION(2,12,0)
 	gtk_widget_set_tooltip_text(widget, tooltip);
============================================================
--- pidgin/gtkmenutray.h	4f6ecf0373eac5fbce176690307da1d1991f9b00
+++ pidgin/gtkmenutray.h	c9ff16a951d6ad167f148de98e9c5198023d0ad9
@@ -40,9 +40,7 @@ struct _PidginMenuTray {
 struct _PidginMenuTray {
 	GtkMenuItem gparent;					/**< The parent instance */
 	GtkWidget *tray;						/**< The tray */
-#if GTK_CHECK_VERSION(2,12,0)
-	gpointer depr1;
-#else
+#if !GTK_CHECK_VERSION(2,12,0)
 	GtkTooltips *tooltips;					/**< Tooltips */
 #endif
 };
============================================================
--- pidgin/gtkconvwin.h	bd944cd044107ce07238281794597f12b90c8ec7
+++ pidgin/gtkconvwin.h	87c9e1be73f62e4ecd3fa804e9fe93c24b85fe3b
@@ -51,6 +51,7 @@ struct _PidginWindow
 		GtkAction *view_log;
 
 		GtkAction *send_file;
+		GtkAction *get_attention;
 		GtkAction *add_pounce;
 		GtkAction *get_info;
 		GtkAction *invite;
============================================================
--- pidgin/gtkidle.c	5ee034cf18b2f5fd98bdf9d5959c2702aef4dc0c
+++ pidgin/gtkidle.c	685a6d339e4695a7b31b1a58fde43f15584594e4
@@ -108,7 +108,7 @@ pidgin_get_time_idle(void)
 
 	if (has_extension == -1)
 		has_extension = XScreenSaverQueryExtension(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
-                                               &event_base, &error_base);
+		                                           &event_base, &error_base);
 
 	if (has_extension)
 	{
@@ -116,7 +116,7 @@ pidgin_get_time_idle(void)
 			mit_info = XScreenSaverAllocInfo();
 
 		XScreenSaverQueryInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
-                          GDK_ROOT_WINDOW(), mit_info);
+		                      GDK_ROOT_WINDOW(), mit_info);
 		return (mit_info->idle) / 1000;
 	}
 	else
============================================================
--- libpurple/protocols/silc/wb.c	124f1418b551e542510b735c15167d0ed274b23b
+++ libpurple/protocols/silc/wb.c	0ea5ddd0518990f940dd7dfb97c703a12b994864
@@ -105,18 +105,16 @@ PurpleWhiteboard *silcpurple_wb_init(Sil
 
 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) {
+	if (!purple_whiteboard_get_protocol_data(wb)) {
 		wbs = silc_calloc(1, sizeof(*wbs));
 		if (!wbs)
 			return NULL;
@@ -126,7 +124,7 @@ PurpleWhiteboard *silcpurple_wb_init(Sil
 		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 +145,7 @@ PurpleWhiteboard *silcpurple_wb_init_ch(
 	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 +155,7 @@ PurpleWhiteboard *silcpurple_wb_init_ch(
 		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 +166,10 @@ static void
 }
 
 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 +237,15 @@ silcpurple_wb_request_cb(SilcPurpleWbReq
 {
 	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 +263,7 @@ silcpurple_wb_request(SilcClient client,
 	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 +274,7 @@ silcpurple_wb_request(SilcClient client,
 		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 +317,11 @@ void silcpurple_wb_receive(SilcClient cl
 			 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 +331,7 @@ void silcpurple_wb_receive(SilcClient cl
 		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 +344,11 @@ void silcpurple_wb_receive_ch(SilcClient
 			    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 +358,24 @@ void silcpurple_wb_receive_ch(SilcClient
 		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 +430,22 @@ void silcpurple_wb_end(PurpleWhiteboard 
 
 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 +457,14 @@ void silcpurple_wb_get_brush(const Purpl
 
 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 +474,15 @@ void silcpurple_wb_clear(PurpleWhiteboar
 
 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;
============================================================
--- doc/notify-signals.dox	56b19fdb4449654a44a21a4994d3931d5282be65
+++ doc/notify-signals.dox	d554f2e8a4bcf2cab4e2d22b0aac3e61b2d7c42a
@@ -35,7 +35,6 @@ void (*displaying_email_notification)(co
   @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 @@ void (*displaying_emails_notification)(c
   @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
 
 */
============================================================
--- pidgin/gtksession.c	1acaa195f577ffb22ecf1fe101f5601c2c7e3af0
+++ pidgin/gtksession.c	c554eb95f25715403e48c1f6a55457f3f162c492
@@ -349,7 +349,7 @@ pidgin_session_init(gchar *argv0, gchar 
 	free(tmp);
 
 	session_managed = TRUE;
-	gdk_x11_set_sm_client_id(client_id);
+	gdk_set_sm_client_id(client_id);
 
 	tmp = g_get_current_dir();
 	session_set_string(session, SmCurrentDirectory, tmp);
============================================================
--- pidgin/plugins/timestamp_format.c	a022a09afbf06e3ce0e039010572ad07c00427d5
+++ pidgin/plugins/timestamp_format.c	b0110601005e3f55178aacef31208bb8ea8c09b3
@@ -155,9 +155,8 @@ menu_cb(GtkWidget *item, gpointer data)
 	if (!frame)
 		return;
 
-  /* GTK_DIALOG_NO_SEPARATOR seems to be gone in gtk+ 3.0... */
 	dialog = gtk_dialog_new_with_buttons(PIDGIN_ALERT_TITLE, NULL,
-			GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
 			GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
 			NULL);
 	g_signal_connect_after(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), dialog);
============================================================
--- libpurple/protocols/oscar/family_feedbag.c	549c9f2e23193ac28d6b4a2718ae2c0129e7821f
+++ libpurple/protocols/oscar/family_feedbag.c	122332a388a13ffea8eec5ff840bef74da822bab
@@ -661,7 +661,7 @@ static int aim_ssi_sync(OscarData *od)
 			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);
@@ -734,10 +734,37 @@ aim_ssi_freelist(OscarData *od)
 }
 
 /**
- * This "cleans" the ssi list.  It does the following:
- * 1) Makes sure all buddies, permits, and denies have names.
- * 2) Makes sure that all buddies are in a group that exist.
- * 3) Deletes any empty groups
+ * Look up the given TLV type in the item's data.  If the value of
+ * the TLV is not a valid UTF-8 string then use purple_utf8_salvage()
+ * to replace invalid bytes with question marks.
+ */
+static void cleanlist_ensure_utf8_data(struct aim_ssi_item *item, guint16 tlvtype)
+{
+	aim_tlv_t *tlv;
+	gchar *value, *salvaged;
+
+	tlv = aim_tlv_gettlv(item->data, tlvtype, 1);
+	if (tlv && tlv->length && !g_utf8_validate((const gchar *)tlv->value, tlv->length, NULL)) {
+		purple_debug_warning("oscar", "cleanlist found invalid UTF-8 "
+				"for 0x%04hx field of 0x%04hx item with name %s.  "
+				"Attempting to repair.\n",
+				tlvtype, item->type, item->name ? item->name : "(null)");
+		value = g_strndup((const gchar *)tlv->value, tlv->length);
+		salvaged = purple_utf8_salvage(value);
+		g_free(value);
+		if (*salvaged)
+			aim_tlvlist_replace_str(&item->data, tlvtype, salvaged);
+		else
+			aim_tlvlist_remove(&item->data, tlvtype);
+		g_free(salvaged);
+	}
+}
+
+/**
+ * This "cleans" the ssi list.  It does things like:
+ * - Makes sure all buddies, permits, and denies have names
+ * - Makes sure all buddies are in a group that exist
+ * - Makes sure strings are valid UTF-8
  *
  * @param od The oscar odion.
  * @return Return 0 if no errors, otherwise return the error number.
@@ -764,27 +791,40 @@ int aim_ssi_cleanlist(OscarData *od)
 				aim_ssi_del_from_private_list(od, NULL, cur->type);
 		} else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(&od->ssi.local, cur->gid, 0x0000)))) {
 			char *alias = aim_ssi_getalias(&od->ssi.local, NULL, cur->name);
-			aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE);
+			aim_ssi_addbuddy(od, cur->name, _("Buddies"), NULL, alias, NULL, NULL, FALSE);
 			aim_ssi_delbuddy(od, cur->name, NULL);
 			g_free(alias);
 		}
 		cur = next;
 	}
 
-	/* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */
 	cur = od->ssi.local.data;
 	while (cur) {
 		if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY))
 		{
 			struct aim_ssi_item *cur2, *next2;
+
+			/* Make sure there aren't any duplicate permits or denies, or
+			   duplicate buddies within a group */
 			cur2 = cur->next;
 			while (cur2) {
 				next2 = cur2->next;
-				if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!oscar_util_name_compare(cur->name, cur2->name))) {
+				if (cur->type == cur2->type
+						&& cur->gid == cur2->gid
+						&& cur->name
+						&& cur2->name
+						&& !oscar_util_name_compare(cur->name, cur2->name))
+				{
 					aim_ssi_itemlist_del(&od->ssi.local, cur2);
 				}
 				cur2 = next2;
 			}
+
+			/* Make sure alias is valid UTF-8 */
+			cleanlist_ensure_utf8_data(cur, 0x0131);
+
+			/* Make sure comment is valid UTF-8 */
+			cleanlist_ensure_utf8_data(cur, 0x013c);
 		}
 		cur = cur->next;
 	}
@@ -1284,7 +1324,7 @@ static int parsedata(OscarData *od, Flap
 		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 */
@@ -1674,18 +1714,35 @@ static int receiveauthgrant(OscarData *o
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint16 tmp;
-	char *bn, *msg;
+	char *bn, *msg, *tmpstr;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping auth grant SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping auth grant SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
-	/* Read message (null terminated) */
-	if ((tmp = byte_stream_get16(bs)))
+	/* Read message */
+	tmp = byte_stream_get16(bs);
+	if (tmp) {
 		msg = byte_stream_getstr(bs, tmp);
-	else
+		if (!g_utf8_validate(msg, -1, NULL)) {
+			/* Ugh, msg isn't UTF8.  Let's salvage. */
+			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+					"grant from %s\n", bn);
+			tmpstr = purple_utf8_salvage(msg);
+			g_free(msg);
+			msg = tmpstr;
+		}
+	} else
 		msg = NULL;
 
 	/* Unknown */
@@ -1748,18 +1805,35 @@ static int receiveauthrequest(OscarData 
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint16 tmp;
-	char *bn, *msg;
+	char *bn, *msg, *tmpstr;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping auth request SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping auth request SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
-	/* Read message (null terminated) */
-	if ((tmp = byte_stream_get16(bs)))
+	/* Read message */
+	tmp = byte_stream_get16(bs);
+	if (tmp) {
 		msg = byte_stream_getstr(bs, tmp);
-	else
+		if (!g_utf8_validate(msg, -1, NULL)) {
+			/* Ugh, msg isn't UTF8.  Let's salvage. */
+			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+					"request from %s\n", bn);
+			tmpstr = purple_utf8_salvage(msg);
+			g_free(msg);
+			msg = tmpstr;
+		}
+	} else
 		msg = NULL;
 
 	/* Unknown */
@@ -1832,21 +1906,38 @@ static int receiveauthreply(OscarData *o
 	aim_rxcallback_t userfunc;
 	guint16 tmp;
 	guint8 reply;
-	char *bn, *msg;
+	char *bn, *msg, *tmpstr;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping auth reply SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping auth reply SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
 	/* Read reply */
 	reply = byte_stream_get8(bs);
 
-	/* Read message (null terminated) */
-	if ((tmp = byte_stream_get16(bs)))
+	/* Read message */
+	tmp = byte_stream_get16(bs);
+	if (tmp) {
 		msg = byte_stream_getstr(bs, tmp);
-	else
+		if (!g_utf8_validate(msg, -1, NULL)) {
+			/* Ugh, msg isn't UTF8.  Let's salvage. */
+			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+					"reply from %s\n", bn);
+			tmpstr = purple_utf8_salvage(msg);
+			g_free(msg);
+			msg = tmpstr;
+		}
+	} else
 		msg = NULL;
 
 	/* Unknown */
@@ -1872,10 +1963,18 @@ static int receiveadded(OscarData *od, F
 	char *bn;
 
 	/* Read buddy name */
-	if ((tmp = byte_stream_get8(bs)))
-		bn = byte_stream_getstr(bs, tmp);
-	else
-		bn = NULL;
+	tmp = byte_stream_get8(bs);
+	if (!tmp) {
+		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
+				"because username was empty\n");
+		return 0;
+	}
+	bn = byte_stream_getstr(bs, tmp);
+	if (!g_utf8_validate(bn, -1, NULL)) {
+		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
+				"because the username was not valid UTF-8\n");
+		g_free(bn);
+	}
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, bn);
============================================================
--- libpurple/protocols/oscar/family_icbm.c	8db064a7666ce65d7c90012a8c19204c7a6ed03f
+++ libpurple/protocols/oscar/family_icbm.c	d504940a4f2d85146d0e86cfc5f8443dc5a9eb81
@@ -1941,7 +1941,7 @@ int icq_im_xstatus_request(OscarData *od
 
 	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 @@ int icq_relay_xstatus(OscarData *od, con
 	/* 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 @@ int icq_relay_xstatus(OscarData *od, con
 	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);
============================================================
--- libpurple/protocols/oscar/peer.c	815bc7a8ebfe86c526229a62531dabb0b62e4d0e
+++ libpurple/protocols/oscar/peer.c	dcf11f829d74f5904d72185eb6bcc38a922ad3fb
@@ -212,7 +212,7 @@ peer_connection_destroy_cb(gpointer data
 	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) &&
@@ -603,15 +603,11 @@ peer_connection_listen_cb(gpointer data,
 peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	PeerConnection *conn;
-	OscarData *od;
-	PurpleConnection *gc;
 	struct sockaddr addr;
 	socklen_t addrlen = sizeof(addr);
 	int flags;
 
 	conn = data;
-	od = conn->od;
-	gc = od->gc;
 
 	purple_debug_info("oscar", "Accepting connection on listener socket.\n");
 
@@ -842,7 +838,7 @@ peer_connection_trynext(PeerConnection *
 		 */
 		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 +1068,7 @@ peer_connection_got_proposition(OscarDat
 		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);
 
============================================================
--- libpurple/protocols/oscar/flap_connection.c	faceb88102b041b253e299c46dd31331da868003
+++ libpurple/protocols/oscar/flap_connection.c	883bd98c7822462152b9037e567d06f3c8147019
@@ -456,7 +456,7 @@ flap_connection_destroy_cb(gpointer data
 	 * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then
 	 * we should try to request one instead of disconnecting.
 	 */
-	if (!account->disconnecting && ((od->oscar_connections == NULL)
+	if (!purple_account_is_disconnecting(account) && ((od->oscar_connections == NULL)
 			|| (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE))))
 	{
 		/* No more FLAP connections!  Sign off this PurpleConnection! */
@@ -921,7 +921,7 @@ flap_connection_recv(FlapConnection *con
 						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;
============================================================
--- libpurple/protocols/oscar/oft.c	db359a6d029fbd11a74eb0e68bfb1c0732ce6514
+++ libpurple/protocols/oscar/oft.c	1d32bb0a29e25d31fcd543015523056b027c23ef
@@ -362,10 +362,10 @@ start_transfer_when_done_sending_data(gp
 
 	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 @@ peer_oft_recv_frame_done(PeerConnection 
 
 	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 @@ peer_oft_recvcb_init(PurpleXfer *xfer)
 {
 	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 @@ peer_oft_recvcb_end(PurpleXfer *xfer)
 {
 	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 @@ peer_oft_recvcb_ack_recv(PurpleXfer *xfe
 	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)
 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 @@ peer_oft_sendcb_init(PurpleXfer *xfer)
 		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 @@ peer_oft_sendcb_init(PurpleXfer *xfer)
 	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 @@ peer_oft_sendcb_ack(PurpleXfer *xfer, co
 {
 	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 @@ peer_oft_sendcb_ack(PurpleXfer *xfer, co
 	 */
 	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 @@ peer_oft_cb_generic_cancel(PurpleXfer *x
 {
 	PeerConnection *conn;
 
-	conn = xfer->data;
+	conn = purple_xfer_get_protocol_data(xfer);
 
 	if (conn == NULL)
 		return;
============================================================
--- finch/gntblist.c	31b88d14b2571e126fffb572f157242e2553d18d
+++ finch/gntblist.c	108396f3750bc1c3f1b01a1065021ea62f1ac0ef
@@ -169,7 +169,7 @@ static gboolean default_can_add_node(Pur
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		PurpleBuddy *buddy = (PurpleBuddy*)node;
-		FinchBlistNode *fnode = FINCH_GET_DATA(node);
+		FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 		if (!purple_buddy_get_contact(buddy))
 			return FALSE; /* When a new buddy is added and show-offline is set */
 		if (PURPLE_BUDDY_IS_ONLINE(buddy))
@@ -329,11 +329,11 @@ create_finch_blist_node(PurpleBlistNode 
 static FinchBlistNode *
 create_finch_blist_node(PurpleBlistNode *node, gpointer row)
 {
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 	if (!fnode) {
 		fnode = g_new0(FinchBlistNode, 1);
 		fnode->signed_timer = 0;
-		FINCH_SET_DATA(node, fnode);
+		purple_blist_node_set_ui_data(node, fnode);
 	}
 	fnode->row = row;
 	return fnode;
@@ -342,13 +342,13 @@ reset_blist_node_ui_data(PurpleBlistNode
 static void
 reset_blist_node_ui_data(PurpleBlistNode *node)
 {
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 	if (fnode == NULL)
 		return;
 	if (fnode->signed_timer)
 		purple_timeout_remove(fnode->signed_timer);
 	g_free(fnode);
-	FINCH_SET_DATA(node, NULL);
+	purple_blist_node_set_ui_data(node, NULL);
 }
 
 static int
@@ -381,7 +381,7 @@ get_blist_node_flag(PurpleBlistNode *nod
 get_blist_node_flag(PurpleBlistNode *node)
 {
 	GntTextFormatFlags flag = 0;
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 
 	if (ggblist->tagged && g_list_find(ggblist->tagged, node))
 		flag |= GNT_TEXT_FLAG_BOLD;
@@ -390,7 +390,7 @@ get_blist_node_flag(PurpleBlistNode *nod
 		flag |= GNT_TEXT_FLAG_BLINK;
 	else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node)));
-		fnode = FINCH_GET_DATA(node);
+		fnode = purple_blist_node_get_ui_data(node);
 		if (fnode && fnode->signed_timer)
 			flag |= GNT_TEXT_FLAG_BLINK;
 	} else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
@@ -406,7 +406,7 @@ get_blist_node_flag(PurpleBlistNode *nod
 					node = purple_blist_node_get_sibling_next(node)) {
 				PurpleBlistNode *pnode;
 				pnode = purple_contact_get_priority_buddy((PurpleContact*)node);
-				fnode = FINCH_GET_DATA(node);
+				fnode = purple_blist_node_get_ui_data(node);
 				if (fnode && fnode->signed_timer) {
 					flag |= GNT_TEXT_FLAG_BLINK;
 					break;
@@ -433,7 +433,7 @@ is_contact_online(PurpleContact *contact
 	PurpleBlistNode *node;
 	for (node = purple_blist_node_get_first_child(((PurpleBlistNode*)contact)); node;
 			node = purple_blist_node_get_sibling_next(node)) {
-		FinchBlistNode *fnode = FINCH_GET_DATA(node);
+		FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 		if (PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) ||
 				(fnode && fnode->signed_timer))
 			return TRUE;
@@ -465,7 +465,7 @@ add_node(PurpleBlistNode *node, FinchBli
 static void
 add_node(PurpleBlistNode *node, FinchBlist *ggblist)
 {
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 
 	if (!ggblist->manager->can_add_node(node))
@@ -502,7 +502,7 @@ node_remove(PurpleBuddyList *list, Purpl
 	FinchBlist *ggblist = FINCH_GET_DATA(list);
 	PurpleBlistNode *parent;
 
-	if (ggblist == NULL || FINCH_GET_DATA(node) == NULL)
+	if (ggblist == NULL || purple_blist_node_get_ui_data(node) == NULL)
 		return;
 
 	if (PURPLE_BLIST_NODE_IS_GROUP(node) && ggblist->new_group) {
@@ -543,7 +543,7 @@ node_update(PurpleBuddyList *list, Purpl
 	if (ggblist->window == NULL)
 		return;
 
-	if (FINCH_GET_DATA(node)!= NULL) {
+	if (purple_blist_node_get_ui_data(node)!= NULL) {
 		gnt_tree_change_text(GNT_TREE(ggblist->tree), node,
 				0, get_display_name(node));
 		gnt_tree_sort_row(GNT_TREE(ggblist->tree), node);
@@ -560,7 +560,7 @@ node_update(PurpleBuddyList *list, Purpl
 	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
 		add_node(node, FINCH_GET_DATA(list));
 	} else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
-		if (FINCH_GET_DATA(node)== NULL) {
+		if (purple_blist_node_get_ui_data(node)== NULL) {
 			/* The core seems to expect the UI to add the buddies. */
 			for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node))
 				add_node(node, FINCH_GET_DATA(list));
@@ -663,7 +663,7 @@ add_buddy_cb(void *data, PurpleRequestFi
 		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
@@ -839,7 +839,7 @@ add_group_cb(gpointer null, const char *
 
 	/* Select the group */
 	if (ggblist->tree) {
-		FinchBlistNode *fnode = FINCH_GET_DATA((PurpleBlistNode*)grp);
+		FinchBlistNode *fnode = purple_blist_node_get_ui_data((PurpleBlistNode*)grp);
 		if (!fnode)
 			add_node((PurpleBlistNode*)grp, ggblist);
 		gnt_tree_set_selected(GNT_TREE(ggblist->tree), grp);
@@ -887,7 +887,7 @@ add_group(PurpleGroup *group, FinchBlist
 {
 	gpointer parent;
 	PurpleBlistNode *node = (PurpleBlistNode *)group;
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 	parent = ggblist->manager->find_parent((PurpleBlistNode*)group);
 	create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
@@ -960,7 +960,7 @@ add_chat(PurpleChat *chat, FinchBlist *g
 {
 	gpointer parent;
 	PurpleBlistNode *node = (PurpleBlistNode *)chat;
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 	if (!purple_account_is_connected(purple_chat_get_account(chat)))
 		return;
@@ -979,7 +979,7 @@ add_contact(PurpleContact *contact, Finc
 	PurpleBlistNode *node = (PurpleBlistNode*)contact;
 	const char *name;
 
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 
 	name = get_display_name(node);
@@ -1002,7 +1002,7 @@ add_buddy(PurpleBuddy *buddy, FinchBlist
 	PurpleBlistNode *node = (PurpleBlistNode *)buddy;
 	PurpleContact *contact;
 
-	if (FINCH_GET_DATA(node))
+	if (purple_blist_node_get_ui_data(node))
 		return;
 
 	contact = purple_buddy_get_contact(buddy);
@@ -1060,7 +1060,7 @@ selection_activate(GntWidget *widget, Fi
 						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 @@ context_menu_callback(GntMenuItem *item,
 	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 @@ gnt_append_menu_action(GntMenu *menu, Pu
 	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 @@ append_proto_menu(GntMenu *menu, PurpleC
 		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, gpoi
 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, PurpleCh
 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);
@@ -1557,7 +1561,7 @@ finch_blist_remove_node_cb(PurpleBlistNo
 	if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		PurpleContact *c = (PurpleContact*)node;
 		name = purple_contact_get_alias(c);
-		if (c->totalsize > 1)
+		if (purple_contact_get_contact_size(c, TRUE) > 1)
 			sec = _("Removing this contact will also remove all the buddies in the contact");
 	} else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		name = purple_buddy_get_name((PurpleBuddy*)node);
@@ -2541,7 +2545,7 @@ buddy_recent_signed_on_off(gpointer data
 buddy_recent_signed_on_off(gpointer data)
 {
 	PurpleBlistNode *node = data;
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 
 	purple_timeout_remove(fnode->signed_timer);
 	fnode->signed_timer = 0;
@@ -2561,7 +2565,7 @@ buddy_signed_on_off_cb(gpointer data)
 buddy_signed_on_off_cb(gpointer data)
 {
 	PurpleBlistNode *node = data;
-	FinchBlistNode *fnode = FINCH_GET_DATA(node);
+	FinchBlistNode *fnode = purple_blist_node_get_ui_data(node);
 	if (!ggblist || !fnode)
 		return FALSE;
 
============================================================
--- finch/gntblist.h	955404668c012274fdffb147e3903a6b2658bf2b
+++ finch/gntblist.h	22ef3c254006e1fdd5c565bdb9f492e062cd148b
@@ -115,15 +115,12 @@ void finch_blist_set_size(int width, int
  * @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 @@ GntTree * finch_blist_get_tree(void);
  * 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 @@ void finch_blist_install_manager(const F
  * 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 @@ void finch_blist_uninstall_manager(const
  * @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 @@ FinchBlistManager * finch_blist_manager_
  * 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);
 
============================================================
--- libpurple/protocols/msn/contact.c	b4c18ff4aab916791e4dbd4f2424f0a9d6dfac2f
+++ libpurple/protocols/msn/contact.c	ed7cd7de034213cfe5d3334512827ffa86aa1e62
@@ -968,7 +968,7 @@ msn_get_address_cb(MsnSoapMessage *req, 
 	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 @@ msn_add_contact_to_group(MsnSession *ses
 		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);
============================================================
--- libpurple/protocols/msn/oim.c	2a81eabd7aa57fccd6708da34d6b477abd06a967
+++ libpurple/protocols/msn/oim.c	00d90adb900e220d1660adb62c689f4075926769
@@ -695,7 +695,7 @@ msn_oim_report_to_user(MsnOimRecvData *r
 	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 @@ msn_parse_oim_xml(MsnOim *oim, xmlnode *
 
 		/* 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);
 	}
============================================================
--- finch/gntconv.c	311404c18dc02e5c09fecb58d100c6006530cdfa
+++ finch/gntconv.c	bc01c894f215b8eb38cc8797028459561fe0420a
@@ -123,7 +123,7 @@ send_typing_notification(GntWidget *w, F
 			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 @@ send_typing_notification(GntWidget *w, F
 		} 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 @@ update_buddy_typing(PurpleAccount *accou
 		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 @@ buddy_signed_on_off(PurpleBuddy *buddy, 
 	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 @@ account_signed_on_off(PurpleConnection *
 		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 @@ cleared_message_history_cb(PurpleConvers
 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
 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 
 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 @@ create_conv_from_userlist(GntWidget *wid
 
 	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 @@ finch_create_conversation(PurpleConversa
 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 @@ finch_create_conversation(PurpleConversa
 
 	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 @@ finch_create_conversation(PurpleConversa
 
 	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(PurpleConvers
 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 *c
 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 @@ finch_chat_add_users(PurpleConversation 
 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 @@ finch_chat_add_users(PurpleConversation 
 		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 @@ finch_chat_add_users(PurpleConversation 
 	{
 		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(PurpleConversatio
 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 @@ finch_chat_rename_user(PurpleConversatio
 	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(PurpleConversatio
 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 @@ users_command_cb(PurpleConversation *con
 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(Purpl
 
 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(
 
 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));
============================================================
--- finch/gntconv.h	e984893c5c04f0d20fea57943e945c475ce755a6
+++ finch/gntconv.h	810181081f79c10bcb1ca1792013a70b4150a778
@@ -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
============================================================
--- finch/gntaccount.h	e4a988b3aab6dc666a5066f10a6b7f21cd243d30
+++ finch/gntaccount.h	cea3bf330eabc9bca6ed71a42e91866648bbaf37
@@ -59,8 +59,6 @@ void finch_accounts_show_all(void);
  * 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);
 
============================================================
--- finch/gntnotify.c	ca4b536f8cb0e2f5416945986a6722d30f9ddad6
+++ finch/gntnotify.c	38bc1d2f4f71f51d03934d6e27cf6c5522492878
@@ -386,6 +386,7 @@ finch_notify_sr_new_rows(PurpleConnectio
 {
 	GntTree *tree = GNT_TREE(data);
 	GList *o;
+	GntTreeRow *prev = NULL;
 
 	/* XXX: Do I need to empty the tree here? */
 
@@ -393,10 +394,17 @@ finch_notify_sr_new_rows(PurpleConnectio
 	{
 		gnt_tree_add_row_after(GNT_TREE(tree), o->data,
 				gnt_tree_create_row_from_list(GNT_TREE(tree), o->data),
-				NULL, NULL);
+				NULL, prev);
+		prev = o->data;
 	}
 }
 
+static void
+notify_sr_destroy_cb(GntWidget *window, void *data)
+{
+	purple_notify_close(PURPLE_NOTIFY_SEARCHRESULTS, window);
+}
+
 static void *
 finch_notify_searchresults(PurpleConnection *gc, const char *title,
 		const char *primary, const char *secondary,
@@ -429,7 +437,7 @@ finch_notify_searchresults(PurpleConnect
 	for (iter = results->columns; iter; iter = iter->next)
 	{
 		PurpleNotifySearchColumn *column = iter->data;
-		gnt_tree_set_column_title(GNT_TREE(tree), i, column->title);
+		gnt_tree_set_column_title(GNT_TREE(tree), i, purple_notify_searchresult_column_get_title(column));
 
 		if (!purple_notify_searchresult_column_is_visible(column))
 			gnt_tree_set_column_visible(GNT_TREE(tree), i, FALSE);
@@ -481,6 +489,8 @@ finch_notify_searchresults(PurpleConnect
 	}
 
 	gnt_box_add_widget(GNT_BOX(window), box);
+	g_signal_connect(G_OBJECT(tree), "destroy",
+			G_CALLBACK(notify_sr_destroy_cb), NULL);
 
 	finch_notify_sr_new_rows(gc, results, tree);
 
============================================================
--- finch/gntrequest.c	a893723e3f647da31c6da8cf8258f83a2128d423
+++ finch/gntrequest.c	f91ca2c96ce82651ca1aaf6786d67d07b10c889c
@@ -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 @@ request_fields_cb(GntWidget *button, Pur
 				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 @@ request_fields_cb(GntWidget *button, Pur
 				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 @@ request_fields_cb(GntWidget *button, Pur
 				}
 				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 @@ request_fields_cb(GntWidget *button, Pur
 			}
 			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 @@ finch_request_fields(const char *title, 
 
 			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());
============================================================
--- finch/gntrequest.h	01f5edc69f49e248c5f4a35aff0960b31f6b5c20
+++ finch/gntrequest.h	04b61e34de7757f08e3314d3fc5dbed2c2f8c7f7
@@ -63,7 +63,6 @@ void finch_request_save_in_prefs(gpointe
  * @param field   The request field.
  *
  * @return A GntWidget for the request field.
- * @since 2.4.0
  */
 GntWidget *finch_request_field_get_widget(PurpleRequestField *field);
 /*@}*/
============================================================
--- finch/plugins/gntgf.c	fa5f65ff1d57f6c8b481b70d4ba43366b2b5236a
+++ finch/plugins/gntgf.c	ae6752d2b92b048f58f7e075f196bf0510887427
@@ -168,7 +168,7 @@ notify(PurpleConversation *conv, const c
 		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 @@ received_chat_msg(PurpleAccount *account
 	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;
============================================================
--- libpurple/dnsquery.c	ec35993e4ab83e1f41e806c33efeb197196248d8
+++ libpurple/dnsquery.c	9cef1e98757c655be07de54bf86443fa8acc0c19
@@ -297,6 +297,10 @@ purple_dnsquery_resolver_run(int child_o
 		}
 		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 *
 }
 
 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 @@ purple_dnsquery_a_account(PurpleAccount 
 	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)
 {
============================================================
--- libpurple/dnsquery.h	be2134cced69bea1dea731f342425a27e1151037
+++ libpurple/dnsquery.h	9535c9eb1ab6c5e3a391ff5b8d9b148df37e745f
@@ -88,7 +88,7 @@ extern "C" {
 /**
  * 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,29 +98,10 @@ extern "C" {
  *         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);
+PurpleDnsQueryData *purple_dnsquery_a(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
-
-/**
  * Cancel a DNS query and destroy the associated data structure.
  *
  * @param query_data The DNS query to cancel.  This data structure
============================================================
--- pidgin/Makefile.am	d949e7f7c00dac781a6ba44cdc316f80342bb3c9
+++ pidgin/Makefile.am	1873a723b808906764c8056eefb56ac135071035
@@ -34,7 +34,7 @@ pkgconfig_DATA = pidgin-3.pc
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = pidgin-3.pc
 
-SUBDIRS = pixmaps plugins
+SUBDIRS = pixmaps plugins themes
 
 bin_PROGRAMS = pidgin
 
@@ -48,11 +48,12 @@ pidgin_SOURCES = \
 	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 @@ pidgin_SOURCES = \
 	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 @@ pidgin_headers = \
 	gtkconn.h \
 	gtkconv.h \
 	gtkconvwin.h \
+	gtkconv-theme.h \
+	gtkconv-theme-loader.h \
 	gtkdebug.h \
 	gtkdialogs.h \
 	gtkdnd-hints.h \
@@ -134,10 +139,12 @@ pidgin_headers = \
 	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 = \
@@ -149,6 +156,7 @@ pidgin_LDADD = \
 pidgin_LDADD = \
 	@LIBOBJS@ \
 	$(GLIB_LIBS) \
+	$(GCR_LIBS) \
 	$(DBUS_LIBS) \
 	$(GSTREAMER_LIBS) \
 	$(XSS_LIBS) \
@@ -156,6 +164,7 @@ pidgin_LDADD = \
 	$(INTLLIBS) \
 	$(GTKSPELL_LIBS) \
 	$(LIBXML_LIBS) \
+	$(WEBKIT_LIBS) \
 	$(GTK_LIBS) \
 	$(top_builddir)/libpurple/libpurple.la
 
@@ -173,11 +182,14 @@ AM_CPPFLAGS = \
 	-I$(top_builddir) \
 	-I$(top_srcdir) \
 	$(GLIB_CFLAGS) \
+	$(GCR_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GTKSPELL_CFLAGS) \
 	$(LIBXML_CFLAGS) \
+	$(WEBKIT_CFLAGS) \
 	$(INTGG_CFLAGS)
 endif  # ENABLE_GTK
+
============================================================
--- pidgin/plugins/Makefile.am	77880be2c48ed0424818a3a12280a51af34afa69
+++ pidgin/plugins/Makefile.am	63ff22d31146b62ff8dc632e5a80042abeeb5b53
@@ -38,16 +38,14 @@ iconaway_la_LDFLAGS         = -module -a
 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 @@ plugin_LTLIBRARIES = \
 	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 @@ iconaway_la_SOURCES         = iconaway.c
 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 @@ iconaway_la_LIBADD          = $(GTK_LIBS
 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 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
+	$(WEBKIT_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
 	$(PLUGIN_CFLAGS)
 
============================================================
--- pidgin/Makefile.mingw	867b6c76a7ab966075f38718bb81a9ce5308a473
+++ pidgin/Makefile.mingw	4b46bf143fe913244345b28563d3f8adaf5a390f
@@ -58,6 +58,8 @@ PIDGIN_C_SRC =	\
 			gtkcertmgr.c \
 			gtkconn.c \
 			gtkconv.c \
+			gtkconv-theme.c \
+			gtkconv-theme-loader.c \
 			gtkdebug.c \
 			gtkdialogs.c \
 			gtkdnd-hints.c \
@@ -91,12 +93,12 @@ PIDGIN_C_SRC =	\
 			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
============================================================
--- pidgin/plugins/perl/common/GtkIMHtml.xs	1186d55a37259a4db14f8dd09b7552d88285c016
+++ pidgin/plugins/perl/common/GtkIMHtml.xs	2b77481f72eb5b91f2a2461cb27d5da223661d2e
@@ -77,30 +77,10 @@ gtk_imhtml_get_text(imhtml, start, end)
 	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.
-void
 gtk_imhtml_hr_add_to(scale, imhtml, iter)
 	Pidgin::IMHtml::Scalable scale
 	Pidgin::IMHtml imhtml
@@ -323,19 +303,6 @@ PPCODE:
 	}
 	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
 
============================================================
--- pidgin/gtkcellrendererexpander.c	0ca976c7d14e714ed20fc02de86276b7bb9e6d1b
+++ pidgin/gtkcellrendererexpander.c	8251823853d9dead3d8f867585f16f5ec79f8ac3
@@ -44,23 +44,24 @@ static void pidgin_cell_renderer_expande
 static void pidgin_cell_renderer_expander_class_init (PidginCellRendererExpanderClass *class);
 static void pidgin_cell_renderer_expander_get_size   (GtkCellRenderer            *cell,
 						   GtkWidget                  *widget,
-						   const GdkRectangle         *cell_area,
+						   GdkRectangle               *cell_area,
 						   gint                       *x_offset,
 						   gint                       *y_offset,
 						   gint                       *width,
 						   gint                       *height);
 static void pidgin_cell_renderer_expander_render     (GtkCellRenderer            *cell,
-						   cairo_t                  *cr,
+						   GdkWindow                  *window,
 						   GtkWidget                  *widget,
-						   const GdkRectangle               *background_area,
-						   const GdkRectangle               *cell_area,
-						   GtkCellRendererState             flags);
+						   GdkRectangle               *background_area,
+						   GdkRectangle               *cell_area,
+						   GdkRectangle               *expose_area,
+						   guint                       flags);
 static gboolean pidgin_cell_renderer_expander_activate  (GtkCellRenderer            *r,
 						      GdkEvent                   *event,
 						      GtkWidget                  *widget,
 						      const gchar                *p,
-						      const GdkRectangle               *bg,
-						      const GdkRectangle               *cell,
+						      GdkRectangle               *bg,
+						      GdkRectangle               *cell,
 						      GtkCellRendererState        flags);
 static void  pidgin_cell_renderer_expander_finalize (GObject *gobject);
 
@@ -107,10 +108,9 @@ static void pidgin_cell_renderer_expande
 
 static void pidgin_cell_renderer_expander_init (PidginCellRendererExpander *cellexpander)
 {
-  g_object_set(G_OBJECT(cellexpander), "mode",
-               GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
-	/*GTK_CELL_RENDERER(cellexpander)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;*/
-  gtk_cell_renderer_set_padding(GTK_CELL_RENDERER(cellexpander), 0, 2);
+	GTK_CELL_RENDERER(cellexpander)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
+	GTK_CELL_RENDERER(cellexpander)->xpad = 0;
+	GTK_CELL_RENDERER(cellexpander)->ypad = 2;
 }
 
 static void pidgin_cell_renderer_expander_class_init (PidginCellRendererExpanderClass *class)
@@ -190,7 +190,7 @@ static void pidgin_cell_renderer_expande
 
 static void pidgin_cell_renderer_expander_get_size (GtkCellRenderer *cell,
 						 GtkWidget       *widget,
-						 const GdkRectangle    *cell_area,
+						 GdkRectangle    *cell_area,
 						 gint            *x_offset,
 						 gint            *y_offset,
 						 gint            *width,
@@ -199,17 +199,11 @@ static void pidgin_cell_renderer_expande
 	gint calc_width;
 	gint calc_height;
 	gint expander_size;
-  gint xpad;
-  gint ypad;
-  gfloat xalign;
-  gfloat yalign;
-    
+
 	gtk_widget_style_get(widget, "expander-size", &expander_size, NULL);
 
-  gtk_cell_renderer_get_padding(cell, &xpad, &ypad);
-  gtk_cell_renderer_get_alignment(cell, &xalign, &yalign); 
-	calc_width = (gint) xpad * 2 + expander_size;
-	calc_height = (gint) ypad * 2 + expander_size;
+	calc_width = (gint) cell->xpad * 2 + expander_size;
+	calc_height = (gint) cell->ypad * 2 + expander_size;
 
 	if (width)
 		*width = calc_width;
@@ -221,12 +215,12 @@ static void pidgin_cell_renderer_expande
 		{
 			if (x_offset)
 				{
-					*x_offset = xalign * (cell_area->width - calc_width);
+					*x_offset = cell->xalign * (cell_area->width - calc_width);
 					*x_offset = MAX (*x_offset, 0);
 				}
 			if (y_offset)
 				{
-					*y_offset = yalign * (cell_area->height - calc_height);
+					*y_offset = cell->yalign * (cell_area->height - calc_height);
 					*y_offset = MAX (*y_offset, 0);
 				}
 		}
@@ -234,64 +228,61 @@ static void pidgin_cell_renderer_expande
 
 
 static void pidgin_cell_renderer_expander_render(GtkCellRenderer *cell,
-					       cairo_t         *cr,
+					       GdkWindow       *window,
 					       GtkWidget       *widget,
-					       const GdkRectangle    *background_area,
-					       const GdkRectangle    *cell_area,
-					       GtkCellRendererState  flags)
+					       GdkRectangle    *background_area,
+					       GdkRectangle    *cell_area,
+					       GdkRectangle    *expose_area,
+					       guint            flags)
 {
 	PidginCellRendererExpander *cellexpander = (PidginCellRendererExpander *) cell;
 	gboolean set;
 	gint width, height;
 	GtkStateType state;
-  gint xpad;
-  gint ypad;
-  gboolean is_expanded;
-  GtkAllocation allocation;
-    
-  gtk_cell_renderer_get_padding(cell, &xpad, &ypad);
-  g_object_get(G_OBJECT(cell), "is-expanded", &is_expanded, NULL);
-    
+
 	if (!cellexpander->is_expander)
 		return;
 
 	width = cell_area->width;
 	height = cell_area->height;
 
-	if (!gtk_widget_get_sensitive(widget))
+	if (!cell->sensitive)
 		state = GTK_STATE_INSENSITIVE;
 	else if (flags & GTK_CELL_RENDERER_PRELIT)
 		state = GTK_STATE_PRELIGHT;
-	else if (gtk_widget_has_focus(widget) && flags & GTK_CELL_RENDERER_SELECTED)
+#if GTK_CHECK_VERSION(2,18,0)
+	else if (gtk_widget_has_focus (widget) && flags & GTK_CELL_RENDERER_SELECTED)
 		state = GTK_STATE_ACTIVE;
+#else
+	else if (GTK_WIDGET_HAS_FOCUS (widget) && flags & GTK_CELL_RENDERER_SELECTED)
+		state = GTK_STATE_ACTIVE;
+#endif
 	else
 		state = GTK_STATE_NORMAL;
 
-	width -= xpad*2;
-	height -= ypad*2;
+	width -= cell->xpad*2;
+	height -= cell->ypad*2;
 
-	gtk_paint_expander (gtk_widget_get_style(widget),
-			    cr, state,
-			    widget, "treeview",
-			    cell_area->x + xpad + (width / 2),
-			    cell_area->y + ypad + (height / 2),
-			    is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED);
+	gtk_paint_expander (widget->style,
+			    window, state,
+			    NULL, widget, "treeview",
+			    cell_area->x + cell->xpad + (width / 2),
+			    cell_area->y + cell->ypad + (height / 2),
+			    cell->is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED);
 
 	/* only draw the line if the color isn't set - this prevents a bug where the hline appears only under the expander */
 	g_object_get(cellexpander, "cell-background-set", &set, NULL);
-  gtk_widget_get_allocation(widget, &allocation);
-
-  if (is_expanded && !set)
-		gtk_paint_hline (gtk_widget_get_style(widget), cr, state, widget, NULL, 0,
-				 allocation.width, cell_area->y + cell_area->height);
+	if (cell->is_expanded && !set)
+		gtk_paint_hline (widget->style, window, state, NULL, widget, NULL, 0,
+				 widget->allocation.width, cell_area->y + cell_area->height);
 }
 
 static gboolean pidgin_cell_renderer_expander_activate(GtkCellRenderer *r,
 						     GdkEvent *event,
 						     GtkWidget *widget,
 						     const gchar *p,
-						     const GdkRectangle *bg,
-						     const GdkRectangle *cell,
+						     GdkRectangle *bg,
+						     GdkRectangle *cell,
 						     GtkCellRendererState flags)
 {
 	GtkTreePath *path = gtk_tree_path_new_from_string(p);
============================================================
--- pidgin/gtkdocklet.c	a35f928f79f0f2cfd3e6fb64b7f4c8764138abc2
+++ pidgin/gtkdocklet.c	00b80c8a2504c9827dcf8828388aa54d52305f01
@@ -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 visibility_manager = FAL
 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 @@ docklet_blink_icon(gpointer data)
 	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 @@ docklet_update_status(void)
 	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 @@ docklet_update_status(void)
 	}
 
 	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);
+		/* 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);
+		gtk_status_icon_set_tooltip(docklet, tooltip_text->str);
 
-			g_string_free(tooltip_text, TRUE);
-		}
-
+		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 @@ docklet_update_status(void)
 		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,13 @@ docklet_update_status(void)
 		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")
+			&& pending && !connecting && docklet_blinking_timer == 0) {
+			docklet_blinking_timer = g_timeout_add(500, docklet_blink_icon, NULL);
+		}
 	}
 
 	return FALSE; /* for when we're called by the glib idle handler */
@@ -223,7 +272,7 @@ online_account_supports_chat(void)
 
 	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;
@@ -260,7 +309,7 @@ docklet_signed_on_cb(PurpleConnection *g
 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();
@@ -270,7 +319,7 @@ docklet_signed_off_cb(PurpleConnection *
 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();
@@ -282,17 +331,15 @@ docklet_show_pref_changed_cb(const char 
 {
 	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();
@@ -309,14 +356,19 @@ docklet_toggle_mute(GtkWidget *toggle, v
 static void
 docklet_toggle_mute(GtkWidget *toggle, void *data)
 {
-	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute",
-                        gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toggle)));
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", GTK_CHECK_MENU_ITEM(toggle)->active);
 }
 
 static void
+docklet_toggle_blink(GtkWidget *toggle, void *data)
+{
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/blink", GTK_CHECK_MENU_ITEM(toggle)->active);
+}
+
+static void
 docklet_toggle_blist(GtkWidget *toggle, void *data)
 {
-	purple_blist_set_visible(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toggle)));
+	purple_blist_set_visible(GTK_CHECK_MENU_ITEM(toggle)->active);
 }
 
 #ifdef _WIN32
@@ -582,7 +634,7 @@ static void
 
 
 static void
-plugin_act(GtkWidget *widget, PurplePluginAction *pam)
+plugin_act(GtkObject *obj, PurplePluginAction *pam)
 {
 	if (pam && pam->callback)
 		pam->callback(pam);
@@ -663,6 +715,7 @@ docklet_menu(void)
 {
 	static GtkWidget *menu = NULL;
 	GtkWidget *menuitem;
+	GtkMenuPositionFunc pos_func = gtk_status_icon_position_menu;
 
 	if (menu) {
 		gtk_widget_destroy(menu);
@@ -723,6 +776,11 @@ docklet_menu(void)
 	g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_mute), NULL);
 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 
+	menuitem = gtk_check_menu_item_new_with_mnemonic(_("_Blink on New Message"));
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink"));
+	g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_blink), NULL);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
 	pidgin_separator(menu);
 
 	/* add plugin actions */
@@ -733,24 +791,15 @@ docklet_menu(void)
 #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) {
@@ -771,8 +820,8 @@ pidgin_docklet_clicked(int button_type)
 	}
 }
 
-void
-pidgin_docklet_embedded()
+static void
+pidgin_docklet_embedded(void)
 {
 	if (!visibility_manager
 	    && strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) {
@@ -781,11 +830,11 @@ pidgin_docklet_embedded()
 	}
 	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) {
@@ -801,12 +850,183 @@ pidgin_docklet_remove()
 	}
 }
 
-void
-pidgin_docklet_set_ui_ops(struct docklet_ui_ops *ops)
+static gboolean
+docklet_gtk_recreate_cb(gpointer data)
 {
-	ui_ops = ops;
+	docklet_gtk_status_create(TRUE);
+
+	return FALSE;
 }
 
+#ifndef _WIN32
+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 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()
 {
@@ -822,6 +1042,7 @@ pidgin_docklet_init()
 	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);
@@ -829,10 +1050,21 @@ pidgin_docklet_init()
 	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);
 	purple_signal_connect(conn_handle, "signed-off",
@@ -860,6 +1092,7 @@ pidgin_docklet_uninit()
 void
 pidgin_docklet_uninit()
 {
-	if (visible && ui_ops && ui_ops->destroy)
-		ui_ops->destroy();
+	if (visible)
+		docklet_gtk_status_destroy();
 }
+
============================================================
--- finch/plugins/lastlog.c	41065a9a8c4cf003e63eface0094670ea996a996
+++ finch/plugins/lastlog.c	80586774594a10ab75c819027a5210ddea0adb3b
@@ -60,7 +60,7 @@ lastlog_cb(PurpleConversation *conv, con
 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;
============================================================
--- finch/libgnt/gntwm.c	5e12b73be213ecfa364da50260bd8b6df02b8863
+++ finch/libgnt/gntwm.c	b62ec012936d97aa1f1ae69b938963b3f1d01389
@@ -32,7 +32,7 @@
 #define _GNU_SOURCE
 #endif
 
-#if !defined _XOPEN_SOURCE_EXTENDED && (defined(__APPLE__) || defined(__unix__)) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
+#if !defined _XOPEN_SOURCE_EXTENDED && (defined(__APPLE__) || defined(__unix__)) && !defined(__FreeBSD__)
 #define _XOPEN_SOURCE_EXTENDED
 #endif
 
============================================================
--- libpurple/protocols/oscar/libaim.c	d64c47ca2ca9f18c114b3dfe3a40b49b4057dc4b
+++ libpurple/protocols/oscar/libaim.c	515df8c8d042449a3bf49ffe0ac67ca78da8ce82
@@ -29,6 +29,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- libpurple/protocols/oscar/libicq.c	b4abfbb97f9246553ab7160c9b4e32f77695c312
+++ libpurple/protocols/oscar/libicq.c	a5937e015658a7c02ab3caa5e0d38ef41837c087
@@ -38,6 +38,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- pidgin/gtkscrollbook.c	24d3cc3a66c603e9542e96099205d513b385b509
+++ pidgin/gtkscrollbook.c	5afe519462e2fbba27e2f5a8b7104e883f426969
@@ -102,7 +102,7 @@ refresh_scroll_box(PidginScrollBook *scr
 
 	gtk_widget_show_all(GTK_WIDGET(scroll_book));
 	if (count < 1)
-		gtk_widget_hide(scroll_book->hbox);
+		gtk_widget_hide_all(scroll_book->hbox);
 	else {
 		gtk_widget_show_all(scroll_book->hbox);
 		if (count == 1) {
@@ -160,7 +160,7 @@ pidgin_scroll_book_add(GtkContainer *con
 	PidginScrollBook *scroll_book;
 
 	g_return_if_fail(GTK_IS_WIDGET (widget));
-	g_return_if_fail (gtk_widget_get_parent(widget) == NULL);
+	g_return_if_fail (widget->parent == NULL);
 
 	scroll_book = PIDGIN_SCROLL_BOOK(container);
 	scroll_book->children = g_list_append(scroll_book->children, widget);
============================================================
--- libpurple/plugins/autoaccept.c	a6540b7a7d2f48c141737052911b01b5e275b303
+++ libpurple/plugins/autoaccept.c	e334ca7184fb6a9d14510a1639456cb53272d369
@@ -73,10 +73,10 @@ auto_accept_complete_cb(PurpleXfer *xfer
 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 @@ file_recv_request_cb(PurpleXfer *xfer, g
 
     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 @@ file_recv_request_cb(PurpleXfer *xfer, g
 				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 @@ file_recv_request_cb(PurpleXfer *xfer, g
 
 				/* 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 @@ file_recv_request_cb(PurpleXfer *xfer, g
 								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;
 	}
 }
============================================================
--- pidgin/plugins/convcolors.c	4a35b055e622ef72c132329523ee86261e60e049
+++ pidgin/plugins/convcolors.c	84887a693f1ec780fd026113f3beb9f727cef0db
@@ -302,7 +302,7 @@ static void
 }
 
 static void
-disconnect_prefs_callbacks(GtkWidget *widget, gpointer data)
+disconnect_prefs_callbacks(GtkObject *object, gpointer data)
 {
 	PurplePlugin *plugin = (PurplePlugin *)data;
 
@@ -383,7 +383,7 @@ get_config_frame(PurplePlugin *plugin)
 		purple_prefs_connect_callback(plugin, tmp2, enable_toggled, button);
 	}
 
-	g_signal_connect(ret, "destroy", G_CALLBACK(disconnect_prefs_callbacks), plugin);
+	g_signal_connect(GTK_OBJECT(ret), "destroy", G_CALLBACK(disconnect_prefs_callbacks), plugin);
 	frame = pidgin_make_frame(ret, _("General"));
 	pidgin_prefs_checkbox(_("Ignore incoming format"), PREF_IGNORE, frame);
 	pidgin_prefs_checkbox(_("Apply in Chats"), PREF_CHATS, frame);
============================================================
--- pidgin/plugins/markerline.c	d93cc1fdf4a84c30387ee33546e0c3c3a00bfabe
+++ pidgin/plugins/markerline.c	2b60a4254e8361b0fd2e4592f611c7e3befebc6f
@@ -42,7 +42,7 @@ static int
 #define PREF_CHATS      PREF_PREFIX "/chats"
 
 static int
-imhtml_expose_cb(GtkWidget *widget, cairo_t *cr, PidginConversation *gtkconv)
+imhtml_expose_cb(GtkWidget *widget, GdkEventExpose *event, PidginConversation *gtkconv)
 {
 	int y, last_y, offset;
 	GdkRectangle visible_rect;
@@ -51,7 +51,6 @@ imhtml_expose_cb(GtkWidget *widget, cair
 	int pad;
 	PurpleConversation *conv = gtkconv->active_conv;
 	PurpleConversationType type = purple_conversation_get_type(conv);
-	GdkColor red = {0, 0xffff, 0, 0};
 
 	if ((type == PURPLE_CONV_TYPE_CHAT && !purple_prefs_get_bool(PREF_CHATS)) ||
 			(type == PURPLE_CONV_TYPE_IM && !purple_prefs_get_bool(PREF_IMS)))
@@ -77,12 +76,18 @@ imhtml_expose_cb(GtkWidget *widget, cair
 	gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT,
 										0, last_y, 0, &y);
 
-	gdk_cairo_set_source_color(cr, &red);
-	cairo_move_to(cr, 0.0, y + 0.5);
-	cairo_rel_line_to(cr, visible_rect.width, 0.0);
-	cairo_set_line_width(cr, 1.0);
-	cairo_stroke(cr);
+	if (y >= event->area.y)
+	{
+		GdkColor red = {0, 0xffff, 0, 0};
+		cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window));
 
+		gdk_cairo_set_source_color(cr, &red);
+		cairo_move_to(cr, 0.0, y + 0.5);
+		cairo_rel_line_to(cr, visible_rect.width, 0.0);
+		cairo_set_line_width(cr, 1.0);
+		cairo_stroke(cr);
+		cairo_destroy(cr);
+	}
 	return FALSE;
 }
 
@@ -168,7 +173,7 @@ attach_to_gtkconv(PidginConversation *gt
 attach_to_gtkconv(PidginConversation *gtkconv, gpointer null)
 {
 	detach_from_gtkconv(gtkconv, NULL);
-	g_signal_connect(G_OBJECT(gtkconv->imhtml), "draw",
+	g_signal_connect(G_OBJECT(gtkconv->imhtml), "expose_event",
 					 G_CALLBACK(imhtml_expose_cb), gtkconv);
 }
 
============================================================
--- pidgin/plugins/xmppconsole.c	bde255b7faed90449f2d163efbacd41bf40608b7
+++ pidgin/plugins/xmppconsole.c	5edcee15c8656104310dfa945e986c06b578cd00
@@ -190,7 +190,7 @@ static void message_send_cb(GtkWidget *w
 	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);
@@ -274,7 +274,9 @@ static void iq_clicked_cb(GtkWidget *w, 
 							GTK_STOCK_OK,
 							GTK_RESPONSE_ACCEPT,
 							NULL);
-	/* TODO: how to set no separator for GtkDialog in gtk+ 3.0... */
+#if !GTK_CHECK_VERSION(2,22,0)
+	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+#endif
 	gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), 12);
 #if GTK_CHECK_VERSION(2,14,0)
@@ -302,11 +304,11 @@ static void iq_clicked_cb(GtkWidget *w, 
 
 	gtk_size_group_add_widget(sg, label);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	type_combo = gtk_combo_box_text_new();
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "get");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "set");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "result");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "error");
+	type_combo = gtk_combo_box_new_text();
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "get");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "set");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "result");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "error");
 	gtk_combo_box_set_active(GTK_COMBO_BOX(type_combo), 0);
 	gtk_box_pack_start(GTK_BOX(hbox), type_combo, FALSE, FALSE, 0);
 
@@ -325,7 +327,7 @@ static void iq_clicked_cb(GtkWidget *w, 
 				 to && *to ? to : "",
 				 to && *to ? "'" : "",
 				 g_random_int(),
-				 gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(type_combo)));
+				 gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_combo)));
 
 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(console->entry));
 	gtk_text_buffer_set_text(buffer, stanza, -1);
@@ -362,9 +364,9 @@ static void presence_clicked_cb(GtkWidge
 							GTK_STOCK_OK,
 							GTK_RESPONSE_ACCEPT,
 							NULL);
-
-  /* TODO: find a way to specify no separator for a dialog in gtk+ 3 */
-  /*gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);*/
+#if !GTK_CHECK_VERSION(2,22,0)
+	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+#endif
 	gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), 12);
 #if GTK_CHECK_VERSION(2,14,0)
@@ -391,15 +393,15 @@ static void presence_clicked_cb(GtkWidge
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_size_group_add_widget(sg, label);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	type_combo = gtk_combo_box_text_new();
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "default");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "unavailable");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "subscribe");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "unsubscribe");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "subscribed");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "unsubscribed");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "probe");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "error");
+	type_combo = gtk_combo_box_new_text();
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "default");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "unavailable");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "subscribe");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "unsubscribe");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "subscribed");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "unsubscribed");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "probe");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "error");
 	gtk_combo_box_set_active(GTK_COMBO_BOX(type_combo), 0);
 	gtk_box_pack_start(GTK_BOX(hbox), type_combo, FALSE, FALSE, 0);
 
@@ -409,12 +411,12 @@ static void presence_clicked_cb(GtkWidge
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_size_group_add_widget(sg, label);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	show_combo = gtk_combo_box_text_new();
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "default");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "away");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "dnd");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "xa");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "chat");
+	show_combo = gtk_combo_box_new_text();
+	gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "default");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "away");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "dnd");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "xa");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "chat");
 
 	gtk_combo_box_set_active(GTK_COMBO_BOX(show_combo), 0);
 	gtk_box_pack_start(GTK_BOX(hbox), show_combo, FALSE, FALSE, 0);
@@ -452,10 +454,10 @@ static void presence_clicked_cb(GtkWidge
 	}
 
 	to = gtk_entry_get_text(GTK_ENTRY(to_entry));
-	type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(type_combo));
+	type = gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_combo));
 	if (!strcmp(type, "default"))
 		type = "";
-	show = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(show_combo));
+	show = gtk_combo_box_get_active_text(GTK_COMBO_BOX(show_combo));
 	if (!strcmp(show, "default"))
 		show = "";
 	status = gtk_entry_get_text(GTK_ENTRY(status_entry));
@@ -522,8 +524,9 @@ static void message_clicked_cb(GtkWidget
 							GTK_STOCK_OK,
 							GTK_RESPONSE_ACCEPT,
 							NULL);
-  /* TODO: find a way to create a dialog without separtor in gtk+ 3 */
-	/*gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);*/
+#if !GTK_CHECK_VERSION(2,22,0)
+	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
+#endif
 	gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), 12);
 #if GTK_CHECK_VERSION(2,14,0)
@@ -550,12 +553,12 @@ static void message_clicked_cb(GtkWidget
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_size_group_add_widget(sg, label);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	type_combo = gtk_combo_box_text_new();
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "chat");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "headline");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "groupchat");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "normal");
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "error");
+	type_combo = gtk_combo_box_new_text();
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "chat");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "headline");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "groupchat");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "normal");
+	gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "error");
 	gtk_combo_box_set_active(GTK_COMBO_BOX(type_combo), 0);
 	gtk_box_pack_start(GTK_BOX(hbox), type_combo, FALSE, FALSE, 0);
 
@@ -616,8 +619,7 @@ static void message_clicked_cb(GtkWidget
 	                         *to ? to : "",
 	                         *to ? "'" : "",
 	                         g_random_int(),
-	                         gtk_combo_box_text_get_active_text(
-                               GTK_COMBO_BOX_TEXT(type_combo)),
+	                         gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_combo)),
 
 	                         *body ? "<body>" : "",
 	                         *body ? body : "",
@@ -647,8 +649,7 @@ signing_on_cb(PurpleConnection *gc)
 	if (!console)
 		return;
 
-	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(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++;
 
@@ -679,7 +680,7 @@ signed_off_cb(PurpleConnection *gc)
 	if (l == NULL)
 		return;
 
-	gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(console->dropdown), i);
+	gtk_combo_box_remove_text(GTK_COMBO_BOX(console->dropdown), i);
 	console->accounts = g_list_remove(console->accounts, gc);
 	console->count--;
 
@@ -721,7 +722,7 @@ static void
 }
 
 static void
-console_destroy(GtkWidget *window, gpointer nul)
+console_destroy(GtkObject *window, gpointer nul)
 {
 	g_list_free(console->accounts);
 	g_free(console);
@@ -736,13 +737,12 @@ dropdown_changed_cb(GtkComboBox *widget,
 	if (!console)
 		return;
 
-	account =
-      purple_accounts_find(gtk_combo_box_text_get_active_text(
-          GTK_COMBO_BOX_TEXT(console->dropdown)), "prpl-jabber");
-	if (!account || !account->gc)
+	account = purple_accounts_find(gtk_combo_box_get_active_text(GTK_COMBO_BOX(console->dropdown)),
+				    "prpl-jabber");
+	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));
 }
 
@@ -773,13 +773,13 @@ create_console(PurplePluginAction *actio
 	label = gtk_label_new(_("Account: "));
 	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
 	gtk_box_pack_start(GTK_BOX(console->hbox), label, FALSE, FALSE, 0);
-	console->dropdown = gtk_combo_box_text_new();
+	console->dropdown = gtk_combo_box_new_text();
 	for (connections = purple_connections_get_all(); connections; connections = connections->next) {
 		PurpleConnection *gc = connections->data;
 		if (!strcmp(purple_account_get_protocol_id(purple_connection_get_account(gc)), "prpl-jabber")) {
 			console->count++;
 			console->accounts = g_list_append(console->accounts, gc);
-			gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(console->dropdown),
+			gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown),
 						  purple_account_get_username(purple_connection_get_account(gc)));
 			if (!console->gc)
 				console->gc = gc;
@@ -799,14 +799,17 @@ create_console(PurplePluginAction *actio
 
 	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));
 
============================================================
--- libpurple/example/nullclient.c	260f65e0b862614dbd86173377ed47e750175e4d
+++ libpurple/example/nullclient.c	d08cd2c45f3807e12f5404caff3ce030ef9f5c9c
@@ -237,7 +237,7 @@ signed_on(PurpleConnection *gc, gpointer
 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
============================================================
--- finch/gntft.c	ec619869bdf5299326659ca376de5734b5f5195b
+++ finch/gntft.c	8a7d5a0ae86e1044be20a4bbe67ae3848f0d7c87
@@ -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 @@ toggle_clear_finished_cb(GntWidget *w)
 		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 @@ remove_button_cb(GntButton *button)
 {
 	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 @@ finch_xfer_dialog_new(void)
 
 	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 @@ finch_xfer_dialog_add_xfer(PurpleXfer *x
 
 	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 @@ finch_xfer_dialog_remove_xfer(PurpleXfer
 	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 @@ finch_xfer_dialog_cancel_xfer(PurpleXfer
 	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 @@ finch_xfer_dialog_cancel_xfer(PurpleXfer
 
 	update_title_progress();
 
-	if (purple_xfer_is_canceled(xfer))
+	if (purple_xfer_is_cancelled(xfer))
 		status = _("Cancelled");
 	else
 		status = _("Failed");
@@ -416,7 +413,7 @@ finch_xfer_dialog_update_xfer(PurpleXfer
 	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 @@ finch_xfer_new_xfer(PurpleXfer *xfer)
 {
 	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 @@ finch_xfer_destroy(PurpleXfer *xfer)
 {
 	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);
 	}
 }
 
============================================================
--- libpurple/protocols/jabber/libxmpp.c	a8d36f925713b21b21fe5aca4b62c01aaf9c207c
+++ libpurple/protocols/jabber/libxmpp.c	a42def1a81147c14fed99115ecc3d0f5e8dc2ff9
@@ -53,6 +53,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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)
============================================================
--- libpurple/protocols/myspace/myspace.c	221d71caa590465e2d792c9bbd09d8ccfcea99c8
+++ libpurple/protocols/myspace/myspace.c	77afca8df0fb8dc53ecc9dac0e6baaab870afa0d
@@ -254,7 +254,7 @@ msim_send_bm(MsimSession *session, const
 	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,12 +429,10 @@ msim_tooltip_text(PurpleBuddy *buddy, Pu
 	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);
+		MsimSession *session = purple_connection_get_protocol_data(gc);
 
-		session = (MsimSession *)gc->proto_data;
-
 		/* TODO: if (full), do something different? */
 
 		/* TODO: request information? have to figure out how to do
@@ -707,14 +705,14 @@ msim_login_challenge(MsimSession *sessio
 	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 @@ msim_unrecognized(MsimSession *session, 
 	 */
 
 	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);
 	}
@@ -1840,7 +1838,7 @@ msim_error(MsimSession *session, MsimMes
 				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 @@ msim_error(MsimSession *session, MsimMes
 							"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. */
@@ -2022,7 +2020,7 @@ msim_input_cb(gpointer gc_uncasted, gint
 	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) {
@@ -2157,7 +2155,7 @@ msim_connect_cb(gpointer data, gint sour
 	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"),
@@ -2169,8 +2167,7 @@ msim_connect_cb(gpointer data, gint sour
 	}
 
 	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 @@ msim_login(PurpleAccount *acct)
 	int port;
 
 	g_return_if_fail(acct != NULL);
-	g_return_if_fail(acct->username != NULL);
+	g_return_if_fail(purple_account_get_username(acct) != NULL);
 
-	purple_debug_info("msim", "logging in %s\n", acct->username);
+	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
@@ -2259,14 +2256,15 @@ msim_close(PurpleConnection *gc)
 		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;
+	purple_connection_set_protocol_data(gc, NULL);
 
-	if (session->gc->inpa) {
-		purple_input_remove(session->gc->inpa);
+	if (session->inpa) {
+		purple_input_remove(session->inpa);
+		session->inpa = 0;
 	}
 	if (session->fd >= 0) {
 		close(session->fd);
@@ -2304,7 +2302,7 @@ msim_send_im(PurpleConnection *gc, const
 
 	/* '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 @@ msim_send_typing(PurpleConnection *gc, c
 	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 @@ msim_get_info(PurpleConnection *gc, cons
 	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 @@ msim_set_status(PurpleAccount *account, 
 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 @@ msim_set_status(PurpleAccount *account, 
 	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 @@ msim_set_status(PurpleAccount *account, 
 
 	/* 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 @@ msim_set_idle(PurpleConnection *gc, int 
 
 	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 @@ static void
  * 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 @@ msim_add_buddy(PurpleConnection *gc, Pur
 	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 @@ msim_remove_buddy(PurpleConnection *gc, 
 	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 @@ msim_add_deny(PurpleConnection *gc, cons
 	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 @@ msim_rem_deny(PurpleConnection *gc, cons
 	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 @@ static const char *msim_normalize(const 
 		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 @@ msim_send_really_raw(PurpleConnection *g
 	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 @@ static PurplePluginProtocolInfo prpl_inf
  * 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static void msim_import_friends(PurplePl
 	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, con
 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 @@ msim_uri_handler(const gchar *proto, con
 		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
============================================================
--- pidgin/gtksourceundomanager.c	a08addd2080c4dde8aa869d35ffde1ccd18612b5
+++ pidgin/gtksourceundomanager.c	007f324b0f92d080085778fde3be45fc8abb5233
@@ -532,8 +532,7 @@ gtk_source_undo_manager_undo (GtkSourceU
 					um->priv->document,
 					undo_action->action.insert_anchor.pos,
 					undo_action->action.insert_anchor.pos + 1);
-				/* TODO: is this needed in GTK+ 3? */
-				/*gtk_text_child_anchor_set_segment(undo_action->action.insert_anchor.anchor, NULL); XXX: This may be a bug in GTK+ */
+				undo_action->action.insert_anchor.anchor->segment = NULL; /* XXX: This may be a bug in GTK+ */
 				break;
 			default:
 				/* Unknown action type. */
============================================================
--- libpurple/protocols/null/nullprpl.c	05be395e5c95930d2d8baa349ffbb5e724b054b9
+++ libpurple/protocols/null/nullprpl.c	88706b2138257271af530fdb111f5974804b7401
@@ -113,7 +113,7 @@ static void call_if_nullprpl(gpointer da
   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 @@ static void call_chat_func(gpointer data
   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(PurpleConnec
 
 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 @@ static void discover_status(PurpleConnec
         !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(PurpleC
 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 @@ static void nullprpl_input_user_info(Pur
   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(Purple
 
 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);
@@ -260,16 +260,16 @@ static void nullprpl_tooltip_text(Purple
     char *msg = nullprpl_status_text(buddy);
 	/* 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(info, purple_status_get_name(status),
+    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)
 		/* 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(info, _("User info"), user_info);
+        purple_notify_user_info_add_pair_html(info, _("User info"), user_info);
     }
 
   } else {
@@ -287,7 +287,7 @@ static GList *nullprpl_status_types(Purp
   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,
@@ -366,7 +366,7 @@ static void nullprpl_login(PurpleAccount
   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 */
@@ -385,12 +385,12 @@ static void nullprpl_login(PurpleAccount
 
   /* 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);
@@ -401,7 +401,7 @@ static void nullprpl_login(PurpleAccount
   }
 
   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)
@@ -413,7 +413,7 @@ static int nullprpl_send_im(PurpleConnec
 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);
@@ -423,13 +423,13 @@ static int nullprpl_send_im(PurpleConnec
                     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;
   }
@@ -461,7 +461,7 @@ static void nullprpl_set_info(PurpleConn
 
 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) {
@@ -475,10 +475,10 @@ static void notify_typing(PurpleConnecti
 
 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,
@@ -489,7 +489,7 @@ static unsigned int nullprpl_send_typing
 
 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;
@@ -501,7 +501,7 @@ static void nullprpl_get_info(PurpleConn
   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);
@@ -516,7 +516,7 @@ static void nullprpl_get_info(PurpleConn
     body = _("No 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(info, "Info", body);
+  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 */
@@ -529,35 +529,35 @@ static void nullprpl_set_status(PurpleAc
 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);
 
@@ -571,20 +571,20 @@ static void nullprpl_add_buddy(PurpleCon
                                  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);
   }
@@ -594,7 +594,7 @@ static void nullprpl_remove_buddy(Purple
                                   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,
@@ -620,22 +620,22 @@ static void nullprpl_add_permit(PurpleCo
  */
 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) {
@@ -648,9 +648,9 @@ static void joined_chat(PurpleConvChat *
                         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 */
@@ -658,9 +658,9 @@ static void joined_chat(PurpleConvChat *
   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 */
@@ -668,7 +668,7 @@ static void nullprpl_join_chat(PurpleCon
 }
 
 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);
@@ -692,7 +692,7 @@ static void nullprpl_reject_chat(PurpleC
 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.",
@@ -719,9 +719,9 @@ static void nullprpl_chat_invite(PurpleC
 
 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",
@@ -752,9 +752,9 @@ static void left_chat_room(PurpleConvCha
   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 */
   }
 }
@@ -762,7 +762,7 @@ static void nullprpl_chat_leave(PurpleCo
 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);
@@ -789,9 +789,9 @@ static PurpleCmdRet send_whisper(PurpleC
     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);
@@ -813,7 +813,7 @@ static PurpleCmdRet send_whisper(PurpleC
     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;
   }
@@ -821,11 +821,11 @@ static void nullprpl_chat_whisper(Purple
 
 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,
@@ -835,24 +835,24 @@ static void receive_chat_message(PurpleC
 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);
@@ -868,14 +868,14 @@ static void nullprpl_register_user(Purpl
 
 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);
 }
@@ -883,25 +883,25 @@ static void nullprpl_alias_buddy(PurpleC
 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.)
@@ -915,20 +915,20 @@ static void nullprpl_set_buddy_icon(Purp
 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);
@@ -954,7 +954,7 @@ static void nullprpl_set_chat_topic(Purp
     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) ||
@@ -970,8 +970,8 @@ static PurpleRoomlist *nullprpl_roomlist
 }
 
 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;
@@ -994,8 +994,8 @@ static PurpleRoomlist *nullprpl_roomlist
   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))
@@ -1019,14 +1019,17 @@ static void nullprpl_roomlist_cancel(Pur
 }
 
 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... */
@@ -1049,6 +1052,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 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() */
@@ -1097,7 +1101,6 @@ static PurplePluginProtocolInfo prpl_inf
   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 */
@@ -1122,15 +1125,12 @@ static PurplePluginProtocolInfo prpl_inf
   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)
============================================================
--- libpurple/protocols/jabber/usermood.c	8cde198e54f822942f383ebb74f344dd36f8f4b2
+++ libpurple/protocols/jabber/usermood.c	892cc11f7a3655233ee93f88e22ab9f251880681
@@ -155,12 +155,12 @@ static void jabber_mood_cb(JabberStream 
 		   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);
 }
============================================================
--- libpurple/protocols/jabber/usertune.c	b04883371a7f0df857c74d4ad4992a04472ad2ee
+++ libpurple/protocols/jabber/usertune.c	528cb1aad7ef0cab6a91d67731126b9463b1e4d3
@@ -92,7 +92,7 @@ static void jabber_tune_cb(JabberStream 
 	}
 
 	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 @@ static void jabber_tune_cb(JabberStream 
 				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 *g
 
 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");
============================================================
--- libpurple/protocols/jabber/adhoccommands.c	8bd27c2dc8d608e56b0855281ccb40fae88a13f5
+++ libpurple/protocols/jabber/adhoccommands.c	f0e2c0d54cc2898a57b0d885cb89661120ac7997
@@ -228,7 +228,8 @@ void jabber_adhoc_execute_action(PurpleB
 		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 @@ static void jabber_adhoc_server_execute(
 	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);
 	}
============================================================
--- libpurple/protocols/jabber/caps.c	6621a1aa9502eb19a737a7df1576fa81bea6d02b
+++ libpurple/protocols/jabber/caps.c	7df7bbfd5814bc8322feaa0a154dc685f7f017cf
@@ -794,11 +794,11 @@ static GList* jabber_caps_xdata_get_fiel
 
 		for (value = xmlnode_get_child(field, "value"); value; value = xmlnode_get_next_twin(value)) {
 			gchar *val = xmlnode_get_data(value);
-			xdatafield->values = g_list_append(xdatafield->values, val);
+			xdatafield->values = g_list_prepend(xdatafield->values, val);
 		}
 
 		xdatafield->values = g_list_sort(xdatafield->values, (GCompareFunc)strcmp);
-		fields = g_list_append(fields, xdatafield);
+		fields = g_list_prepend(fields, xdatafield);
 	}
 
 	fields = g_list_sort(fields, jabber_caps_xdata_field_compare);
@@ -875,21 +875,24 @@ gchar *jabber_caps_calculate_hash(Jabber
 		g_free(formtype);
 
 		while (fields) {
-			GList *value;
 			JabberDataFormField *field = (JabberDataFormField*)fields->data;
 
 			if (!g_str_equal(field->var, "FORM_TYPE")) {
 				/* Append the "var" attribute */
 				append_escaped_string(context, field->var);
 				/* Append <value/> elements' cdata */
-				for (value = field->values; value; value = value->next) {
-					append_escaped_string(context, value->data);
-					g_free(value->data);
+				while (field->values) {
+					append_escaped_string(context, field->values->data);
+					g_free(field->values->data);
+					field->values = g_list_delete_link(field->values,
+					                                   field->values);
 				}
+			} else {
+				g_list_free_full(field->values, g_free);
 			}
 
 			g_free(field->var);
-			g_list_free(field->values);
+			g_free(field);
 
 			fields = g_list_delete_link(fields, fields);
 		}
@@ -958,7 +961,7 @@ void jabber_caps_broadcast_change()
 		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);
 		}
 	}
 
============================================================
--- libpurple/protocols/bonjour/mdns_common.c	9ac6232226f1774d123022c929729861fb9be9e2
+++ libpurple/protocols/bonjour/mdns_common.c	26d8d9facbb4d7d30d7abfdaa3604c2304ca11d2
@@ -257,7 +257,7 @@ bonjour_dns_sd_set_jid(PurpleAccount *ac
 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
============================================================
--- libpurple/protocols/bonjour/mdns_win32.c	7d80de474b3ebee47a339ff2f77eda76cb8a3f39
+++ libpurple/protocols/bonjour/mdns_win32.c	0a6d6edd38146b4a922d9b1fb4d0d1a654d13a8c
@@ -177,7 +177,7 @@ _mdns_resolve_host_callback(DNSServiceRe
 	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 @@ _mdns_service_browse_callback(DNSService
 
 				/* 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 @@ _mdns_service_browse_callback(DNSService
 					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 @@ _mdns_service_browse_callback(DNSService
 			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);
============================================================
--- libpurple/certificate.c	bbf17e3f3ee5f3296bfd889371f0d0dc54d4c7a6
+++ libpurple/certificate.c	084505c8e55c07db86a7d6ac74b929759762434a
@@ -275,7 +275,7 @@ gboolean
 }
 
 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 @@ purple_certificate_check_signature_chain
 	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)
 {
@@ -505,6 +499,24 @@ purple_certificate_get_times(PurpleCerti
 	return (scheme->get_times)(crt, activation, expiration);
 }
 
+GByteArray *
+purple_certificate_get_der_data(PurpleCertificate *crt)
+{
+	PurpleCertificateScheme *scheme;
+	GByteArray *data;
+
+	g_return_val_if_fail(crt, NULL);
+	g_return_val_if_fail(crt->scheme, NULL);
+
+	scheme = crt->scheme;
+
+	g_return_val_if_fail(scheme->get_der_data, NULL);
+
+	data = (scheme->get_der_data)(crt);
+
+	return data;
+}
+
 gchar *
 purple_certificate_pool_mkpath(PurpleCertificatePool *pool, const gchar *id)
 {
@@ -1622,7 +1634,7 @@ x509_tls_cached_unknown_peer(PurpleCerti
 	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;
============================================================
--- libpurple/certificate.h	ce6122d62967a91f101c7d06ec0febe9910abfee
+++ libpurple/certificate.h	5d633be617de911eac5f7758f1c36c88aa4e835e
@@ -2,7 +2,6 @@
  * @file certificate.h Public-Key Certificate API
  * @ingroup core
  * @see @ref certificate-signals
- * @since 2.2.0
  */
 
 /*
@@ -258,9 +257,17 @@ struct _PurpleCertificateScheme
 	 */
 	GSList * (* import_certificates)(const gchar * filename);
 
+	/**
+	 * Retrieves the certificate data in DER form
+	 *
+	 * @param crt   Certificate instance
+	 * @return Binary DER representation of certificate - must be freed using
+	 *         g_byte_array_free()
+	 */
+	GByteArray * (* get_der_data)(PurpleCertificate *crt);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
 };
 
 /** A set of operations used to provide logic for verifying a Certificate's
@@ -462,33 +469,12 @@ purple_certificate_signed_by(PurpleCerti
  *                   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
@@ -583,6 +569,17 @@ purple_certificate_get_times(PurpleCerti
 gboolean
 purple_certificate_get_times(PurpleCertificate *crt, time_t *activation, time_t *expiration);
 
+/**
+ * Retrieves the certificate data in DER form.
+ *
+ * @param crt Certificate instance
+ *
+ * @return Binary DER representation of the certificate - must be freed using
+ *         g_byte_array_free().
+ */
+GByteArray *
+purple_certificate_get_der_data(PurpleCertificate *crt);
+
 /*@}*/
 
 /*****************************************************************************/
============================================================
--- pidgin/gtkcertmgr.c	ea9690460570023612e9de6678a46c3ca480820c
+++ pidgin/gtkcertmgr.c	602d3840590d2f5907757b9b24235487fd601dc5
@@ -40,6 +40,12 @@
 
 #include "gtkcertmgr.h"
 
+#ifdef ENABLE_GCR
+#define GCR_API_SUBJECT_TO_CHANGE
+#include <gcr/gcr.h>
+#include <gcr/gcr-simple-certificate.h>
+#endif
+
 /*****************************************************************************
  * X.509 tls_peers management interface                                      *
  *****************************************************************************/
@@ -310,6 +316,13 @@ tls_peers_mgmt_info_cb(GtkWidget *button
 	GtkTreeModel *model;
 	gchar *id;
 	PurpleCertificate *crt;
+#ifdef ENABLE_GCR
+	GByteArray *der;
+	GcrCertificate *gcrt;
+	char *title;
+	GtkWidget *dialog;
+	GcrCertificateBasicsWidget *cert_widget;
+#endif
 
 	/* See if things are selected */
 	if (!gtk_tree_selection_get_selected(select, &model, &iter)) {
@@ -325,14 +338,47 @@ tls_peers_mgmt_info_cb(GtkWidget *button
 	crt = purple_certificate_pool_retrieve(tpm_dat->tls_peers, id);
 	g_return_if_fail(crt);
 
+#ifdef ENABLE_GCR
+	der = purple_certificate_get_der_data(crt);
+	g_return_if_fail(der);
+
+	gcrt = gcr_simple_certificate_new(der->data, der->len);
+	g_return_if_fail(gcrt);
+
 	/* Fire the notification */
+	title = g_strdup_printf(_("Certificate Information for %s"), id);
+	dialog = gtk_dialog_new_with_buttons(title,
+	                                     NULL,
+	                                     0,
+	                                     GTK_STOCK_OK,
+	                                     GTK_RESPONSE_ACCEPT,
+	                                     NULL);
+	cert_widget = gcr_certificate_basics_widget_new(gcrt);
+	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
+	                   GTK_WIDGET(cert_widget), TRUE, TRUE, 0);
+	g_signal_connect_swapped(dialog, "response",
+	                         G_CALLBACK(gtk_widget_destroy),
+	                         dialog);
+	gtk_widget_show_all(dialog);
+
+	g_byte_array_free(der, TRUE);
+	g_object_unref(G_OBJECT(gcrt));
+#else
+	/* Fire the notification */
 	purple_certificate_display_x509(crt);
 
 	g_free(id);
 	purple_certificate_destroy(crt);
+#endif
 }
 
 static void
+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 +498,9 @@ tls_peers_mgmt_build(void)
 	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 +520,8 @@ tls_peers_mgmt_build(void)
 	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 +529,8 @@ tls_peers_mgmt_build(void)
 
 
 	/* 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",
============================================================
--- finch/gntsound.c	3d4aef18aa8413deea3a48c86ecbe6997ee63dce
+++ finch/gntsound.c	9bc4a9c5977622aef9c1a24215cdf71610d9a849
@@ -150,7 +150,7 @@ chat_nick_matches_name(PurpleConversatio
 		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 @@ chat_msg_received_cb(PurpleAccount *acco
 	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);
============================================================
--- finch/gntsound.h	7d3300e8cab7cee5e69fa501b56e380a1128df8e
+++ finch/gntsound.h	9abfe9f3d48afe3e40d461187867a68f9f7765e4
@@ -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 @@ const char *finch_sound_get_active_profi
  * 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 @@ void finch_sound_set_active_profile(cons
  *
  * @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 @@ GList *finch_sound_get_profiles(void);
  *
  * @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 @@ gboolean finch_sound_is_enabled(void);
  * 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);
 
============================================================
--- libpurple/protocols/yahoo/yahoo_aliases.c	6712e727d06848af814aa979d4cca5bcc2e09580
+++ libpurple/protocols/yahoo/yahoo_aliases.c	e35d62c46291e5b99d8f934ce38cb8cfc83722d2
@@ -74,7 +74,7 @@ yahoo_fetch_aliases_cb(PurpleUtilFetchUr
 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 @@ yahoo_fetch_aliases(PurpleConnection *gc
 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 @@ yahoo_fetch_aliases(PurpleConnection *gc
 				  webaddress);
 
 	/* We have a URL and some header information, let's connect and get some aliases  */
-	url_data = purple_util_fetch_url_request_len(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 @@ yahoo_update_alias_cb(PurpleUtilFetchUrl
 	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 @@ yahoo_update_alias(PurpleConnection *gc,
 		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 @@ yahoo_update_alias(PurpleConnection *gc,
 			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 @@ yahoo_update_alias(PurpleConnection *gc,
 			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 @@ yahoo_update_alias(PurpleConnection *gc,
 			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 @@ yahoo_update_alias(PurpleConnection *gc,
 			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 @@ yahoo_update_alias(PurpleConnection *gc,
 				  content);
 
 	/* We have a URL and some header information, let's connect and update the alias  */
-	url_data = purple_util_fetch_url_request_len(
+	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 @@ yahoo_set_userinfo_cb(PurpleConnection *
 	}
 #endif
 
-	url_data = purple_util_fetch_url_request_len(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)
============================================================
--- libpurple/protocols/bonjour/mdns_avahi.c	7da97ca06c35f9dc1dc1e5b106a7dad3ea2fc107
+++ libpurple/protocols/bonjour/mdns_avahi.c	abe85b854321a0a4ba8ff4addc8975b288a1b85b
@@ -179,6 +179,9 @@ _resolver_callback(AvahiServiceResolver 
 			ip[0] = '\0';
 			avahi_address_snprint(ip, AVAHI_ADDRESS_STR_MAX, a);
 
+			if (protocol == AVAHI_PROTO_INET6)
+				append_iface_if_linklocal(ip, interface);
+
 			purple_debug_info("bonjour", "_resolve_callback - name:%s ip:%s prev_ip:%s\n",
 				name, ip, rd->ip);
 
@@ -190,7 +193,7 @@ _resolver_callback(AvahiServiceResolver 
 				}
 				/* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */
 				if (protocol == AVAHI_PROTO_INET6) {
-					rd->ip = g_strdup_printf("%s%%%d", ip, interface);
+					rd->ip = g_strdup_printf("%s", ip);
 					bb->ips = g_slist_prepend(bb->ips, (gchar *) rd->ip);
 				} else {
 					rd->ip = g_strdup(ip);
@@ -615,7 +618,7 @@ void _mdns_retrieve_buddy_icon(BonjourBu
 
 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;
============================================================
--- libpurple/protocols/myspace/session.h	b6fd056e7c512e5210fac889456be2e2e7b84d3a
+++ libpurple/protocols/myspace/session.h	26ef1d78d5e8f0242dd02b316fcaa6530155a95d
@@ -38,6 +38,7 @@ typedef struct _MsimSession
 	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 */
============================================================
--- libpurple/protocols/myspace/zap.c	619464474f8424bd70787c8d0040c58905051546
+++ libpurple/protocols/myspace/zap.c	38bff3f6d6b192c92648ce6e48160dea92ae3504
@@ -132,10 +132,10 @@ msim_send_attention(PurpleConnection *gc
 	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 @@ msim_send_zap_from_menu(PurpleBlistNode 
 	/* 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);
 
============================================================
--- libpurple/protocols/myspace/user.c	94ed54c3d0cfff30e4bbee1cf2482495502081f2
+++ libpurple/protocols/myspace/user.c	e8100e06127c6137a749a7df4bfea7e5bc8cb7fa
@@ -384,7 +384,7 @@ msim_store_user_info_each(const gchar *k
 		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 */
@@ -412,7 +412,7 @@ msim_store_user_info_each(const gchar *k
  *
  * @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
@@ -758,7 +758,7 @@ static void msim_set_username_confirmed_
 
 	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),
@@ -851,7 +851,7 @@ static void msim_check_username_availabi
 
 	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);
 
============================================================
--- libpurple/media.h	446b57c35eaabf153e8b0ac42e01a3fbe83b0c45
+++ libpurple/media.h	0916e8525a5d2247daab3763459179a7e78ca2fb
@@ -57,8 +57,6 @@ extern "C" {
  * 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 @@ GType purple_media_get_type(void);
  * @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 @@ GList *purple_media_get_session_ids(Purp
  * @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 @@ PurpleAccount *purple_media_get_account(
  * @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 @@ gpointer purple_media_get_prpl_data(Purp
  *
  * @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 @@ void purple_media_set_prpl_data(PurpleMe
  * @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 @@ void purple_media_error(PurpleMedia *med
  * @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 @@ void purple_media_end(PurpleMedia *media
  * @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 @@ void purple_media_stream_info(PurpleMedi
  * @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 @@ void purple_media_set_params(PurpleMedia
  * @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 @@ const gchar **purple_media_get_available
  * @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 @@ gboolean purple_media_param_is_supported
  * @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 @@ gboolean purple_media_add_stream(PurpleM
  * @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 @@ PurpleMediaSessionType purple_media_get_
  * @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 @@ struct _PurpleMediaManager *purple_media
  * @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 @@ GList *purple_media_get_codecs(PurpleMed
  * @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 @@ void purple_media_add_remote_candidates(
  * @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 @@ GList *purple_media_get_local_candidates
  *                    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 @@ GList *purple_media_get_active_local_can
  *                    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 @@ GList *purple_media_get_active_remote_ca
  * @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 @@ gboolean purple_media_set_remote_codecs(
  * @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 @@ gboolean purple_media_candidates_prepare
  * @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 @@ gboolean purple_media_set_send_codec(Pur
  * @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 @@ gboolean purple_media_codecs_ready(Purpl
  * @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 @@ gboolean purple_media_is_initiator(Purpl
  * @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 @@ gboolean purple_media_accepted(PurpleMed
  * @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 @@ void purple_media_set_input_volume(Purpl
  * @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 @@ void purple_media_set_output_volume(Purp
  * @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 @@ gulong purple_media_set_output_window(Pu
  * 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);
 
============================================================
--- libpurple/mediamanager.h	dbc11bf0e2a89793ecbecaa713acd3d4ffaea9e1
+++ libpurple/mediamanager.h	0a60e6949deb5ed3ecf5a0925b83cc9b172ebd13
@@ -60,8 +60,6 @@ extern "C" {
  * 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 @@ GType purple_media_manager_get_type(void
  * 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 @@ PurpleMediaManager *purple_media_manager
  * @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 @@ PurpleMedia *purple_media_manager_create
  * @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 @@ GList *purple_media_manager_get_media(Pu
  * @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 @@ GList *purple_media_manager_get_media_by
  *
  * @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 @@ purple_media_manager_remove_media(Purple
  * @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 @@ gboolean purple_media_manager_create_out
  * @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 @@ gulong purple_media_manager_set_output_w
  * @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 @@ gboolean purple_media_manager_remove_out
  * @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 @@ void purple_media_manager_remove_output_
  *
  * @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 @@ void purple_media_manager_set_ui_caps(Pu
  * @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 @@ PurpleMediaCaps purple_media_manager_get
  *
  * @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 @@ void purple_media_manager_set_backend_ty
  * @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);
 
============================================================
--- pidgin/gtkmedia.c	de642f2258baebda2a20c75d47ed06f7e042036c
+++ pidgin/gtkmedia.c	324d93b426c8972d27307a8cc7a9e1d231df3ad2
@@ -40,6 +40,8 @@
 
 #ifdef _WIN32
 #include <gdk/gdkwin32.h>
+#elif defined(GDK_WINDOWING_QUARTZ)
+#include <gdk/gdkquartz.h>
 #endif
 
 #include <gst/interfaces/xoverlay.h>
@@ -290,14 +292,14 @@ setup_menubar(PidginMedia *window)
 	GtkWidget *menu;
 
 	action_group = gtk_action_group_new("MediaActions");
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(action_group,
+	                                        PACKAGE);
+#endif
 	gtk_action_group_add_actions(action_group,
 	                             menu_entries,
 	                             G_N_ELEMENTS(menu_entries),
 	                             GTK_WINDOW(window));
-#ifdef ENABLE_NLS
-	gtk_action_group_set_translation_domain(action_group,
-	                                        PACKAGE);
-#endif
 
 	window->priv->ui = gtk_ui_manager_new();
 	gtk_ui_manager_insert_action_group(window->priv->ui, action_group, 0);
@@ -455,7 +457,7 @@ level_message_cb(PurpleMedia *media, gch
 		progress = pidgin_media_get_widget(gtkmedia, session_id, participant);
 
 	if (progress)
-		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level * 5);
+		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level);
 }
 
 
@@ -559,7 +561,9 @@ realize_cb_cb(PidginMediaRealizeData *da
 #ifdef _WIN32
 		window_id = GDK_WINDOW_HWND(window);
 #elif defined(HAVE_X11)
-		window_id = gdk_x11_window_get_xid(window);
+		window_id = GDK_WINDOW_XWINDOW(window);
+#elif defined(GDK_WINDOWING_QUARTZ)
+		window_id = (gulong) gdk_quartz_window_get_nsview(window);
 #else
 #		error "Unsupported windowing system"
 #endif
@@ -789,7 +793,7 @@ pidgin_media_ready_cb(PurpleMedia *media
 
 		/* Hold button */
 		gtkmedia->priv->hold =
-				gtk_toggle_button_new_with_mnemonic("_Hold");
+				gtk_toggle_button_new_with_mnemonic(_("_Hold"));
 		gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->hold,
 				FALSE, FALSE, 0);
 		gtk_widget_show(gtkmedia->priv->hold);
@@ -878,7 +882,7 @@ pidgin_media_ready_cb(PurpleMedia *media
 
 	if (type & PURPLE_MEDIA_SEND_AUDIO) {
 		gtkmedia->priv->mute =
-				gtk_toggle_button_new_with_mnemonic("_Mute");
+				gtk_toggle_button_new_with_mnemonic(_("_Mute"));
 		gtk_box_pack_end(GTK_BOX(button_widget), gtkmedia->priv->mute,
 				FALSE, FALSE, 0);
 		gtk_widget_show(gtkmedia->priv->mute);
@@ -969,7 +973,7 @@ pidgin_media_stream_info_cb(PurpleMedia 
 		pidgin_media_set_state(gtkmedia, PIDGIN_MEDIA_ACCEPTED);
 		pidgin_media_emit_message(gtkmedia, _("Call in progress."));
 		gtk_statusbar_push(GTK_STATUSBAR(gtkmedia->priv->statusbar),
-				0, _("Call in progress."));
+				0, _("Call in progress"));
 		gtk_widget_show(GTK_WIDGET(gtkmedia));
 	}
 }
@@ -1082,6 +1086,10 @@ create_default_video_src(PurpleMedia *me
 		src = gst_element_factory_make("dshowvideosrc", NULL);
 	if (src == NULL)
 		src = gst_element_factory_make("autovideosrc", NULL);
+#elif defined(__APPLE__)
+	src = gst_element_factory_make("osxvideosrc", NULL);
+	if (src == NULL)
+		src = gst_element_factory_make("autovideosrc", NULL);
 #else
 	src = gst_element_factory_make("gconfvideosrc", NULL);
 	if (src == NULL)
@@ -1136,6 +1144,8 @@ create_default_audio_src(PurpleMedia *me
 		src = gst_element_factory_make("osssrc", NULL);
 	if (src == NULL)
 		src = gst_element_factory_make("dshowaudiosrc", NULL);
+	if (src == NULL)
+		src = gst_element_factory_make("osxaudiosrc", NULL);
 	if (src == NULL) {
 		purple_debug_error("gtkmedia", "Unable to find a suitable "
 				"element for the default audio source.\n");
============================================================
--- pidgin/plugins/gevolution/gevo-util.c	ff52dd1bfe12040161e43eb3a8272b9b1018d989
+++ pidgin/plugins/gevolution/gevo-util.c	aa6ffb95da3a8aff5ece6d68d1dea81ae62d5513
@@ -49,7 +49,7 @@ gevo_add_buddy(PurpleAccount *account, c
 		purple_blist_add_buddy(buddy, NULL, group, NULL);
 	}
 
-	purple_account_add_buddy(account, buddy);
+	purple_account_add_buddy(account, buddy, NULL);
 
 	if (conv != NULL)
 	{
============================================================
--- libpurple/purple.h.in	5fa4dbee8684be3ea40b66dc3a3695979a2b967e
+++ libpurple/purple.h.in	ac688dd051b90c18b5b50184a15cc81ab5b067a3
@@ -6,7 +6,6 @@
  * include any other libpurple files.
  *
  * @ingroup core libpurple
- * @since 2.3.0
  */
 
 /* purple
============================================================
--- pidgin/minidialog.c	d2a1cb82d9f84ed1b346e10a2e634061d27f8712
+++ pidgin/minidialog.c	25df03b2f3f0c96122312096e55480391960a750
@@ -184,7 +184,7 @@ pidgin_mini_dialog_get_num_children(Pidg
 guint
 pidgin_mini_dialog_get_num_children(PidginMiniDialog *mini_dialog)
 {
-	return g_list_length(gtk_container_get_children(GTK_CONTAINER(mini_dialog->contents)));
+	return g_list_length(mini_dialog->contents->children);
 }
 
 static gboolean
============================================================
--- libpurple/protocols/bonjour/bonjour_ft.c	32fa3fc9eaffd055c9bf7faee6d2f643cbd28349
+++ libpurple/protocols/bonjour/bonjour_ft.c	64c2e3c77a0e5f80fcb86bdcb2beb77e0862e82d
@@ -38,7 +38,7 @@ bonjour_xfer_receive(PurpleConnection *p
 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(
 
 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 @@ static void bonjour_xfer_end(PurpleXfer 
 	 * 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 @@ bonjour_si_xfer_find(BonjourData *bd, co
 		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 @@ xep_ft_si_offer(PurpleXfer *xfer, const 
 {
 	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 @@ xep_ft_si_offer(PurpleXfer *xfer, const 
 
 	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
 }
 
 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 @@ xep_ft_si_result(PurpleXfer *xfer, char 
 
 	if(!to || !xfer)
 		return;
-	xf = xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 	if(!xf)
 		return;
 
@@ -290,14 +290,14 @@ bonjour_free_xfer(PurpleXfer *xfer)
 		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 @@ bonjour_free_xfer(PurpleXfer *xfer)
 		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 @@ bonjour_new_xfer(PurpleConnection *gc, c
 		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 @@ bonjour_xfer_init(PurpleXfer *xfer)
 	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 @@ bonjour_xfer_init(PurpleXfer *xfer)
 	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 @@ xep_si_parse(PurpleConnection *pc, xmlno
 	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;
 
@@ -426,83 +427,178 @@ xep_si_parse(PurpleConnection *pc, xmlno
 
 	type = xmlnode_get_attrib(packet, "type");
 	id = xmlnode_get_attrib(packet, "id");
-	if(type) {
-		if(!strcmp(type, "set")) {
-			const char *profile;
-			xmlnode *si;
-			gboolean parsed_receive = FALSE;
+	if(!type)
+		return;
 
-			si = xmlnode_get_child(packet, "si");
+	if(!strcmp(type, "set")) {
+		const char *profile;
+		xmlnode *si;
+		gboolean parsed_receive = FALSE;
 
-			purple_debug_info("bonjour", "si offer Message type - SET.\n");
-			if (si && (profile = xmlnode_get_attrib(si, "profile"))
-					&& !strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) {
-				const char *filename = NULL, *filesize_str = NULL;
-				int filesize = 0;
-				xmlnode *file;
+		si = xmlnode_get_child(packet, "si");
 
-				const char *sid = xmlnode_get_attrib(si, "id");
+		purple_debug_info("bonjour", "si offer Message type - SET.\n");
+		if (si && (profile = xmlnode_get_attrib(si, "profile"))
+				&& !strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) {
+			const char *filename = NULL, *filesize_str = NULL;
+			int filesize = 0;
+			xmlnode *file;
 
-				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);
-				}
+			const char *sid = xmlnode_get_attrib(si, "id");
 
-				/* TODO: Make sure that it is advertising a bytestreams transfer */
+			if ((file = xmlnode_get_child(si, "file"))) {
+				filename = xmlnode_get_attrib(file, "name");
+				if((filesize_str = xmlnode_get_attrib(file, "size")))
+					filesize = atoi(filesize_str);
+			}
 
-				if (filename) {
-					bonjour_xfer_receive(pc, id, sid, name, filesize, filename, XEP_BYTESTREAMS);
+			/* TODO: Make sure that it is advertising a bytestreams transfer */
 
-					parsed_receive = TRUE;
-				}
+			if (filename) {
+				bonjour_xfer_receive(pc, id, sid, name, filesize, filename, XEP_BYTESTREAMS);
+
+				parsed_receive = TRUE;
 			}
+		}
 
-			if (!parsed_receive) {
-				BonjourData *bd = purple_connection_get_protocol_data(pc);
+		if (!parsed_receive) {
+			BonjourData *bd = purple_connection_get_protocol_data(pc);
 
-				purple_debug_info("bonjour", "rejecting unrecognized si SET offer.\n");
-				xep_ft_si_reject(bd, id, name, "403", "cancel");
-				/*TODO: Send Cancel (501) */
-			}
-		} else if(!strcmp(type, "result")) {
-			purple_debug_info("bonjour", "si offer Message type - RESULT.\n");
+			purple_debug_info("bonjour", "rejecting unrecognized si SET offer.\n");
+			xep_ft_si_reject(bd, id, name, "403", "cancel");
+			/*TODO: Send Cancel (501) */
+		}
+	} else if(!strcmp(type, "result")) {
+		purple_debug_info("bonjour", "si offer Message type - RESULT.\n");
 
-			xfer = bonjour_si_xfer_find(bd, id, name);
+		xfer = bonjour_si_xfer_find(bd, id, name);
 
-			if(xfer == NULL) {
-				BonjourData *bd = purple_connection_get_protocol_data(pc);
-				purple_debug_info("bonjour", "xfer find fail.\n");
-				xep_ft_si_reject(bd, id, name, "403", "cancel");
-			} else
-				bonjour_bytestreams_init(xfer);
+		if(xfer == NULL) {
+			BonjourData *bd = purple_connection_get_protocol_data(pc);
+			purple_debug_info("bonjour", "xfer find fail.\n");
+			xep_ft_si_reject(bd, id, name, "403", "cancel");
+		} else
+			bonjour_bytestreams_init(xfer);
 
-		} else if(!strcmp(type, "error")) {
-			purple_debug_info("bonjour", "si offer Message type - ERROR.\n");
+	} else if(!strcmp(type, "error")) {
+		purple_debug_info("bonjour", "si offer Message type - ERROR.\n");
 
-			xfer = bonjour_si_xfer_find(bd, id, name);
+		xfer = bonjour_si_xfer_find(bd, id, name);
 
-			if(xfer == NULL)
-				purple_debug_info("bonjour", "xfer find fail.\n");
-			else
-				purple_xfer_cancel_remote(xfer);
-		} else
-			purple_debug_info("bonjour", "si offer Message type - Unknown-%s.\n", type);
+		if(xfer == NULL)
+			purple_debug_info("bonjour", "xfer find fail.\n");
+		else
+			purple_xfer_cancel_remote(xfer);
+	} else
+		purple_debug_info("bonjour", "si offer Message type - Unknown-%s.\n", type);
+}
+
+/**
+ * Will compare a host with a buddy_ip.
+ *
+ * Additionally to a common '!strcmp(host, buddy_ip)', it will also return TRUE
+ * if 'host' is a link local IPv6 address without an appended interface
+ * identifier and 'buddy_ip' string is "host" + "%iface".
+ *
+ * Note: This may theoretically result in the attempt to connect to the wrong
+ * host, because we do not know for sure which interface the according link
+ * local IPv6 address might relate to and RFC4862 for instance only ensures the
+ * uniqueness of this address on a given link. So we could possibly have two
+ * distinct buddies with the same ipv6 link local address on two distinct
+ * interfaces. Unfortunately XEP-0065 does not seem to specify how to deal with
+ * link local ip addresses properly...
+ * However, in practice the possiblity for such a conflict is relatively low
+ * (2011 - might be different in the future though?).
+ *
+ * @param host		ipv4 or ipv6 address string
+ * @param buddy_ip	ipv4 or ipv6 address string
+ * @return		TRUE if they match, FALSE otherwise
+ */
+static gboolean
+xep_cmp_addr(const char *host, const char *buddy_ip)
+{
+#if defined(AF_INET6) && defined(HAVE_GETADDRINFO)
+	struct addrinfo hint, *res = NULL;
+	int ret;
+
+	memset(&hint, 0, sizeof(hint));
+	hint.ai_family = AF_UNSPEC;
+	hint.ai_flags = AI_NUMERICHOST;
+
+	ret = getaddrinfo(host, NULL, &hint, &res);
+	if(ret)
+		goto out;
+
+	if(res->ai_family != AF_INET6 ||
+	   !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
+		freeaddrinfo(res);
+		goto out;
 	}
+	freeaddrinfo(res);
+
+	if(strlen(buddy_ip) <= strlen(host) ||
+	   buddy_ip[strlen(host)] != '%')
+		return FALSE;
+
+	return !strncmp(host, buddy_ip, strlen(host));
+
+out:
+#endif
+	return !strcmp(host, buddy_ip);
 }
 
+static gboolean
+__xep_bytestreams_parse(PurpleBuddy *pb, PurpleXfer *xfer, xmlnode *query,
+			const char *iq_id)
+{
+	const char *jid, *host, *port;
+	int portnum;
+	xmlnode *streamhost;
+	XepXfer *xf = purple_xfer_get_protocol_data(xfer);
+
+	for(streamhost = xmlnode_get_child(query, "streamhost");
+			streamhost;
+			streamhost = xmlnode_get_next_twin(streamhost)) {
+
+		if(!(jid = xmlnode_get_attrib(streamhost, "jid")) ||
+		   !(host = xmlnode_get_attrib(streamhost, "host")) ||
+		   !(port = xmlnode_get_attrib(streamhost, "port")) ||
+		   !(portnum = atoi(port))) {
+			purple_debug_info("bonjour", "bytestream offer Message parse error.\n");
+			continue;
+		}
+
+		if(!xep_cmp_addr(host, xf->buddy_ip))
+			continue;
+
+		g_free(xf->iq_id);
+		xf->iq_id = g_strdup(iq_id);
+		xf->jid = g_strdup(jid);
+		xf->proxy_host = g_strdup(xf->buddy_ip);
+		xf->proxy_port = portnum;
+		purple_debug_info("bonjour", "bytestream offer parse"
+				  "jid=%s host=%s port=%d.\n", jid, host, portnum);
+		bonjour_bytestreams_connect(xfer, pb);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
 void
 xep_bytestreams_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb)
 {
-	const char *type, *from;
+	const char *type, *from, *iq_id, *sid;
 	xmlnode *query;
 	BonjourData *bd;
+	PurpleXfer *xfer;
 
 	g_return_if_fail(pc != NULL);
 	g_return_if_fail(packet != NULL);
 	g_return_if_fail(pb != NULL);
 
-	bd = (BonjourData*) pc->proto_data;
+	bd = purple_connection_get_protocol_data(pc);
 	if(bd == NULL)
 		return;
 
@@ -511,71 +607,32 @@ xep_bytestreams_parse(PurpleConnection *
 	type = xmlnode_get_attrib(packet, "type");
 	from = purple_buddy_get_name(pb);
 	query = xmlnode_get_child(packet,"query");
-	if(type) {
-		if(!strcmp(type, "set")) {
-			const char *iq_id, *sid;
-			gboolean found = FALSE;
-			PurpleXfer *xfer;
+	if(!type)
+		return;
 
-			purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");
+	if(strcmp(type, "set")) {
+		purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
+		return;
+	}
 
-			iq_id = xmlnode_get_attrib(packet, "id");
+	purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");
 
-			sid = xmlnode_get_attrib(query, "sid");
-			xfer = bonjour_si_xfer_find(bd, sid, from);
+	iq_id = xmlnode_get_attrib(packet, "id");
 
-			if(xfer) {
-				const char *jid, *host, *port;
-				xmlnode *streamhost;
-				int portnum;
-				XepXfer *xf = NULL;
+	sid = xmlnode_get_attrib(query, "sid");
+	xfer = bonjour_si_xfer_find(bd, sid, from);
+	if(xfer && __xep_bytestreams_parse(pb, xfer, query, iq_id))
+		return; /* success */
 
-				xf = (XepXfer*)xfer->data;
-				for(streamhost = xmlnode_get_child(query, "streamhost");
-						streamhost;
-						streamhost = xmlnode_get_next_twin(streamhost)) {
+	purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
 
-					if((jid = xmlnode_get_attrib(streamhost, "jid")) &&
-					   (host = xmlnode_get_attrib(streamhost, "host")) &&
-					   (port = xmlnode_get_attrib(streamhost, "port")) &&
-					   (portnum = atoi(port))) {
-
-						if(!strcmp(host, xf->buddy_ip)) {
-							g_free(xf->iq_id);
-							xf->iq_id = g_strdup(iq_id);
-							xf->jid = g_strdup(jid);
-							xf->proxy_host = g_strdup(host);
-							xf->proxy_port = portnum;
-							purple_debug_info("bonjour", "bytestream offer parse"
-									  "jid=%s host=%s port=%d.\n", jid, host, portnum);
-							bonjour_bytestreams_connect(xfer, pb);
-							found = TRUE;
-							break;
-						}
-					} else {
-						purple_debug_info("bonjour", "bytestream offer Message parse error.\n");
-					}
-				}
-			} else {
-
-			}
-
-			if (!found) {
-				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");
-			}
-
-		} else {
-			purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type);
-		}
-	}
+	if (iq_id && xfer != NULL)
+		xep_ft_si_reject(bd, iq_id, xfer->who, "404", "cancel");
 }
 
 static void
 bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from,
-		     const int filesize, const char *filename, int option)
+		     const goffset filesize, const char *filename, int option)
 {
 	PurpleXfer *xfer;
 	XepXfer *xf;
@@ -584,15 +641,16 @@ bonjour_xfer_receive(PurpleConnection *p
 	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 +672,7 @@ bonjour_sock5_request_cb(gpointer data, 
 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 +690,6 @@ bonjour_sock5_request_cb(gpointer data, 
 			/* 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 +704,26 @@ bonjour_sock5_request_cb(gpointer data, 
 			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 +736,13 @@ bonjour_sock5_request_cb(gpointer data, 
 		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 +751,9 @@ bonjour_sock5_request_cb(gpointer data, 
 		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 +772,12 @@ bonjour_sock5_request_cb(gpointer data, 
 		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 +806,25 @@ bonjour_bytestreams_listen(int sock, gpo
 		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 +846,10 @@ bonjour_bytestreams_init(PurpleXfer *xfe
 		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 +860,7 @@ bonjour_bytestreams_connect_cb(gpointer 
 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 +870,7 @@ bonjour_bytestreams_connect_cb(gpointer 
 	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 +883,7 @@ bonjour_bytestreams_connect_cb(gpointer 
 	/* 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 +909,7 @@ bonjour_bytestreams_connect(PurpleXfer *
 
 	purple_debug_info("bonjour", "bonjour-bytestreams-connect.\n");
 
-	xf = (XepXfer*)xfer->data;
+	xf = purple_xfer_get_protocol_data(xfer);
 	if(!xf)
 		return;
 
@@ -891,7 +938,7 @@ bonjour_bytestreams_connect(PurpleXfer *
 							   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);
 	}
============================================================
--- pidgin/pidgintooltip.c	181fc572e4abbc04b2105ab4ef547487632ae19c
+++ pidgin/pidgintooltip.c	72c61132854e8efb3f1d0c9327d128649941d258
@@ -101,16 +101,11 @@ static gboolean
 }
 
 static gboolean
-pidgin_tooltip_draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data)
+pidgin_tooltip_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
 {
-	GtkAllocation allocation;
-
-	gtk_widget_get_allocation(widget, &allocation);
-
 	if (pidgin_tooltip.paint_tooltip) {
-		gtk_paint_flat_box(gtk_widget_get_style(widget), cr,
-			GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-			widget, "tooltip", 0, 0, allocation.width, allocation.height);
+		gtk_paint_flat_box(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+				NULL, widget, "tooltip", 0, 0, -1, -1);
 		pidgin_tooltip.paint_tooltip(widget, data);
 	}
 	return FALSE;
@@ -194,8 +189,8 @@ setup_tooltip_window_position(gpointer d
 	gtk_window_move(GTK_WINDOW(tipwindow), x, y);
 	gtk_widget_show(tipwindow);
 
-	g_signal_connect(G_OBJECT(tipwindow), "draw",
-			G_CALLBACK(pidgin_tooltip_draw_cb), data);
+	g_signal_connect(G_OBJECT(tipwindow), "expose_event",
+			G_CALLBACK(pidgin_tooltip_expose_event), data);
 
 	/* Hide the tooltip when the widget is destroyed */
 	sig = g_signal_connect(G_OBJECT(pidgin_tooltip.widget), "destroy", G_CALLBACK(pidgin_tooltip_destroy), NULL);
============================================================
--- pidgin/pidgintooltip.h	3848e49f3e0492c1fa7863d756b506db6045b263
+++ pidgin/pidgintooltip.h	180f1bf22356c60435f0999091dc5fc47367d071
@@ -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 @@ typedef gboolean (*PidginTooltipCreateFo
  * @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 @@ typedef gboolean (*PidginTooltipCreate)(
  * @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 @@ typedef gboolean (*PidginTooltipPaint)(G
  * @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 @@ gboolean pidgin_tooltip_setup_for_treevi
  * @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 @@ void pidgin_tooltip_destroy(void);
  * @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);
============================================================
--- finch/gntroomlist.c	0eccbc6c4217925daa79267b56fe88f1eca588ae
+++ finch/gntroomlist.c	910f5627995c2f8d7034de115d38e3ef4a714078
@@ -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 @@ roomlist_activated(GntWidget *widget)
 			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 @@ fl_create(PurpleRoomlist *list)
 static void
 fl_create(PurpleRoomlist *list)
 {
-	FINCH_SET_DATA(list, &froomlist);
+	purple_roomlist_set_ui_data(list, &froomlist);
 	setup_roomlist(NULL);
 	update_roomlist(list);
 }
============================================================
--- finch/plugins/grouping.c	979625bb2b146dc972de28aac70f1b7e6ab0f1e0
+++ finch/plugins/grouping.c	3c36b74b7ffb1115158c9c4e4ee86e0d548a3ca9
@@ -54,7 +54,7 @@ static gboolean on_offline_can_add_node(
 		case PURPLE_BLIST_CONTACT_NODE:
 			{
 				PurpleContact *contact = (PurpleContact*)node;
-				if (contact->currentsize > 0)
+				if (purple_contact_get_contact_size(contact, FALSE) > 0)
 					return TRUE;
 				return FALSE;
 			}
============================================================
--- libpurple/smiley.h	2f37c7d0c8c3ceecc9980095592c58e01e93f093
+++ libpurple/smiley.h	aed301f685799b3255c89bdde291c2545065af0d
@@ -1,7 +1,6 @@
 /**
  * @file smiley.h Smiley API
  * @ingroup core
- * @since 2.5.0
  */
 
 /* purple
============================================================
--- pidgin/gtksmiley.c	b2f43863165cb6bbf8dcc72decfdd2bf7b7831a0
+++ pidgin/gtksmiley.c	2ac2e46e2106abc9c009d83a3d4a3c4d5c6dc70c
@@ -47,9 +47,9 @@ struct _PidginSmiley
 	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
@@ -399,7 +399,7 @@ pidgin_smiley_edit(GtkWidget *widget, Pu
 
 	window = gtk_dialog_new_with_buttons(smiley ? _("Edit Smiley") : _("Add Smiley"),
 			widget ? GTK_WINDOW(widget) : NULL,
-			GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
 			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 			smiley ? GTK_STOCK_SAVE : GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
 			NULL);
@@ -414,8 +414,7 @@ pidgin_smiley_edit(GtkWidget *widget, Pu
 
 	/* The vbox */
 	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(window))),
-                    vbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), vbox);
 	gtk_widget_show(vbox);
 
 	/* The hbox */
@@ -725,10 +724,9 @@ smiley_dnd_recv(GtkWidget *widget, GdkDr
 		GtkSelectionData *sd, guint info, guint t, gpointer user_data)
 {
 	SmileyManager *dialog = user_data;
-	gchar *name = g_strchomp((gchar *) gtk_selection_data_get_data(sd));
-    
-	if ((gtk_selection_data_get_length(sd) >= 0)
-      && (gtk_selection_data_get_format(sd) == 8)) {
+	gchar *name = g_strchomp((gchar *)sd->data);
+
+	if ((sd->length >= 0) && (sd->format == 8)) {
 		/* Well, it looks like the drag event was cool.
 		 * Let's do something with it */
 
@@ -752,7 +750,7 @@ smiley_dnd_recv(GtkWidget *widget, GdkDr
 		} 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);
@@ -761,7 +759,7 @@ smiley_dnd_recv(GtkWidget *widget, GdkDr
 			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);
 		}
 
@@ -884,8 +882,7 @@ void pidgin_smiley_manager_show(void)
 
 	/* The vbox */
 	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(win))),
-                    vbox);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win)->vbox), vbox);
 	gtk_widget_show(vbox);
 
 	/* get the scrolled window with all stuff */
============================================================
--- pidgin/gtksmiley.h	a733b639804437d392214410941f0ccf96064c7d
+++ pidgin/gtksmiley.h	cef7b37434fbb6898210da12aa7295b5f790660f
@@ -1,7 +1,6 @@
 /**
  * @file gtksmiley.h GTK+ Custom Smiley API
  * @ingroup pidgin
- * @since 2.5.0
  */
 
 /* pidgin
@@ -106,8 +105,6 @@ void pidgin_smiley_editor_set_image(Pidg
  * @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);
 
============================================================
--- libpurple/protocols/jabber/jingle/jingle.c	185980c698f1c26bad6f0f8a23e866c0645ea1d9
+++ libpurple/protocols/jabber/jingle/jingle.c	2933cb6d81371155c69a5a4f97b6b3bf09aa5aa5
@@ -126,7 +126,7 @@ jingle_handle_content_modify(JingleSessi
 		if (local_content != NULL) {
 			const gchar *senders = xmlnode_get_attrib(content, "senders");
 			gchar *local_senders = jingle_content_get_senders(local_content);
-			if (strcmp(senders, local_senders))
+			if (!purple_strequal(senders, local_senders))
 				jingle_content_modify(local_content, senders);
 			g_free(local_senders);
 		} else {
============================================================
--- libpurple/theme.c	562727889d220926e36d1282c0ae82e921a4dc2a
+++ libpurple/theme.c	19bf04d61cf3caebb06c9f00976ae7deb1c4fbc7
@@ -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
 }
 
 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 @@ purple_theme_class_init(PurpleThemeClass
 
 	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 @@ purple_theme_get_type(void)
 			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,
============================================================
--- libpurple/theme.h	5b185ced6cfecfcf6a5c7b59d346add4c85833a8
+++ libpurple/theme.h	f19f99fbbca849b3ed39f56209104eef9255f132
@@ -49,7 +49,6 @@ struct _PurpleTheme
 struct _PurpleTheme
 {
 	GObject parent;
-	gpointer priv;
 };
 
 struct _PurpleThemeClass
============================================================
--- libpurple/theme-loader.c	d640ec7a4cfc5b9b5e06e75e2a30554967d7aaee
+++ libpurple/theme-loader.c	2d3bb6af1b849f019ff0921b3e9b0ec42f1463ae
@@ -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
 }
 
 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 @@ purple_theme_loader_class_init(PurpleThe
 
 	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 @@ purple_theme_loader_get_type(void)
 			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,
============================================================
--- libpurple/theme-loader.h	bbb30ed76a7b4a55a568e6364ac48ecac3fc6c62
+++ libpurple/theme-loader.h	eb80046e3c0c90a69f86f073bdfe6841a14cf654
@@ -50,7 +50,6 @@ struct _PurpleThemeLoader
 struct _PurpleThemeLoader
 {
 	GObject parent;
-	gpointer priv;
 };
 
 struct _PurpleThemeLoaderClass
============================================================
--- libpurple/sound-theme.c	832cad835b20e8d5bcd36e680644b90ef67f7cc0
+++ libpurple/sound-theme.c	843b91c36cf336bd74ee0bdbf13c3778eeb90ab3
@@ -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 @@ purple_sound_theme_init(GTypeInstance *i
 {
 	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 @@ purple_sound_theme_class_init(PurpleSoun
 
 	parent_class = g_type_class_peek_parent(klass);
 
+	g_type_class_add_private(klass, sizeof(PurpleSoundThemePrivate));
+
 	obj_class->finalize = purple_sound_theme_finalize;
 }
 
============================================================
--- libpurple/sound-theme.h	d6e1850e4cd92ead2ac39ab8dca7ce6874f4bb60
+++ libpurple/sound-theme.h	6caadf8daa0a32eaef6fc9db533e5c02ec48f751
@@ -51,7 +51,6 @@ struct _PurpleSoundTheme
 struct _PurpleSoundTheme
 {
 	PurpleTheme parent;
-	gpointer priv;
 };
 
 struct _PurpleSoundThemeClass
============================================================
--- pidgin/gtkblist-theme-loader.c	bc1477c02198c8f52296ea914e7f0ff5ef5ba798
+++ pidgin/gtkblist-theme-loader.c	998de9eccacaf35c081669f51313bbec33ee37f2
@@ -65,8 +65,7 @@ parse_color(xmlnode *node, const char *t
 	GdkColor color;
 
 	if (temp && gdk_color_parse(temp, &color)) {
-    /* TODO: fix this for gtk+ 3.0 */
-		/*gdk_colormap_alloc_color(gdk_colormap_get_system(), &color, FALSE, TRUE);*/
+		gdk_colormap_alloc_color(gdk_colormap_get_system(), &color, FALSE, TRUE);
 		return gdk_color_copy(&color);
 	} else {
 		return NULL;
============================================================
--- pidgin/gtkblist-theme.c	e85dd470934bc3638f1f66a5889b17f5fcc66ffc
+++ pidgin/gtkblist-theme.c	d03ecde39a15a5c7361f2b016c95255eeeb98a17
@@ -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
  *****************************************************************************/
 
 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_blist_theme_finalize(GObject *obj
 	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 @@ pidgin_blist_theme_class_init(PidginBlis
 
 	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 @@ pidgin_blist_theme_get_type (void)
 			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 @@ pidgin_blist_theme_get_background_color(
 
 	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 @@ pidgin_blist_theme_get_opacity(PidginBli
 
 	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 @@ pidgin_blist_theme_get_layout(PidginBlis
 
 	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 @@ pidgin_blist_theme_get_expanded_backgrou
 
 	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 @@ pidgin_blist_theme_get_expanded_text_inf
 
 	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 @@ pidgin_blist_theme_get_collapsed_backgro
 
 	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 @@ pidgin_blist_theme_get_collapsed_text_in
 
 	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 @@ pidgin_blist_theme_get_contact_color(Pid
 
 	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 @@ pidgin_blist_theme_get_contact_text_info
 
 	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 @@ pidgin_blist_theme_get_online_text_info(
 
 	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 @@ pidgin_blist_theme_get_away_text_info(Pi
 
 	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 @@ pidgin_blist_theme_get_offline_text_info
 
 	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 @@ pidgin_blist_theme_get_idle_text_info(Pi
 
 	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 @@ pidgin_blist_theme_get_unread_message_te
 
 	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 @@ pidgin_blist_theme_get_unread_message_ni
 
 	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 @@ pidgin_blist_theme_get_status_text_info(
 
 	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 @@ pidgin_blist_theme_set_background_color(
 
 	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 @@ pidgin_blist_theme_set_opacity(PidginBli
 
 	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 @@ pidgin_blist_theme_set_layout(PidginBlis
 
 	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 @@ pidgin_blist_theme_set_expanded_backgrou
 
 	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 @@ pidgin_blist_theme_set_expanded_text_inf
 
 	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 @@ pidgin_blist_theme_set_collapsed_backgro
 
 	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 @@ pidgin_blist_theme_set_collapsed_text_in
 
 	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 @@ pidgin_blist_theme_set_contact_color(Pid
 
 	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 @@ pidgin_blist_theme_set_contact_text_info
 
 	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 @@ pidgin_blist_theme_set_online_text_info(
 
 	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 @@ pidgin_blist_theme_set_away_text_info(Pi
 
 	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 @@ pidgin_blist_theme_set_offline_text_info
 
 	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 @@ pidgin_blist_theme_set_idle_text_info(Pi
 
 	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 @@ pidgin_blist_theme_set_unread_message_te
 
 	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 @@ pidgin_blist_theme_set_unread_message_ni
 
 	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 @@ pidgin_blist_theme_set_status_text_info(
 
 	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);
============================================================
--- pidgin/gtkblist-theme.h	98d3b7bd44ecde9eff6333d9660947c733c18d25
+++ pidgin/gtkblist-theme.h	93a721824df4dad64ff3a0902767838da1b303a0
@@ -51,7 +51,6 @@ struct _PidginBlistTheme
 struct _PidginBlistTheme
 {
 	PurpleTheme parent;
-	gpointer priv;
 };
 
 struct _PidginBlistThemeClass
============================================================
--- libpurple/plugins/perl/common/Certificate.xs	2f09254414a7b6add63b5d356827678cb68b1a25
+++ libpurple/plugins/perl/common/Certificate.xs	42ac5f504269c6685d874d000c44091c2d85d35e
@@ -202,7 +202,7 @@ purple_certificate_check_signature_chain
 			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;
============================================================
--- pidgin/gtkicon-theme.c	d9320ee233f882d990857fa54b118c27e5c3b7ee
+++ pidgin/gtkicon-theme.c	f8986faa22506d1f49207f6b53dab54d549119a3
@@ -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 @@ pidgin_icon_theme_init(GTypeInstance *in
 {
 	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 @@ pidgin_icon_theme_finalize(GObject *obj)
 	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 @@ pidgin_icon_theme_class_init(PidginIconT
 	parent_class = g_type_class_peek_parent(klass);
 
 	obj_class->finalize = pidgin_icon_theme_finalize;
+
+	g_type_class_add_private(klass, sizeof(PidginIconThemePrivate));
 }
 
 GType
============================================================
--- pidgin/gtkicon-theme.h	2c92e56d150c04b73756b3884ea931c9a82eda5b
+++ pidgin/gtkicon-theme.h	b71df80971dc2e29edee14c80d031c7cd7392661
@@ -50,7 +50,6 @@ struct _PidginIconTheme
 struct _PidginIconTheme
 {
 	PurpleTheme parent;
-	gpointer priv;
 };
 
 struct _PidginIconThemeClass
============================================================
--- libpurple/protocols/jabber/jingle/content.c	c776283c4144965fbcbbe694234ca16b983002ac
+++ libpurple/protocols/jabber/jingle/content.c	10ba84c087cc2297450e5c223e3195dfef507627
@@ -181,6 +181,8 @@ jingle_content_set_property (GObject *ob
 jingle_content_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleContent *content;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_CONTENT(object));
 
 	content = JINGLE_CONTENT(object);
@@ -225,6 +227,8 @@ jingle_content_get_property (GObject *ob
 jingle_content_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleContent *content;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_CONTENT(object));
 
 	content = JINGLE_CONTENT(object);
@@ -454,6 +458,7 @@ jingle_content_to_xml(JingleContent *con
 xmlnode *
 jingle_content_to_xml(JingleContent *content, xmlnode *jingle, JingleActionType action)
 {
+	g_return_val_if_fail(content != NULL, NULL);
 	g_return_val_if_fail(JINGLE_IS_CONTENT(content), NULL);
 	return JINGLE_CONTENT_GET_CLASS(content)->to_xml(content, jingle, action);
 }
@@ -461,6 +466,7 @@ jingle_content_handle_action(JingleConte
 void
 jingle_content_handle_action(JingleContent *content, xmlnode *xmlcontent, JingleActionType action)
 {
+	g_return_if_fail(content != NULL);
 	g_return_if_fail(JINGLE_IS_CONTENT(content));
 	JINGLE_CONTENT_GET_CLASS(content)->handle_action(content, xmlcontent, action);
 }
============================================================
--- libpurple/protocols/jabber/jingle/session.c	c1b4c4eb938cf774840df8d92780271917d3c2a5
+++ libpurple/protocols/jabber/jingle/session.c	6f394c4ccad3d4ef658116e13e9db59d4b4a46fb
@@ -189,6 +189,8 @@ jingle_session_set_property (GObject *ob
 jingle_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleSession *session;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_SESSION(object));
 
 	session = JINGLE_SESSION(object);
@@ -231,6 +233,8 @@ jingle_session_get_property (GObject *ob
 jingle_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleSession *session;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_SESSION(object));
 
 	session = JINGLE_SESSION(object);
@@ -284,7 +288,7 @@ jingle_session_create(JabberStream *js, 
 	if (!js->sessions) {
 		purple_debug_info("jingle",
 				"Creating hash table for sessions\n");
-		js->sessions = g_hash_table_new(g_str_hash, g_str_equal);
+		js->sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 	}
 	purple_debug_info("jingle",
 			"inserting session with key: %s into table\n", sid);
@@ -407,27 +411,25 @@ jingle_add_jingle_packet(JingleSession *
 			xmlnode_new("jingle");
 	gchar *local_jid = jingle_session_get_local_jid(session);
 	gchar *remote_jid = jingle_session_get_remote_jid(session);
+	gchar *sid = jingle_session_get_sid(session);
 
 	xmlnode_set_namespace(jingle, JINGLE);
 	xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
 
 	if (jingle_session_is_initiator(session)) {
-		xmlnode_set_attrib(jingle, "initiator",
-				jingle_session_get_local_jid(session));
-		xmlnode_set_attrib(jingle, "responder",
-				jingle_session_get_remote_jid(session));
+		xmlnode_set_attrib(jingle, "initiator", local_jid);
+		xmlnode_set_attrib(jingle, "responder", remote_jid);
 	} else {
-		xmlnode_set_attrib(jingle, "initiator",
-				jingle_session_get_remote_jid(session));
-		xmlnode_set_attrib(jingle, "responder",
-				jingle_session_get_local_jid(session));
+		xmlnode_set_attrib(jingle, "initiator", remote_jid);
+		xmlnode_set_attrib(jingle, "responder", local_jid);
 	}
 
+	xmlnode_set_attrib(jingle, "sid", sid);
+
 	g_free(local_jid);
 	g_free(remote_jid);
+	g_free(sid);
 
-	xmlnode_set_attrib(jingle, "sid", jingle_session_get_sid(session));
-
 	return jingle;
 }
 
@@ -504,11 +506,16 @@ jingle_session_find_content(JingleSessio
 JingleContent *
 jingle_session_find_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	GList *iter = session->priv->contents;
+	GList *iter;
+
+	if (name == NULL)
+		return NULL;
+
+	iter = session->priv->contents;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleContent *content = iter->data;
 		gchar *cname = jingle_content_get_name(content);
-		gboolean result = !strcmp(name, cname);
+		gboolean result = g_str_equal(name, cname);
 		g_free(cname);
 
 		if (creator != NULL) {
@@ -526,11 +533,16 @@ jingle_session_find_pending_content(Jing
 JingleContent *
 jingle_session_find_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	GList *iter = session->priv->pending_contents;
+	GList *iter;
+
+	if (name == NULL)
+		return NULL;
+
+	iter = session->priv->pending_contents;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleContent *content = iter->data;
 		gchar *cname = jingle_content_get_name(content);
-		gboolean result = !strcmp(name, cname);
+		gboolean result = g_str_equal(name, cname);
 		g_free(cname);
 
 		if (creator != NULL) {
============================================================
--- libpurple/protocols/jabber/jingle/transport.c	0c669021e6fd078cec7fa3ff99a103fbae0d0d82
+++ libpurple/protocols/jabber/jingle/transport.c	bd9d70bcb9b26e54d3caee73384c208fbb03becf
@@ -108,6 +108,7 @@ jingle_transport_set_property (GObject *
 static void
 jingle_transport_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_TRANSPORT(object));
 
 	switch (prop_id) {
@@ -120,6 +121,7 @@ jingle_transport_get_property (GObject *
 static void
 jingle_transport_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_TRANSPORT(object));
 
 	switch (prop_id) {
@@ -170,6 +172,7 @@ jingle_transport_to_xml(JingleTransport 
 xmlnode *
 jingle_transport_to_xml(JingleTransport *transport, xmlnode *content, JingleActionType action)
 {
+	g_return_val_if_fail(transport != NULL, NULL);
 	g_return_val_if_fail(JINGLE_IS_TRANSPORT(transport), NULL);
 	return JINGLE_TRANSPORT_GET_CLASS(transport)->to_xml(transport, content, action);
 }
============================================================
--- libpurple/protocols/jabber/jingle/rawudp.c	89032bac19cf6b7ee32fd0248f1241b62ba8dc66
+++ libpurple/protocols/jabber/jingle/rawudp.c	77ad5da7fb7c36d4cf53c3e7d5132352ac4d346c
@@ -174,6 +174,8 @@ jingle_rawudp_set_property (GObject *obj
 jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleRawUdp *rawudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_RAWUDP(object));
 
 	rawudp = JINGLE_RAWUDP(object);
@@ -197,6 +199,8 @@ jingle_rawudp_get_property (GObject *obj
 jingle_rawudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleRawUdp *rawudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_RAWUDP(object));
 
 	rawudp = JINGLE_RAWUDP(object);
============================================================
--- libpurple/protocols/jabber/jingle/rtp.c	82797d1d6d25e5b34f9668847288b64596d0e91e
+++ libpurple/protocols/jabber/jingle/rtp.c	dcacf06a52d80015f7bc1676b1ccbdb182276784
@@ -577,11 +577,12 @@ jingle_rtp_init_media(JingleContent *con
 	guint num_params;
 
 	/* maybe this create ought to just be in initiate and handle initiate */
-	if (media == NULL)
+	if (media == NULL) {
 		media = jingle_rtp_create_media(content);
 
-	if (media == NULL)
-		return FALSE;
+		if (media == NULL)
+			return FALSE;
+	}
 
 	name = jingle_content_get_name(content);
 	media_type = jingle_rtp_get_media_type(content);
@@ -589,6 +590,16 @@ jingle_rtp_init_media(JingleContent *con
 	senders = jingle_content_get_senders(content);
 	transport = jingle_content_get_transport(content);
 
+	if (media_type == NULL) {
+		g_free(name);
+		g_free(remote_jid);
+		g_free(senders);
+		g_free(params);
+		g_object_unref(transport);
+		g_object_unref(session);
+		return FALSE;
+	}
+
 	if (JINGLE_IS_RAWUDP(transport))
 		transmitter = "rawudp";
 	else if (JINGLE_IS_ICEUDP(transport))
@@ -597,17 +608,17 @@ jingle_rtp_init_media(JingleContent *con
 		transmitter = "notransmitter";
 	g_object_unref(transport);
 
-	is_audio = !strcmp(media_type, "audio");
+	is_audio = g_str_equal(media_type, "audio");
 
-	if (!strcmp(senders, "both"))
-		type = is_audio == TRUE ? PURPLE_MEDIA_AUDIO
+	if (purple_strequal(senders, "both"))
+		type = is_audio ? PURPLE_MEDIA_AUDIO
 				: PURPLE_MEDIA_VIDEO;
-	else if ((strcmp(senders, "initiator") == 0) ==
+	else if (purple_strequal(senders, "initiator") ==
 			jingle_session_is_initiator(session))
-		type = is_audio == TRUE ? PURPLE_MEDIA_SEND_AUDIO
+		type = is_audio ? PURPLE_MEDIA_SEND_AUDIO
 				: PURPLE_MEDIA_SEND_VIDEO;
 	else
-		type = is_audio == TRUE ? PURPLE_MEDIA_RECV_AUDIO
+		type = is_audio ? PURPLE_MEDIA_RECV_AUDIO
 				: PURPLE_MEDIA_RECV_VIDEO;
 
 	params =
@@ -615,7 +626,17 @@ jingle_rtp_init_media(JingleContent *con
 			NULL, NULL, &num_params);
 
 	creator = jingle_content_get_creator(content);
-	if (!strcmp(creator, "initiator"))
+	if (creator == NULL) {
+		g_free(name);
+		g_free(media_type);
+		g_free(remote_jid);
+		g_free(senders);
+		g_free(params);
+		g_object_unref(session);
+		return FALSE;
+	}
+
+	if (g_str_equal(creator, "initiator"))
 		is_creator = jingle_session_is_initiator(session);
 	else
 		is_creator = !jingle_session_is_initiator(session);
@@ -624,6 +645,8 @@ jingle_rtp_init_media(JingleContent *con
 	if(!purple_media_add_stream(media, name, remote_jid,
 			type, is_creator, transmitter, num_params, params)) {
 		purple_media_end(media, NULL, NULL);
+		/* TODO: How much clean-up is necessary here? (does calling
+		         purple_media_end lead to cleaning up Jingle structs?) */
 		return FALSE;
 	}
 
@@ -645,10 +668,23 @@ jingle_rtp_parse_codecs(xmlnode *descrip
 	const char *encoding_name,*id, *clock_rate;
 	PurpleMediaCodec *codec;
 	const gchar *media = xmlnode_get_attrib(description, "media");
-	PurpleMediaSessionType type =
-			!strcmp(media, "video") ? PURPLE_MEDIA_VIDEO :
-			!strcmp(media, "audio") ? PURPLE_MEDIA_AUDIO : 0;
+	PurpleMediaSessionType type;
 
+	if (media == NULL) {
+		purple_debug_warning("jingle-rtp", "missing media type\n");
+		return NULL;
+	}
+
+	if (g_str_equal(media, "video")) {
+		type = PURPLE_MEDIA_VIDEO;
+	} else if (g_str_equal(media, "audio")) {
+		type = PURPLE_MEDIA_AUDIO;
+	} else {
+		purple_debug_warning("jingle-rtp", "unknown media type: %s\n",
+				media);
+		return NULL;
+	}
+
 	for (codec_element = xmlnode_get_child(description, "payload-type") ;
 		 codec_element ;
 		 codec_element = xmlnode_get_next_twin(codec_element)) {
@@ -768,19 +804,19 @@ jingle_rtp_handle_action_internal(Jingle
 	switch (action) {
 		case JINGLE_SESSION_ACCEPT:
 		case JINGLE_SESSION_INITIATE: {
-			JingleSession *session = jingle_content_get_session(content);
-			JingleTransport *transport = jingle_transport_parse(
-					xmlnode_get_child(xmlcontent, "transport"));
-			xmlnode *description = xmlnode_get_child(xmlcontent, "description");
-			GList *candidates = jingle_rtp_transport_to_candidates(transport);
-			GList *codecs = jingle_rtp_parse_codecs(description);
-			gchar *name = jingle_content_get_name(content);
-			gchar *remote_jid =
-					jingle_session_get_remote_jid(session);
+			JingleSession *session;
+			JingleTransport *transport;
+			xmlnode *description;
+			GList *candidates;
+			GList *codecs;
+			gchar *name;
+			gchar *remote_jid;
 			PurpleMedia *media;
 
+			session = jingle_content_get_session(content);
+
 			if (action == JINGLE_SESSION_INITIATE &&
-					jingle_rtp_init_media(content) == FALSE) {
+					!jingle_rtp_init_media(content)) {
 				/* XXX: send error */
 				jabber_iq_send(jingle_session_terminate_packet(
 						session, "general-error"));
@@ -788,6 +824,14 @@ jingle_rtp_handle_action_internal(Jingle
 				break;
 			}
 
+			transport = jingle_transport_parse(
+					xmlnode_get_child(xmlcontent, "transport"));
+			description = xmlnode_get_child(xmlcontent, "description");
+			candidates = jingle_rtp_transport_to_candidates(transport);
+			codecs = jingle_rtp_parse_codecs(description);
+			name = jingle_content_get_name(content);
+			remote_jid = jingle_session_get_remote_jid(session);
+
 			media = jingle_rtp_get_media(session);
 			purple_media_set_remote_codecs(media,
 					name, remote_jid, codecs);
============================================================
--- libpurple/protocols/jabber/jingle/iceudp.c	342d9053ce0f4e60537a2baef51ab5c5a89444cc
+++ libpurple/protocols/jabber/jingle/iceudp.c	373ea820d0f0d3d19ce457da17a1339b0e6a3c80
@@ -202,6 +202,8 @@ jingle_iceudp_set_property (GObject *obj
 jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
 	JingleIceUdp *iceudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_ICEUDP(object));
 
 	iceudp = JINGLE_ICEUDP(object);
@@ -225,6 +227,8 @@ jingle_iceudp_get_property (GObject *obj
 jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	JingleIceUdp *iceudp;
+
+	g_return_if_fail(object != NULL);
 	g_return_if_fail(JINGLE_IS_ICEUDP(object));
 
 	iceudp = JINGLE_ICEUDP(object);
============================================================
--- libpurple/protocols/jabber/useravatar.c	db821f64b1414bd537a55ecb8b7e95c71bccd653
+++ libpurple/protocols/jabber/useravatar.c	398da00de2888194e652302f184efc621e2aeb11
@@ -377,7 +377,7 @@ update_buddy_metadata(JabberStream *js, 
 				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) {
============================================================
--- libpurple/media-gst.h	4b2ed89f2709e7a9b4a4852f8a6cbdb878eabf35
+++ libpurple/media-gst.h	e550602d051b926df7f5560baf307c88190fc972
@@ -81,8 +81,6 @@ extern "C" {
  * 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 @@ GType purple_media_element_type_get_type
  * 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 @@ GType purple_media_element_info_get_type
  * @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 @@ GstElement *purple_media_get_src(PurpleM
  * @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 @@ GstElement *purple_media_get_tee(PurpleM
  * @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 @@ GstElement *purple_media_manager_get_pip
  * @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 @@ PurpleMediaElementInfo *purple_media_man
  *
  * @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 @@ void purple_media_manager_set_video_caps
  * @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);
 
============================================================
--- finch/plugins/gnttinyurl.c	762feefac28f88d3e69dd9f37be2fb441e8705b9
+++ finch/plugins/gnttinyurl.c	192c27939715983b721d2940c0a318635819383b
@@ -319,7 +319,7 @@ process_urls(PurpleConversation *conv, G
 			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 @@ tinyurl_notify_uri(const char *uri)
 	/* 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);
============================================================
--- pidgin/plugins/themeedit.c	ac145969c9e7a0b2e0f2aa36c0ae16d657ff2df4
+++ pidgin/plugins/themeedit.c	2f0d0e9408ea58753ccf682fd30ba01b4391b45d
@@ -306,6 +306,9 @@ pidgin_blist_theme_edit(PurplePluginActi
 		}
 	}
 
+#if !GTK_CHECK_VERSION(2,22,0)
+	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE);
+#endif
 #ifdef NOT_SADRUL
 	pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, G_CALLBACK(save_blist_theme), dialog);
 #endif
============================================================
--- pidgin/plugins/disco/gtkdisco.c	12e7452e732fc57bc1e748865d4f7e69834cea42
+++ pidgin/plugins/disco/gtkdisco.c	fc4d7d8bcbf24fa130fc87cd95bdd36f8256ea78
@@ -429,12 +429,15 @@ disco_paint_tooltip(GtkWidget *tipwindow
 static gboolean
 disco_paint_tooltip(GtkWidget *tipwindow, gpointer data)
 {
-	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(tipwindow));
 	PangoLayout *layout = g_object_get_data(G_OBJECT(tipwindow), "tooltip-plugin");
+#if GTK_CHECK_VERSION(2,14,0)
 	gtk_paint_layout(gtk_widget_get_style(tipwindow),
-			cr,
+			gtk_widget_get_window(tipwindow),
 			GTK_STATE_NORMAL, FALSE,
-			tipwindow, "tooltip",
+#else
+	gtk_paint_layout(tipwindow->style, tipwindow->window, GTK_STATE_NORMAL, FALSE,
+#endif
+			NULL, tipwindow, "tooltip",
 			6, 6, layout);
 	return TRUE;
 }
============================================================
--- libpurple/protocols/oscar/clientlogin.c	5cabbddca7acb2acf40e5d11b4d1a5858489c414
+++ libpurple/protocols/oscar/clientlogin.c	d88d9cd7dc6bbc07f337e5a4fb727fb95284a258
@@ -384,7 +384,7 @@ static void send_start_oscar_session(Osc
 	g_free(signature);
 
 	/* Make the request */
-	od->url_data = purple_util_fetch_url_request_len(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);
@@ -646,7 +646,7 @@ void send_client_login(OscarData *od, co
 	g_string_free(body, TRUE);
 
 	/* Send the POST request  */
-	od->url_data = purple_util_fetch_url_request_len(
+	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);
============================================================
--- libpurple/protocols/yahoo/libyahoo.c	a871e3427922dc201c58b80316d86bfe4e67f5c6
+++ libpurple/protocols/yahoo/libyahoo.c	6479939357f99ccd243616f5ac21e90413e22805
@@ -194,6 +194,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- libpurple/protocols/yahoo/libyahoojp.c	da89c3568e9054e458c7510b1cc67a6f5f46c190
+++ libpurple/protocols/yahoo/libyahoojp.c	6fefdbe13ac6664fbfb55ba28971792d4bdb866a
@@ -90,6 +90,7 @@ static PurplePluginProtocolInfo prpl_inf
 
 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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- pidgin/plugins/vvconfig.c	b789cd7a55e5b588c57179750c8c27c2d6d5f9d4
+++ pidgin/plugins/vvconfig.c	757386351b1cdaa86d9509b6e87e9873f3e33f91
@@ -39,6 +39,7 @@ static const gchar *AUDIO_SRC_PLUGINS[] 
 	/* "esdmon",	"ESD", ? */
 	"osssrc",	"OSS",
 	"pulsesrc",	"PulseAudio",
+	"libsndiosrc",	"sndio",
 	/* "audiotestsrc wave=silence", "Silence", */
 	"audiotestsrc",	"Test Sound",
 	NULL
@@ -50,6 +51,7 @@ static const gchar *AUDIO_SINK_PLUGINS[]
 	"esdsink",	"ESD",
 	"osssink",	"OSS",
 	"pulsesink",	"PulseAudio",
+	"libsndiosink",	"sndio",
 	NULL
 };
 
@@ -503,14 +505,14 @@ static void
 }
 
 static void
-config_destroy(GtkWidget *w, gpointer nul)
+config_destroy(GtkObject *w, gpointer nul)
 {
 	purple_debug_info("vvconfig", "closing vv configuration window\n");
 	window = NULL;
 }
 
 static void
-config_close(GtkWidget *w, gpointer nul)
+config_close(GtkObject *w, gpointer nul)
 {
 	gtk_widget_destroy(GTK_WIDGET(window));
 }
@@ -610,7 +612,7 @@ gst_bus_cb(GstBus *bus, GstMessage *msg,
 			GstElement *valve;
 
 			percent = gst_msg_db_to_percent(msg, "rms");
-			gtk_progress_bar_set_fraction(ctx->level, percent * 5);
+			gtk_progress_bar_set_fraction(ctx->level, percent);
 
 			percent = gst_msg_db_to_percent(msg, "decay");
 			threshold = gtk_range_get_value(ctx->threshold) / 100.0;
============================================================
--- libpurple/media/enum-types.h	47956e4afc314aa1048ee606584fcf8553c533c6
+++ libpurple/media/enum-types.h	cecc79c5c5857a990308fe2a867d3b5c3325ac58
@@ -107,8 +107,6 @@ typedef enum {
  * 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 @@ GType purple_media_candidate_type_get_ty
  * 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 @@ GType purple_media_caps_get_type(void);
  * 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 @@ GType purple_media_info_type_get_type(vo
  * 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 @@ GType purple_media_network_protocol_get_
  * 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 @@ GType purple_media_session_type_get_type
  * 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);
 
============================================================
--- libpurple/media/candidate.h	8d363729421aaf9390ee97b26a30a104dde785b1
+++ libpurple/media/candidate.h	dab1c98a357167d690809894283a8194316b8c49
@@ -47,8 +47,6 @@ typedef struct _PurpleMediaCandidate Pur
  * 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 @@ GType purple_media_candidate_get_type(vo
  * @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 @@ PurpleMediaCandidate *purple_media_candi
  * @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 @@ PurpleMediaCandidate *purple_media_candi
  * @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 @@ GList *purple_media_candidate_list_copy(
  * 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 @@ void purple_media_candidate_list_free(GL
  * @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 @@ gchar *purple_media_candidate_get_founda
  * @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 @@ guint purple_media_candidate_get_compone
  * @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 @@ gchar *purple_media_candidate_get_ip(Pur
  * @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 @@ guint16 purple_media_candidate_get_port(
  * @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 @@ gchar *purple_media_candidate_get_base_i
  * @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 @@ guint16 purple_media_candidate_get_base_
  * @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 @@ PurpleMediaNetworkProtocol purple_media_
  * @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 @@ guint32 purple_media_candidate_get_prior
  * @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 @@ PurpleMediaCandidateType purple_media_ca
  * @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 @@ gchar *purple_media_candidate_get_userna
  * @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 @@ gchar *purple_media_candidate_get_passwo
  * @param The candidate to get the TTL from.
  *
  * @return The TTL.
- *
- * @since 2.6.0
  */
 guint purple_media_candidate_get_ttl(PurpleMediaCandidate *candidate);
 
============================================================
--- libpurple/media/codec.h	333c5528dde3a1cc8ca9bebad5b8dd6f918ba110
+++ libpurple/media/codec.h	6af8bba48647c0bbf374be64ddecc6dfca5d1dbd
@@ -50,8 +50,6 @@ G_BEGIN_DECLS
  * 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 @@ GType purple_media_codec_get_type(void);
  * @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 @@ PurpleMediaCodec *purple_media_codec_new
  * @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 @@ guint purple_media_codec_get_id(PurpleMe
  * @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 @@ gchar *purple_media_codec_get_encoding_n
  * @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 @@ guint purple_media_codec_get_clock_rate(
  * @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 @@ guint purple_media_codec_get_channels(Pu
  *
  * @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 @@ GList *purple_media_codec_get_optional_p
  * @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 @@ void purple_media_codec_add_optional_par
  *
  * @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 @@ void purple_media_codec_remove_optional_
  * @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 @@ PurpleKeyValuePair *purple_media_codec_g
  * @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 @@ PurpleMediaCodec *purple_media_codec_cop
  * @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 @@ GList *purple_media_codec_list_copy(GLis
  * 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 @@ void purple_media_codec_list_free(GList 
  * @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);
 
============================================================
--- libpurple/media/backend-iface.h	320648565c761b97a84fb95fec1c0d8bd97a59a1
+++ libpurple/media/backend-iface.h	0c72ba7c6ba757326960002e99fa2bad72d3f321
@@ -77,8 +77,6 @@ struct _PurpleMediaBackendIface
  * 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 @@ GType purple_media_backend_get_type(void
  * @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 @@ gboolean purple_media_backend_add_stream
  * @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 @@ void purple_media_backend_add_remote_can
  * @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 @@ gboolean purple_media_backend_codecs_rea
  * @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 @@ GList *purple_media_backend_get_codecs(P
  * @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 @@ GList *purple_media_backend_get_local_ca
  * @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 @@ gboolean purple_media_backend_set_remote
  * @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 @@ gboolean purple_media_backend_set_send_c
  * @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 @@ void purple_media_backend_set_params(Pur
  * @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);
 
============================================================
--- libpurple/media/backend-fs2.h	d0c98270d331a2386413bdc2057c6dac0da72c28
+++ libpurple/media/backend-fs2.h	571ff96b62bc7db5985c26cded288faa31cb5bf6
@@ -50,8 +50,6 @@ typedef struct _PurpleMediaBackendFs2 Pu
  * 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);
 
============================================================
--- pidgin/gtkdocklet-gtk.c	a1ff3ac87eced7c771533c461692fde8a0f3787d
+++ /dev/null	
@@ -1,290 +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);
-	}
-}
-
-static void
-docklet_gtk_status_set_tooltip(gchar *tooltip)
-{
-	gtk_status_icon_set_tooltip_text(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");
-}
-
============================================================
--- libpurple/protocols/mxit/actions.c	e35847c7c937bdcab33b4327d66c4ad9a517fde7
+++ libpurple/protocols/mxit/actions.c	322aa1361f77118a4b0b0cc41bddb58ef28df0b2
@@ -43,7 +43,7 @@ static void mxit_profile_cb( PurpleConne
  */
 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;
@@ -200,7 +200,7 @@ static void mxit_profile_action( PurpleP
 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;
@@ -297,7 +297,7 @@ static void mxit_change_pin_cb( PurpleCo
  */
 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;
@@ -359,7 +359,7 @@ static void mxit_change_pin_action( Purp
 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;
@@ -372,12 +372,12 @@ static void mxit_change_pin_action( Purp
 	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 );
 
@@ -395,7 +395,7 @@ static void mxit_splash_action( PurplePl
 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 );
@@ -432,7 +432,7 @@ static void mxit_suggested_friends_actio
 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,
@@ -449,7 +449,7 @@ static void mxit_user_search_cb( PurpleC
  */
 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,
============================================================
--- libpurple/protocols/mxit/cipher.c	9ed2c64fec02de40e478cd601cda4e322fc7dff6
+++ libpurple/protocols/mxit/cipher.c	df932e8124c5aeaaaf83e71dafae57ac80df691e
@@ -79,7 +79,8 @@ static char* transport_layer_key( struct
 static char* transport_layer_key( struct MXitSession* session )
 {
 	static char	key[16 + 1];
-	int			passlen			= strlen( session->acc->password );
+	const char*	password		= purple_account_get_password( session->acc );
+	int			passlen			= strlen( password );
 
 	/* initialize with initial key */
 	g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
@@ -89,9 +90,9 @@ static char* transport_layer_key( struct
 
 	/* add last 8 characters of the PIN (no padding if less characters) */
 	if ( passlen <= 8 )
-		memcpy( key + 8, session->acc->password, passlen );
+		memcpy( key + 8, password, passlen );
 	else
-		memcpy( key + 8, session->acc->password + ( passlen - 8 ), 8 );
+		memcpy( key + 8, password + ( passlen - 8 ), 8 );
 
 	return key;
 }
@@ -124,7 +125,7 @@ char* mxit_encrypt_password( struct MXit
 
 	/* build the secret data to be encrypted: SECRET_HEADER + password */
 	pass = g_string_new( SECRET_HEADER );
-	g_string_append( pass, session->acc->password );
+	g_string_append( pass, purple_account_get_password( session->acc) );
 	padding_add( pass );		/* add ISO10126 padding */
 
 	/* now encrypt the secret. we encrypt each block separately (ECB mode) */
============================================================
--- libpurple/protocols/mxit/filexfer.c	50e87d30c7fb89e91dc5cb5cd7df57457a9cf26b
+++ libpurple/protocols/mxit/filexfer.c	4114b932117473ba7b3a817a835fd4c64007ef81
@@ -97,11 +97,11 @@ static void mxit_xfer_free( PurpleXfer* 
  */
 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,16 +117,16 @@ static void mxit_xfer_init( PurpleXfer* 
  */
 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" );
 
 	if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
 		/* we are trying to send a file to MXit */
 
-		if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) {
+		if ( purple_xfer_get_size( xfer ) > ( CP_MAX_PACKET - 1000 ) ) {	/* need to reserve some space for packet headers */
 			/* the file is too big */
-			purple_xfer_error( 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 @@ static void mxit_xfer_init( PurpleXfer* 
 		 * 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*
  */
 static void mxit_xfer_start( PurpleXfer* xfer )
 {
+	goffset			filesize;
 	unsigned char*	buffer;
 	int				size;
 	int				wrote;
@@ -163,10 +164,12 @@ static void mxit_xfer_start( PurpleXfer*
 		 * 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 guc
  */
 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( Pu
  */
 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( PurpleConnect
  */
 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 @@ PurpleXfer* mxit_xfer_new( PurpleConnect
 	/* 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 @@ void mxit_xfer_rx_offer( struct MXitSess
 		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 @@ static PurpleXfer* find_mxit_xfer( struc
 	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 ) )
@@ -424,19 +427,17 @@ void mxit_xfer_rx_file( struct MXitSessi
 void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen )
 {
 	PurpleXfer*			xfer	= NULL;
-	struct mxitxfer*	mx		= NULL;
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen );
 
 	/* find the file-transfer object */
 	xfer = find_mxit_xfer( session, fileid );
 	if ( xfer ) {
-		mx = xfer->data;
-
 		/* 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 );
============================================================
--- libpurple/protocols/mxit/formcmds.c	8888c7bc15e7758d2c8fbe9e7a00d214621c08b1
+++ libpurple/protocols/mxit/formcmds.c	f907caa69e7a4425622ba383f525f772629ec201
@@ -25,7 +25,7 @@
 
 
 #include "internal.h"
-#include <glib/gprintf.h>
+#include <glib.h>
 
 #include "purple.h"
 
@@ -86,7 +86,6 @@ static void mxit_cb_ii_returned(PurpleUt
 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,13 +105,9 @@ static void mxit_cb_ii_returned(PurpleUt
 		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 a copy in the imagestore */
+	id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
 
-	/* we now have the inline image, store it in the imagestore */
-	id = purple_imgstore_add_with_id(ii_data, len, NULL);
-
 	/* map the inline image id to purple image id */
 	intptr = g_malloc(sizeof(int));
 	*intptr = id;
@@ -367,7 +362,7 @@ static void command_image(struct RXMsgDa
 				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++;
 			}
 		}
============================================================
--- libpurple/protocols/mxit/login.c	c7e21c05defc7a351d65a40f5374043f3efd4c62
+++ libpurple/protocols/mxit/login.c	83abc02c1c7d4f71ed4825535770413c7982d243
@@ -49,30 +49,33 @@ static struct MXitSession* mxit_create_o
  */
 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;
+	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
+	);
 
-	/* add account */
-	session->acc = account;
-
 	/* 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 ) );
 	g_strlcpy( session->http_server, purple_account_get_string( account, MXIT_CONFIG_HTTPSERVER, DEFAULT_HTTP_SERVER ), sizeof( session->http_server ) );
@@ -173,7 +176,7 @@ static void mxit_cb_connect( gpointer us
 	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 );
 }
@@ -221,7 +224,7 @@ static void mxit_cb_register_ok( PurpleC
  */
 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 @@ static void mxit_cb_register_cancel( Pur
 	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 ) );
 }
 
 
@@ -507,7 +510,7 @@ static void mxit_cb_captcha_ok( PurpleCo
  */
 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,24 @@ static void mxit_cb_captcha_ok( PurpleCo
 	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 )
+	);
+	/* FIXME: This should be cancelled somewhere if not needed. */
+	url_data = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_clientinfo2, session );
 
 #ifdef	DEBUG_PROTOCOL
 	purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
@@ -571,7 +588,7 @@ static void mxit_cb_captcha_cancel( Purp
  */
 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 );
@@ -658,7 +675,7 @@ static void mxit_cb_clientinfo1( PurpleU
 			/* 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 +696,7 @@ static void mxit_cb_clientinfo1( PurpleU
 			/* 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 +732,8 @@ static void get_clientinfo( struct MXitS
 
 	/* 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 );
+	/* FIXME: This should be cancelled somewhere if not needed. */
+	url_data = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_clientinfo1, session );
 
 #ifdef	DEBUG_PROTOCOL
 	purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
@@ -764,9 +782,9 @@ void mxit_reconnect( struct MXitSession*
 	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 */
============================================================
--- libpurple/protocols/mxit/markup.c	645b4601bfae8c09b0028bc145e940d6ab7905a9
+++ libpurple/protocols/mxit/markup.c	2ec92e1b2229c18700c75a88bd830393a4ad3491
@@ -628,7 +628,8 @@ static void emoticon_request( struct RXM
 
 	/* 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 );
+	/* FIXME: This should be cancelled somewhere if not needed. */
+	url_data = purple_util_fetch_url( url, TRUE, NULL, TRUE, -1, emoticon_returned, mx );
 	g_free( url );
 }
 
============================================================
--- libpurple/protocols/mxit/multimx.c	13b5a9211d1f5cba73b4aae7db1266289b9f8961
+++ libpurple/protocols/mxit/multimx.c	a274454c16695c53ff7e0175aa7dc5b5ac7d9eed
@@ -458,7 +458,7 @@ void mxit_chat_join(PurpleConnection *gc
  */
 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;
 
@@ -500,7 +500,7 @@ void mxit_chat_reject(PurpleConnection *
  */
 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;
 
@@ -543,7 +543,7 @@ void mxit_chat_invite(PurpleConnection *
  */
 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;
@@ -589,7 +589,7 @@ void mxit_chat_leave(PurpleConnection *g
  */
 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);
@@ -620,7 +620,7 @@ int mxit_chat_send(PurpleConnection *gc,
  */
 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;
 
============================================================
--- libpurple/protocols/mxit/mxit.c	99e0162713a147af741a4144d309ec5183c4b4f7
+++ libpurple/protocols/mxit/mxit.c	935121cd3dabbd0b544e80e8c3c5bfcfd836e348
@@ -58,7 +58,7 @@ static void* mxit_link_click( const char
 static void* mxit_link_click( const char* link64 )
 {
 	PurpleAccount*		account;
-	PurpleConnection*	con;
+	PurpleConnection*	gc;
 	gchar**				parts		= NULL;
 	gchar*				link		= NULL;
 	gsize				len;
@@ -91,15 +91,15 @@ static void* mxit_link_click( const char
 	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 = ( atoi( parts[4] ) == 1 );
 
 	/* send click message back to MXit */
-	mxit_send_message( con->proto_data, parts[3], parts[5], FALSE, is_command );
+	mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command );
 
 	g_free( link );
 	link = NULL;
@@ -176,7 +176,7 @@ static void mxit_cb_chat_created( Purple
 	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;
@@ -358,11 +358,8 @@ static void mxit_tooltip( PurpleBuddy* b
 		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 ) ) {
-		/* 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, _( "Rejection Message" ), contact->msg );
-	}
+	if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) )
+		purple_notify_user_info_add_pair_plaintext( info, _( "Rejection Message" ), contact->msg );
 }
 
 
@@ -373,7 +370,7 @@ static void mxit_close( PurpleConnection
  */
 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 );
@@ -409,7 +406,7 @@ static int mxit_send_im( PurpleConnectio
 {
 	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 */
 }
@@ -423,7 +420,7 @@ static void mxit_set_status( PurpleAccou
  */
 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;
@@ -516,7 +513,7 @@ static void mxit_keepalive( PurpleConnec
  */
 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 ) )
@@ -544,7 +541,7 @@ static void mxit_set_buddy_icon( PurpleC
  */
 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 );
@@ -563,7 +560,7 @@ static void mxit_get_info( PurpleConnect
 {
 	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 };
@@ -614,13 +611,10 @@ static void mxit_reinvite( PurpleBlistNo
 static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored )
 {
 	PurpleBuddy*		buddy		= (PurpleBuddy *) node;
-	PurpleConnection*	gc;
-	struct MXitSession*	session;
+	PurpleConnection*	gc			= purple_account_get_connection( purple_buddy_get_account( buddy ) );
+	struct MXitSession*	session		= purple_connection_get_protocol_data( gc );
 	struct contact*		contact;
 
-	gc = purple_account_get_connection( purple_buddy_get_account( buddy ) );
-	session = gc->proto_data;
-
 	contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node );
 	if ( !contact )
 		return;
@@ -674,6 +668,7 @@ static PurplePluginProtocolInfo proto_in
 /*========================================================================================================================*/
 
 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 */
@@ -702,7 +697,7 @@ static PurplePluginProtocolInfo proto_in
 	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 */
@@ -721,7 +716,6 @@ static PurplePluginProtocolInfo proto_in
 	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] */
@@ -746,15 +740,12 @@ static PurplePluginProtocolInfo proto_in
 	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 */
 };
 
 
============================================================
--- libpurple/protocols/mxit/mxit.h	f1143fa501b957542f9e10ce262d1bc6280389b5
+++ libpurple/protocols/mxit/mxit.h	eda518db53c4f3734935eb878def5fc5faec178b
@@ -161,6 +161,7 @@ struct MXitSession {
 	/* 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) */
============================================================
--- libpurple/protocols/mxit/profile.c	375d93aaa6c0af1240775ce33043916b4e0e0d8d
+++ libpurple/protocols/mxit/profile.c	de4a344e1843e7f388350fcb3582222715ce99ef
@@ -175,40 +175,26 @@ void mxit_show_profile( struct MXitSessi
 		contact = purple_buddy_get_protocol_data( buddy );
 	}
 
-	/* 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, _( "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 ) );
-	/* 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, _( "Birthday" ), tmp );
+	purple_notify_user_info_add_pair_plaintext( info, _( "Birthday" ), tmp );
 	g_free( tmp );
 
 	purple_notify_user_info_add_pair_plaintext( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
 
 	/* optional information */
-	/* 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, _( "First Name" ), profile->firstname );
-	/* 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, _( "Last Name" ), profile->lastname );
-	/* 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, _( "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 );
 
-	if ( *profile->aboutme ) {
-		/* 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, _( "About Me" ), profile->aboutme );
-	}
-	if ( *profile->whereami ) {
-		/* 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, _( "Where I Live" ), profile->whereami );
-	}
+	purple_notify_user_info_add_pair_plaintext( info, _( "Country" ), profile->regcountry );
 
+	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 ) {
@@ -241,11 +227,8 @@ void mxit_show_profile( struct MXitSessi
 		if ( contact ) {
 			/* invite found */
 
-			if ( contact->msg ) {
-				/* 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, _( "Invite Message" ), contact->msg );
-			}
+			if ( contact->msg )
+				purple_notify_user_info_add_pair_plaintext( info, _( "Invite Message" ), contact->msg );
 
 			if ( contact->imgid ) {
 				/* this invite has a avatar */
============================================================
--- libpurple/protocols/mxit/protocol.c	10dd7e05b590052e1c4055afc7868956ff000c46
+++ libpurple/protocols/mxit/protocol.c	99bd25324ca144ef7acbad8fdf2ac83b517afd13
@@ -311,7 +311,7 @@ static void mxit_write_http_get( struct 
 #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 )
@@ -458,7 +458,7 @@ static void mxit_queue_packet( struct MX
 	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 */
@@ -718,7 +718,7 @@ void mxit_send_register( struct MXitSess
 								"%s%c%i%c%s%c%s%c"			/* dateOfBirth\1gender\1location\1capabilities\1 */
 								"%s%c%i%c%s%c%s"			/* dc\1features\1dialingcode\1locale */
 								"%c%i%c%i",					/* \1protocolVer\1lastRosterUpdate */
-								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
+								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_PACKET, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
 								profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM,
 								session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale,
 								CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
@@ -765,7 +765,7 @@ void mxit_send_login( struct MXitSession
 								session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, 1, CP_FLD_TERM,
 								MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM,
 								session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
-								CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
+								CP_MAX_PACKET, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
 	);
 
 	/* include "custom resource" information */
@@ -2136,13 +2136,13 @@ static void mxit_parse_cmd_media( struct
 					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 );
 					}
 				}
 			}
@@ -2819,9 +2819,9 @@ void mxit_close_connection( struct MXitS
 	}
 
 	/* 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 */
============================================================
--- libpurple/protocols/mxit/protocol.h	f8c10dcf4d656f055ee0e9452e893b034a274f1e
+++ libpurple/protocols/mxit/protocol.h	3da9215cc34caf0877a7380b1db0d8630d2caa44
@@ -34,8 +34,7 @@
 #define		CP_PKT_TERM				'\x02'				/* packet terminator */
 
 
-#define		CP_MAX_PACKET			( 1024 * 1024 )		/* maximum client protocol packet size (1 MiB) */
-#define		CP_MAX_FILESIZE			( 150 * 1000 )		/* maximum client protocol file transfer size (150 KB) */
+#define		CP_MAX_PACKET			( 1 * 1000 * 1000 )	/* maximum client protocol packet size (1 MB) */
 #define		MXIT_EMOTICON_SIZE		18					/* icon size for custom emoticons */
 #define		CP_MAX_STATUS_MSG		250					/* maximum status message length (in characters) */
 
@@ -77,6 +76,7 @@
 #define		MXIT_CF_GAMING_UPDATE	0x800000
 #define		MXIT_CF_VOICE			0x1000000
 #define		MXIT_CF_VIDEO			0x2000000
+#define		MXIT_CF_TOUCHSCREEN		0x4000000
 
 /* Client features supported by this implementation */
 #define		MXIT_CP_FEATURES		( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 )
============================================================
--- libpurple/protocols/mxit/roster.c	ae7790bbd739414b18561e0297bbf50fa1af023e
+++ libpurple/protocols/mxit/roster.c	556b93161c6b7b3bda59e690bc7d68ee2a07af00
@@ -293,14 +293,15 @@ static PurpleBuddy* mxit_update_buddy_gr
  */
 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 @@ static PurpleBuddy* mxit_update_buddy_gr
 		 * 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 @@ static PurpleBuddy* mxit_update_buddy_gr
 		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 @@ void mxit_update_contact( struct MXitSes
 
 		/* 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* g
  */
 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
  */
 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*
  */
 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*
  */
 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
  */
 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;
 
============================================================
--- libpurple/protocols/mxit/splashscreen.c	ea0c77abaf1981e197f5ab7b4b03b653e84c9d40
+++ libpurple/protocols/mxit/splashscreen.c	8ae7d93b5b835a5ed37825cf4a48f76dddad9c73
@@ -144,7 +144,7 @@ static void splash_click_ok(PurpleConnec
  */
 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 */
============================================================
--- libpurple/purple-3.pc.in	85bccb8ee08949360496ac8997878b50c8433fd1
+++ libpurple/purple-3.pc.in	76ebc94c91b1b1449c51a662b7e7b757777d9d2c
@@ -1,7 +1,7 @@ libdir=@libdir@
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
-includedir=@includedir@
+includedir=@includedir@/libpurple
 datarootdir=@datarootdir@
 datadir=@datadir@
 sysconfdir=@sysconfdir@
============================================================
--- pidgin/pidgin-3.pc.in	2675d7a8428b39c28c987e10317b23fb4ae54971
+++ pidgin/pidgin-3.pc.in	54a073ea818f0ae282c5f285218ef00020d475f7
@@ -1,7 +1,7 @@ libdir=@libdir@
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
-includedir=@includedir@
+includedir=@includedir@/pidgin
 datarootdir=@datarootdir@
 datadir=@datadir@
 sysconfdir=@sysconfdir@
============================================================
--- libpurple/protocols/gg/lib/dcc7.c	1e4298363bc0b0687e3044ef89a8cddf07bcc55f
+++ libpurple/protocols/gg/lib/dcc7.c	06f1ac15d74499da48fb2ab0181978c5c45dc16e
@@ -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 @@ struct gg_event *gg_dcc7_watch_fd(struct
 		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 @@ struct gg_event *gg_dcc7_watch_fd(struct
 		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");
============================================================
--- libpurple/protocols/gg/lib/resolver.c	de746848ad54b347d8c2997e9e6486c478fa9105
+++ libpurple/protocols/gg/lib/resolver.c	1360fbb37c933b5e7d4f9d2707b9af85e409c436
@@ -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 @@ int gg_gethostbyname_real(const char *ho
 #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,8 +283,9 @@ static int gg_resolver_run(int fd, const
 
 	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 @@ struct in_addr *gg_gethostbyname(const c
 	return result;
 }
 
+#ifdef GG_CONFIG_HAVE_FORK
+
 /**
  * \internal Struktura przekazywana do w?tku rozwi?zuj?cego nazw?.
  */
@@ -319,281 +318,7 @@ struct gg_resolver_fork_data {
 	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.
  *
  * Po??czenia asynchroniczne nie mog? blokowa? procesu w trakcie rozwi?zywania
@@ -644,12 +369,17 @@ static int gg_resolver_fork_start(int *f
 	}
 
 	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,8 +428,9 @@ static void gg_resolver_fork_cleanup(voi
 
 	free(data);
 }
-#endif
 
+#endif /* GG_CONFIG_HAVE_FORK */
+
 #ifdef GG_CONFIG_HAVE_PTHREAD
 
 /**
@@ -868,25 +599,15 @@ int gg_session_set_resolver(struct gg_se
 			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 @@ int gg_http_set_resolver(struct gg_http 
 			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 @@ int gg_global_set_resolver(gg_resolver_t
 			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;
============================================================
--- libpurple/protocols/gg/lib/resolver.h	a411899abe871eacbfff1891ce9baf98dd50fb32
+++ libpurple/protocols/gg/lib/resolver.h	a3add0e0d4866ed7740b605f9bf873e48a3d03b2
@@ -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);
 
============================================================
--- libpurple/protocols/jabber/google/gmail.c	43f78321281c20551cafab655e875153fa25bfff
+++ libpurple/protocols/jabber/google/gmail.c	2fac522ac20c1793ea76750257e758e6f419e047
@@ -150,7 +150,7 @@ jabber_gmail_poke(JabberStream *js, cons
 	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 */
============================================================
--- libpurple/protocols/jabber/google/google_presence.c	cd0481a083e3568c8f489d260045bba8a28aac14
+++ libpurple/protocols/jabber/google/google_presence.c	e2c6cdce51495e427307a812d02f82b390f23c76
@@ -27,12 +27,12 @@ void jabber_google_presence_incoming(Jab
 	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");
 	}
 }
 
============================================================
--- libpurple/protocols/jabber/google/jingleinfo.c	70a53ff970e3705a25a264c748dac2f57218ce70
+++ libpurple/protocols/jabber/google/jingleinfo.c	86aabf9b6bb82b51e1e3b357950e7e4dc758cb44
@@ -117,7 +117,7 @@ jabber_google_jingle_info_common(JabberS
 					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);
 			}
 		}
============================================================
--- libpurple/protocols/oscar/userinfo.c	c47a311acf25b21964d38e8a82bc2eb22465d6b0
+++ libpurple/protocols/oscar/userinfo.c	4a8d80b12d772d69c5ac9de737155e98f7a87085
@@ -307,8 +307,6 @@ oscar_user_info_append_extra_info(Purple
 {
 	OscarData *od;
 	PurpleAccount *account;
-	PurplePresence *presence = NULL;
-	PurpleStatus *status = NULL;
 	PurpleGroup *g = NULL;
 	struct buddyinfo *bi = NULL;
 	char *tmp;
@@ -330,8 +328,6 @@ oscar_user_info_append_extra_info(Purple
 		bname = purple_buddy_get_name(b);
 		g = purple_buddy_get_group(b);
 		gname = purple_group_get_name(g);
-		presence = purple_buddy_get_presence(b);
-		status = purple_presence_get_active_status(presence);
 	}
 
 	if (userinfo != NULL)
============================================================
--- libpurple/protocols/msn/sbconn.c	eff828e66030ba1f23ecd25ba7fd0ded4af6c9a4
+++ libpurple/protocols/msn/sbconn.c	c492d67235834a0f645146feb7a7550f1a9c8153
@@ -121,6 +121,8 @@ release_msg(MsnSwitchBoard *swboard, Msn
 			}
 #endif
 		}
+	} else {
+		msn_transaction_set_saveable(trans, FALSE);
 	}
 
 	trans->payload = payload;
============================================================
--- libpurple/protocols/msn/xfer.c	d8541455da494f7df015ae5d64a0f398af567d89
+++ libpurple/protocols/msn/xfer.c	cfb12b08cc0e6feeac2fb4144c730269a6de76c7
@@ -42,7 +42,7 @@ msn_xfer_init(PurpleXfer *xfer)
 
 	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 @@ msn_xfer_cancel(PurpleXfer *xfer)
 	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 @@ msn_xfer_write(const guchar *data, gsize
 
 	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 @@ msn_xfer_read(guchar **data, PurpleXfer 
 
 	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 @@ msn_file_context_to_wire(MsnFileContext 
 {
 	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_file_context_to_wire(MsnFileContext 
 	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 @@ msn_file_context_from_wire(const char *b
 {
 	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) {
+	if (context->version == 0) {
+		if (context->length != MSN_FILE_CONTEXT_SIZE_V0) {
+			g_free(context);
+			return NULL;
+		}
+	} else if (context->version == 2) {
 		/* The length field is broken for this version. No check. */
-		context->length = MSN_FILE_CONTEXT_SIZE;
+		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 + 63) {
+		if (context->length != MSN_FILE_CONTEXT_SIZE_V3) {
 			g_free(context);
 			return NULL;
-		} else if (len < MSN_FILE_CONTEXT_SIZE + 63) {
+		} else if (len < MSN_FILE_CONTEXT_SIZE_V3) {
 			g_free(context);
 			return NULL;
 		}
@@ -218,9 +233,15 @@ msn_file_context_from_wire(const char *b
 	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;
============================================================
--- libpurple/protocols/msn/xfer.h	14c70992d37863a845ab03341f1dc88802ee33c5
+++ libpurple/protocols/msn/xfer.h	4259153e0c4dcc6c1b42f2da99434d5ce260cef1
@@ -39,13 +39,17 @@ typedef struct
 	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);
============================================================
--- libpurple/protocols/jabber/google/relay.c	482f69f1a3ab5051c1a053f392fa1f111d0079c1
+++ libpurple/protocols/jabber/google/relay.c	338b506d34ddd2763a38afc777f559ddf1e5fc07
@@ -137,7 +137,7 @@ jabber_google_do_relay_request(JabberStr
 	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 =
============================================================
--- libpurple/protocols/mxit/voicevideo.c	9f8067b027c3d3099abf07c10e464fe20257ec6f
+++ libpurple/protocols/mxit/voicevideo.c	fc8c14ce76910f6579a783ee22d82f6935697164
@@ -63,7 +63,7 @@ PurpleMediaCaps mxit_media_caps(PurpleAc
  */
 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;
============================================================
--- libpurple/protocols/gg/lib/handlers.c	87d66880d587b734d3016a4449b5dd2f782f025e
+++ libpurple/protocols/gg/lib/handlers.c	3d0c7b4c5928d70f70f5675d6976ed0684189faf
@@ -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 @@ static int gg_session_handle_welcome(str
 	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;
============================================================
--- libpurple/tests/test_xmlnode.c	ef8840551902714078a88e375c19a8caf02be7d8
+++ libpurple/tests/test_xmlnode.c	15242821df719edc44b882586ccfface0905aa11
@@ -21,6 +21,101 @@ END_TEST
 }
 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 at gmail.com/resource' to='another_user at 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 at gmail.com/resource' to='another_user at 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 @@ xmlnode_suite(void)
 
 	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;


More information about the Commits mailing list