Merged soc.2013.gobjectification branch soc.2013.gobjectification.plugins

Sun, 18 Aug 2013 01:53:00 +0530

author
Ankit Vani <a@nevitus.org>
date
Sun, 18 Aug 2013 01:53:00 +0530
branch
soc.2013.gobjectification.plugins
changeset 36550
9af0493c6f26
parent 36549
735cd882faf7 (diff)
parent 34884
1eda402a5924 (current diff)
child 36551
8988e6e21acb

Merged soc.2013.gobjectification branch

libpurple/connection.h file | annotate | diff | comparison | revisions
--- a/Doxyfile.in	Sun Aug 18 01:52:32 2013 +0530
+++ b/Doxyfile.in	Sun Aug 18 01:53:00 2013 +0530
@@ -1381,7 +1381,7 @@
 # undefined via #undef or recursively expanded use the := operator
 # instead of the = operator.
 
-PREDEFINED             =
+PREDEFINED             = "@PLUGINS_MACRO@"
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
 # this tag can be used to specify a list of macro names that should be expanded.
--- a/acinclude.m4	Sun Aug 18 01:52:32 2013 +0530
+++ b/acinclude.m4	Sun Aug 18 01:53:00 2013 +0530
@@ -6,7 +6,7 @@
 # Owen Taylor     1997-2001
 
 dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
-dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject or 
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gobject or 
 dnl gthread is specified in MODULES, pass to pkg-config
 dnl
 AC_DEFUN([AM_PATH_GLIB_2_0],
@@ -20,9 +20,6 @@
   for module in . $4
   do
       case "$module" in
-         gmodule) 
-             pkg_config_args="$pkg_config_args gmodule-2.0"
-         ;;
          gobject) 
              pkg_config_args="$pkg_config_args gobject-2.0"
          ;;
--- a/configure.ac	Sun Aug 18 01:52:32 2013 +0530
+++ b/configure.ac	Sun Aug 18 01:53:00 2013 +0530
@@ -335,10 +335,7 @@
 dnl #######################################################################
 dnl # Check for GLib 2.20 (required)
 dnl #######################################################################
-# TODO: gmodule-2.0 is only needed if enable_plugins is 'yes'.  It
-#       might be nice to change this check so that it's not required
-#       if enable_plugins is 'no'.
-PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.20.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.20.0 gobject-2.0 gthread-2.0], , [
 	AC_MSG_RESULT(no)
 	AC_MSG_ERROR([
 
@@ -1282,7 +1279,7 @@
 AC_ARG_ENABLE(distrib,,,enable_distrib=no)
 AM_CONDITIONAL(DISTRIB, test "x$enable_distrib" = "xyes")
 DYNAMIC_PRPLS=all
-AC_ARG_WITH(static-prpls, [AS_HELP_STRING([--with-static-prpls], [Link to certain protocols statically])], [STATIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`], [STATIC_PRPLS=""])
+AC_ARG_WITH(static-prpls, [AS_HELP_STRING([--with-static-protocols], [Link to certain protocols statically])], [STATIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`], [STATIC_PRPLS=""])
 if test "x$STATIC_PRPLS" != "x" -a "x$DYNAMIC_PRPLS" = "xall"; then
 	DYNAMIC_PRPLS=""
 fi
@@ -1301,31 +1298,43 @@
 fi
 AC_SUBST(STATIC_PRPLS)
 STATIC_LINK_LIBS=
-extern_init=
+extern_load=
 load_proto=
+extern_unload=
+unload_proto=
 for i in $STATIC_PRPLS ; do
 	dnl Ugly special case for "libsilcpurple.la":
 	dnl ... and Ugly special case for multi-protocol oscar and yahoo
 	if test \( "x$i" = "xoscar" -o "x$i" = "xaim" -o "x$i" = "xicq" \) -a "x$static_oscar" != "xyes"; then
 		STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/oscar/liboscar.la"
-		extern_init="$extern_init extern gboolean purple_init_aim_plugin();"
-		extern_init="$extern_init extern gboolean purple_init_icq_plugin();"
-		load_proto="$load_proto purple_init_aim_plugin();"
-		load_proto="$load_proto purple_init_icq_plugin();"
+		extern_load="$extern_load extern gboolean aim_plugin_load();"
+		extern_load="$extern_load extern gboolean icq_plugin_load();"
+		load_proto="$load_proto aim_plugin_load();"
+		load_proto="$load_proto icq_plugin_load();"
+		extern_unload="$extern_unload extern gboolean aim_plugin_unload();"
+		extern_unload="$extern_unload extern gboolean icq_plugin_unload();"
+		unload_proto="$unload_proto aim_plugin_unload();"
+		unload_proto="$unload_proto icq_plugin_unload();"
 	elif test "x$i" = "xyahoo"; then
 		STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/yahoo/libymsg.la"
-		extern_init="$extern_init extern gboolean purple_init_yahoo_plugin();"
-		extern_init="$extern_init extern gboolean purple_init_yahoojp_plugin();"
-		load_proto="$load_proto purple_init_yahoo_plugin();"
-		load_proto="$load_proto purple_init_yahoojp_plugin();"
+		extern_load="$extern_load extern gboolean yahoo_plugin_load();"
+		extern_load="$extern_load extern gboolean yahoojp_plugin_load();"
+		load_proto="$load_proto yahoo_plugin_load();"
+		load_proto="$load_proto yahoojp_plugin_load();"
+		extern_unload="$extern_unload extern gboolean yahoo_plugin_unload();"
+		extern_unload="$extern_unload extern gboolean yahoojp_plugin_unload();"
+		unload_proto="$unload_proto yahoo_plugin_unload();"
+		unload_proto="$unload_proto yahoojp_plugin_unload();"
 	else
 		if test "x$i" = "xsilc"; then
 			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
 		else
 			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la"
 		fi
-		extern_init="$extern_init extern gboolean purple_init_${i}_plugin();"
-		load_proto="$load_proto purple_init_${i}_plugin();"
+		extern_load="$extern_load extern gboolean ${i}_plugin_load();"
+		load_proto="$load_proto ${i}_plugin_load();"
+		extern_unload="$extern_unload extern gboolean ${i}_plugin_unload();"
+		unload_proto="$unload_proto ${i}_plugin_unload();"
 	fi
 	case $i in
 		bonjour)	static_bonjour=yes ;;
@@ -1362,10 +1371,12 @@
 AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes")
 AM_CONDITIONAL(STATIC_ZEPHYR, test "x$static_zephyr" = "xyes")
 AC_SUBST(STATIC_LINK_LIBS)
-AC_DEFINE_UNQUOTED(STATIC_PROTO_INIT, $extern_init static void static_proto_init(void) { $load_proto },
-	[Loads static protocol plugin module initialization functions.])
+AC_DEFINE_UNQUOTED(STATIC_PROTO_LOAD, $extern_load static void static_proto_load(void) { $load_proto },
+	[Loads protocols from static protocol plugin modules.])
+AC_DEFINE_UNQUOTED(STATIC_PROTO_UNLOAD, $extern_unload static void static_proto_unload(void) { $unload_proto },
+	[Unloads protocols from static protocol plugin modules.])
 
-AC_ARG_WITH(dynamic_prpls, [AS_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`])
+AC_ARG_WITH(dynamic_prpls, [AS_HELP_STRING([--with-dynamic-protocols], [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 mxit myspace novell oscar sametime silc simple yahoo zephyr"
 fi
@@ -1707,6 +1718,22 @@
 AM_CONDITIONAL(ENABLE_KWALLET, test "x$enable_kwallet" = "xyes")
 
 dnl #######################################################################
+dnl # Check for GPlugin 0.0.5
+dnl #######################################################################
+if test "x$enable_plugins" = "xyes" ; then
+	PKG_CHECK_MODULES(GPLUGIN, [gplugin >= 0.0.5 gmodule-2.0], , [
+		AC_MSG_RESULT(no)
+		AC_MSG_ERROR([
+	GPlugin 0.0.5 development headers not found, which are required if you wish to
+	enable plugins.
+	Use --disable-plugins if you want to disable plugins (will also disable
+	protocols).
+	])])
+	AC_SUBST(GPLUGIN_CFLAGS)
+	AC_SUBST(GPLUGIN_LIBS)
+fi
+
+dnl #######################################################################
 dnl # Check for Python
 dnl #######################################################################
 
@@ -2611,11 +2638,13 @@
 	AC_DEFINE(PURPLE_PLUGINS, 1, [Define if plugins are enabled.])
 	AM_CONDITIONAL(PLUGINS, true)
 	PLUGINS_DEFINE="#define PURPLE_PLUGINS 1"
+	PLUGINS_MACRO="PURPLE_PLUGINS"
 else
 	AM_CONDITIONAL(PLUGINS, false)
 	PLUGINS_DEFINE="#undef PURPLE_PLUGINS"
 fi
 AC_SUBST(PLUGINS_DEFINE)
+AC_SUBST(PLUGINS_MACRO)
 
 dnl #######################################################################
 dnl # Check for Cyrus-SASL (for xmpp/irc)
--- a/doc/C-HOWTO.dox	Sun Aug 18 01:52:32 2013 +0530
+++ b/doc/C-HOWTO.dox	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 #include <glib.h>
 
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 static gboolean
@@ -83,7 +83,7 @@
   like described before.  Next we include glib.h, mainly for gboolean and the
   glib wrappers of the standard C types.
 
-  Next, we include plugin.h which has all the plugin specific stuff that we
+  Next, we include plugins.h which has all the plugin specific stuff that we
   need.  For example: @c PurplePlugin, @c PurplePluginInfo,
   @c PURPLE_PLUGIN_MAGIC, and @c PURPLE_INIT_PLUGIN().
 
--- a/doc/plugin-signals.dox	Sun Aug 18 01:52:32 2013 +0530
+++ b/doc/plugin-signals.dox	Sun Aug 18 01:53:00 2013 +0530
@@ -5,7 +5,7 @@
   @signal plugin-unload
  @endsignals
 
- @see plugin.h
+ @see plugins.h
 
  <hr>
 
--- a/finch/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -72,6 +72,7 @@
 	$(DBUS_LIBS) \
 	$(INTLLIBS) \
 	$(GLIB_LIBS) \
+	$(GPLUGIN_LIBS) \
 	$(LIBXML_LIBS) \
 	$(GNT_LIBS) \
 	$(GSTREAMER_LIBS) \
@@ -89,6 +90,7 @@
 	-I$(srcdir)/libgnt/ \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(LIBXML_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
--- a/finch/finch.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/finch.c	Sun Aug 18 01:53:00 2013 +0530
@@ -30,8 +30,8 @@
 #include "ft.h"
 #include "log.h"
 #include "notify.h"
-#include "prefs.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "pounce.h"
 #include "savedstatuses.h"
 #include "sound.h"
@@ -361,6 +361,14 @@
 	purple_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops());
 	purple_idle_set_ui_ops(finch_idle_get_ui_ops());
 
+	if (!purple_core_init(FINCH_UI))
+	{
+		fprintf(stderr,
+				"Initialization of the Purple core failed. Dumping core.\n"
+				"Please report this!\n");
+		abort();
+	}
+
 	path = g_build_filename(purple_user_dir(), "plugins", NULL);
 	if (!g_stat(path, &st))
 		g_mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR);
@@ -368,14 +376,7 @@
 	g_free(path);
 
 	purple_plugins_add_search_path(LIBDIR);
-
-	if (!purple_core_init(FINCH_UI))
-	{
-		fprintf(stderr,
-				"Initialization of the Purple core failed. Dumping core.\n"
-				"Please report this!\n");
-		abort();
-	}
+	purple_plugins_refresh();
 
 	/* TODO: should this be moved into finch_prefs_init() ? */
 	finch_prefs_update_old();
--- a/finch/gntaccount.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntaccount.c	Sun Aug 18 01:53:00 2013 +0530
@@ -43,7 +43,7 @@
 #include <accountopt.h>
 #include <connection.h>
 #include <notify.h>
-#include <plugin.h>
+#include <plugins.h>
 #include <request.h>
 #include <savedstatuses.h>
 
@@ -74,7 +74,7 @@
 	GntWidget *splits;
 	GList *split_entries;
 
-	GList *prpl_entries;
+	GList *protocol_entries;
 	GntWidget *prpls;
 
 	GntWidget *newmail;
@@ -101,7 +101,7 @@
 edit_dialog_destroy(AccountEditDialog *dialog)
 {
 	accountdialogs = g_list_remove(accountdialogs, dialog);
-	g_list_free(dialog->prpl_entries);
+	g_list_free(dialog->protocol_entries);
 	g_list_free(dialog->split_entries);
 	g_free(dialog);
 }
@@ -110,15 +110,13 @@
 save_account_cb(AccountEditDialog *dialog)
 {
 	PurpleAccount *account;
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prplinfo;
+	PurpleProtocol *protocol;
 	const char *value;
 	GString *username;
 
 	/* XXX: Do some error checking first. */
 
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+	protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
 
 	/* Username && user-splits */
 	value = gnt_entry_get_text(GNT_ENTRY(dialog->username));
@@ -133,10 +131,10 @@
 
 	username = g_string_new(value);
 
-	if (prplinfo != NULL)
+	if (protocol != NULL)
 	{
 		GList *iter, *entries;
-		for (iter = prplinfo->user_splits, entries = dialog->split_entries;
+		for (iter = protocol->user_splits, entries = dialog->split_entries;
 				iter && entries; iter = iter->next, entries = entries->next)
 		{
 			PurpleAccountUserSplit *split = iter->data;
@@ -153,7 +151,7 @@
 
 	if (dialog->account == NULL)
 	{
-		account = purple_account_new(username->str, purple_plugin_get_id(plugin));
+		account = purple_account_new(username->str, protocol->id);
 		purple_accounts_add(account);
 	}
 	else
@@ -162,12 +160,12 @@
 
 		/* Protocol */
 		if (purple_account_is_disconnected(account)) {
-			purple_account_set_protocol_id(account, purple_plugin_get_id(plugin));
+			purple_account_set_protocol_id(account, protocol->id);
 			purple_account_set_username(account, username->str);
 		} else {
 			const char *old = purple_account_get_protocol_id(account);
 			char *oldprpl;
-			if (strcmp(old, purple_plugin_get_id(plugin))) {
+			if (strcmp(old, protocol->id)) {
 				purple_notify_error(NULL, _("Error"), _("Account was not modified"),
 						_("The account's protocol cannot be changed while it is connected to the server."));
 				return;
@@ -204,11 +202,11 @@
 			gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->newmail)));
 
 	/* Protocol options */
-	if (prplinfo)
+	if (protocol)
 	{
 		GList *iter, *entries;
 
-		for (iter = prplinfo->protocol_options, entries = dialog->prpl_entries;
+		for (iter = protocol->protocol_options, entries = dialog->protocol_entries;
 				iter && entries; iter = iter->next, entries = entries->next)
 		{
 			PurpleAccountOption *option = iter->data;
@@ -253,7 +251,7 @@
 		gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree);
 	}
 
-	if (prplinfo && prplinfo->register_user &&
+	if (protocol && protocol->register_user &&
 			gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->regserver))) {
 		purple_account_register(account);
 	} else if (dialog->account == NULL) {
@@ -285,8 +283,7 @@
 update_user_splits(AccountEditDialog *dialog)
 {
 	GntWidget *hbox;
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prplinfo;
+	PurpleProtocol *protocol;
 	GList *iter, *entries;
 	char *username = NULL;
 
@@ -304,14 +301,13 @@
 
 	dialog->split_entries = NULL;
 
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	if (!plugin)
+	protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	if (!protocol)
 		return;
-	prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 
 	username = dialog->account ? g_strdup(purple_account_get_username(dialog->account)) : NULL;
 
-	for (iter = prplinfo->user_splits; iter; iter = iter->next)
+	for (iter = protocol->user_splits; iter; iter = iter->next)
 	{
 		PurpleAccountUserSplit *split = iter->data;
 		GntWidget *entry;
@@ -330,7 +326,7 @@
 		g_free(buf);
 	}
 
-	for (iter = g_list_last(prplinfo->user_splits), entries = g_list_last(dialog->split_entries);
+	for (iter = g_list_last(protocol->user_splits), entries = g_list_last(dialog->split_entries);
 			iter && entries; iter = iter->prev, entries = entries->prev)
 	{
 		GntWidget *entry = entries->data;
@@ -368,8 +364,7 @@
 static void
 add_protocol_options(AccountEditDialog *dialog)
 {
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prplinfo;
+	PurpleProtocol *protocol;
 	GList *iter;
 	GntWidget *vbox, *box;
 	PurpleAccount *account;
@@ -384,23 +379,21 @@
 		gnt_box_set_fill(GNT_BOX(vbox), TRUE);
 	}
 
-	if (dialog->prpl_entries)
+	if (dialog->protocol_entries)
 	{
-		g_list_free(dialog->prpl_entries);
-		dialog->prpl_entries = NULL;
+		g_list_free(dialog->protocol_entries);
+		dialog->protocol_entries = NULL;
 	}
 
 	vbox = dialog->prpls;
 
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	if (!plugin)
+	protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	if (!protocol)
 		return;
 
-	prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
 	account = dialog->account;
 
-	for (iter = prplinfo->protocol_options; iter; iter = iter->next)
+	for (iter = protocol->protocol_options; iter; iter = iter->next)
 	{
 		PurpleAccountOption *option = iter->data;
 		PurplePrefType type = purple_account_option_get_type(option);
@@ -413,7 +406,7 @@
 		{
 			GntWidget *widget = gnt_check_box_new(purple_account_option_get_text(option));
 			gnt_box_add_widget(GNT_BOX(box), widget);
-			dialog->prpl_entries = g_list_append(dialog->prpl_entries, widget);
+			dialog->protocol_entries = g_list_append(dialog->protocol_entries, widget);
 
 			if (account)
 				gnt_check_box_set_checked(GNT_CHECK_BOX(widget),
@@ -441,7 +434,7 @@
 						purple_account_option_get_setting(option), dv);
 
 				gnt_box_add_widget(GNT_BOX(box), combo);
-				dialog->prpl_entries = g_list_append(dialog->prpl_entries, combo);
+				dialog->protocol_entries = g_list_append(dialog->protocol_entries, combo);
 
 				for ( ; opt_iter; opt_iter = opt_iter->next)
 				{
@@ -456,7 +449,7 @@
 			{
 				GntWidget *entry = gnt_entry_new(NULL);
 				gnt_box_add_widget(GNT_BOX(box), entry);
-				dialog->prpl_entries = g_list_append(dialog->prpl_entries, entry);
+				dialog->protocol_entries = g_list_append(dialog->protocol_entries, entry);
 
 				if (type == PURPLE_PREF_STRING)
 				{
@@ -491,27 +484,24 @@
 	/* Show the registration checkbox only in a new account dialog,
 	 * and when the selected prpl has the support for it. */
 	gnt_widget_set_visible(dialog->regserver, account == NULL &&
-			prplinfo->register_user != NULL);
+			protocol->register_user != NULL);
 }
 
 static void
 update_user_options(AccountEditDialog *dialog)
 {
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prplinfo;
+	PurpleProtocol *protocol;
 
-	plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
-	if (!plugin)
+	protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol));
+	if (!protocol)
 		return;
 
-	prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
 	if (dialog->newmail == NULL)
 		dialog->newmail = gnt_check_box_new(_("New mail notifications"));
 	if (dialog->account)
 		gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail),
 				purple_account_get_check_mail(dialog->account));
-	if (!prplinfo || !(prplinfo->options & OPT_PROTO_MAIL_CHECK))
+	if (!protocol || !(protocol->options & OPT_PROTO_MAIL_CHECK))
 		gnt_widget_set_visible(dialog->newmail, FALSE);
 	else
 		gnt_widget_set_visible(dialog->newmail, TRUE);
@@ -524,7 +514,7 @@
 }
 
 static void
-prpl_changed_cb(GntWidget *combo, PurplePlugin *old, PurplePlugin *new, AccountEditDialog *dialog)
+protocol_changed_cb(GntWidget *combo, PurpleProtocol *old, PurpleProtocol *new, AccountEditDialog *dialog)
 {
 	update_user_splits(dialog);
 	add_protocol_options(dialog);
@@ -541,7 +531,7 @@
 	GntWidget *combo, *button, *entry;
 	GList *list, *iter;
 	AccountEditDialog *dialog;
-	PurplePlugin *plugin;
+	PurpleProtocol *protocol;
 
 	if (account)
 	{
@@ -554,10 +544,10 @@
 		}
 	}
 
-	list = purple_plugins_get_protocols();
+	list = purple_protocols_get_all();
 	if (list == NULL) {
 		purple_notify_error(NULL, _("Error"),
-				_("There are no protocol plugins installed."),
+				_("There are no protocols installed."),
 				_("(You probably forgot to 'make install'.)"));
 		return;
 	}
@@ -582,17 +572,17 @@
 	for (iter = list; iter; iter = iter->next)
 	{
 		gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data,
-				((PurplePlugin*)iter->data)->info->name);
+				((PurpleProtocol*)iter->data)->name);
 	}
 
-	plugin = purple_plugins_find_with_id(purple_account_get_protocol_id(account));
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
-	if (account && plugin)
-		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), plugin);
+	if (account && protocol)
+		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), protocol);
 	else
 		gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data);
 
-	g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog);
+	g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(protocol_changed_cb), dialog);
 
 	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:")));
 	gnt_box_add_widget(GNT_BOX(hbox), combo);
--- a/finch/gntblist.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntblist.c	Sun Aug 18 01:53:00 2013 +0530
@@ -31,6 +31,7 @@
 #include <log.h>
 #include <notify.h>
 #include <request.h>
+#include <plugins.h>
 #include <savedstatuses.h>
 #include <server.h>
 #include <signal.h>
@@ -726,7 +727,7 @@
 	GHashTable *hash = NULL;
 	PurpleConnection *gc;
 	gboolean autojoin;
-	PurplePluginProtocolInfo *info;
+	PurpleProtocol *protocol;
 
 	account = purple_request_fields_get_account(allfields, "account");
 	name = purple_request_fields_get_string(allfields, "name");
@@ -741,9 +742,9 @@
 		group = _("Chats");
 
 	gc = purple_account_get_connection(account);
-	info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-	if (info->chat_info_defaults != NULL)
-		hash = info->chat_info_defaults(gc, name);
+	protocol = purple_connection_get_protocol_info(gc);
+	if (protocol->chat_info_defaults != NULL)
+		hash = protocol->chat_info_defaults(gc, name);
 
 	chat = purple_chat_new(account, name, hash);
 
@@ -1061,12 +1062,12 @@
 append_proto_menu(GntMenu *menu, PurpleConnection *gc, PurpleBlistNode *node)
 {
 	GList *list;
-	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-
-	if(!prpl_info || !prpl_info->blist_node_menu)
+	PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
+
+	if(!protocol || !protocol->blist_node_menu)
 		return;
 
-	for(list = prpl_info->blist_node_menu(node); list;
+	for(list = protocol->blist_node_menu(node); list;
 			list = g_list_delete_link(list, list))
 	{
 		PurpleMenuAction *act = (PurpleMenuAction *) list->data;
@@ -1125,7 +1126,7 @@
 	purple_request_fields_add_group(fields, group);
 
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc);
+	parts = purple_connection_get_protocol_info(gc)->chat_info(gc);
 
 	for (iter = parts; iter; iter = iter->next) {
 		pce = iter->data;
@@ -1273,11 +1274,11 @@
 	PurpleAccount *account;
 	gboolean permitted;
 	GntMenuItem *item;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-	if (prpl_info && prpl_info->get_info)
+	protocol = purple_connection_get_protocol_info(gc);
+	if (protocol && protocol->get_info)
 	{
 		add_custom_action(menu, _("Get Info"),
 				PURPLE_CALLBACK(finch_blist_get_buddy_info_cb), buddy);
@@ -1286,10 +1287,10 @@
 	add_custom_action(menu, _("Add Buddy Pounce"),
 			PURPLE_CALLBACK(finch_blist_pounce_node_cb), buddy);
 
-	if (prpl_info && prpl_info->send_file)
+	if (protocol && protocol->send_file)
 	{
-		if (!prpl_info->can_receive_file ||
-			prpl_info->can_receive_file(gc, purple_buddy_get_name(buddy)))
+		if (!protocol->can_receive_file ||
+			protocol->can_receive_file(gc, purple_buddy_get_name(buddy)))
 			add_custom_action(menu, _("Send File"),
 					PURPLE_CALLBACK(finch_blist_menu_send_file_cb), buddy);
 	}
@@ -1411,12 +1412,12 @@
 		account = purple_buddy_get_account(b);
 	} else if (PURPLE_IS_CHAT(node)) {
 		PurpleChat *c = (PurpleChat*) node;
-		PurplePluginProtocolInfo *prpl_info = NULL;
+		PurpleProtocol *protocol = NULL;
 		type = PURPLE_LOG_CHAT;
 		account = purple_chat_get_account(c);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
-		if (prpl_info && prpl_info->get_chat_name) {
-			name = prpl_info->get_chat_name(purple_chat_get_components(c));
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+		if (protocol && protocol->get_chat_name) {
+			name = protocol->get_chat_name(purple_chat_get_components(c));
 		}
 	} else if (PURPLE_IS_CONTACT(node)) {
 		finch_log_show_contact((PurpleContact *)node);
@@ -1714,8 +1715,7 @@
 static void
 tooltip_for_buddy(PurpleBuddy *buddy, GString *str, gboolean full)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleAccount *account;
 	PurpleNotifyUserInfo *user_info;
 	PurplePresence *presence;
@@ -1737,10 +1737,9 @@
 	purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), tmp);
 	g_free(tmp);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info && prpl_info->tooltip_text) {
-		prpl_info->tooltip_text(buddy, user_info, full);
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+	if (protocol && protocol->tooltip_text) {
+		protocol->tooltip_text(buddy, user_info, full);
 	}
 
 	if (purple_prefs_get_bool("/finch/blist/idletime")) {
@@ -2452,25 +2451,60 @@
 }
 
 static void
-build_plugin_actions(GntMenuItem *item, PurplePlugin *plugin, gpointer context)
+build_plugin_actions(GntMenuItem *item, PurplePlugin *plugin)
+{
+	GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
+	PurplePluginGetActionsCallback get_actions;
+	GList *actions;
+	GntMenuItem *menuitem;
+
+	get_actions =
+		purple_plugin_info_get_actions_callback(purple_plugin_get_info(plugin));
+
+	gnt_menuitem_set_submenu(item, GNT_MENU(sub));
+	for (actions = get_actions(plugin); actions;
+			actions = g_list_delete_link(actions, actions)) {
+		if (actions->data) {
+			PurplePluginAction *action = actions->data;
+			action->plugin = plugin;
+			menuitem = gnt_menuitem_new(action->label);
+			gnt_menu_add_item(GNT_MENU(sub), menuitem);
+
+			gnt_menuitem_set_callback(menuitem, plugin_action, action);
+			g_object_set_data_full(G_OBJECT(menuitem), "plugin_action",
+								   action, (GDestroyNotify)purple_plugin_action_free);
+		}
+	}
+}
+
+static void
+protocol_action(GntMenuItem *item, gpointer data)
+{
+	PurpleProtocolAction *action = data;
+	if (action && action->callback)
+		action->callback(action);
+}
+
+static void
+build_protocol_actions(GntMenuItem *item, PurpleProtocol *protocol,
+		PurpleConnection *gc)
 {
 	GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP);
 	GList *actions;
 	GntMenuItem *menuitem;
 
 	gnt_menuitem_set_submenu(item, GNT_MENU(sub));
-	for (actions = PURPLE_PLUGIN_ACTIONS(plugin, context); actions;
+	for (actions = protocol->get_actions(gc); actions;
 			actions = g_list_delete_link(actions, actions)) {
 		if (actions->data) {
-			PurplePluginAction *action = actions->data;
-			action->plugin = plugin;
-			action->context = context;
+			PurpleProtocolAction *action = actions->data;
+			action->connection = gc;
 			menuitem = gnt_menuitem_new(action->label);
 			gnt_menu_add_item(GNT_MENU(sub), menuitem);
 
-			gnt_menuitem_set_callback(menuitem, plugin_action, action);
-			g_object_set_data_full(G_OBJECT(menuitem), "plugin_action",
-								   action, (GDestroyNotify)purple_plugin_action_free);
+			gnt_menuitem_set_callback(menuitem, protocol_action, action);
+			g_object_set_data_full(G_OBJECT(menuitem), "protocol_action",
+								   action, (GDestroyNotify)purple_protocol_action_free);
 		}
 	}
 }
@@ -2540,16 +2574,15 @@
 
 	for (iter = purple_plugins_get_loaded(); iter; iter = iter->next) {
 		PurplePlugin *plugin = iter->data;
+		PurplePluginInfo *info = purple_plugin_get_info(plugin);
 		GntMenuItem *item;
-		if (PURPLE_IS_PROTOCOL_PLUGIN(plugin))
+
+		if (!purple_plugin_info_get_actions_callback(info))
 			continue;
 
-		if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin))
-			continue;
-
-		item = gnt_menuitem_new(_(plugin->info->name));
+		item = gnt_menuitem_new(_(purple_plugin_info_get_name(info)));
 		gnt_menu_add_item(GNT_MENU(sub), item);
-		build_plugin_actions(item, plugin, NULL);
+		build_plugin_actions(item, plugin);
 	}
 }
 
@@ -2574,16 +2607,16 @@
 			iter = g_list_delete_link(iter, iter)) {
 		PurpleAccount *account = iter->data;
 		PurpleConnection *gc = purple_account_get_connection(account);
-		PurplePlugin *prpl;
+		PurpleProtocol *protocol;
 
 		if (!gc || !PURPLE_CONNECTION_IS_CONNECTED(gc))
 			continue;
-		prpl = purple_connection_get_prpl(gc);
-
-		if (PURPLE_PLUGIN_HAS_ACTIONS(prpl)) {
+		protocol = purple_connection_get_protocol_info(gc);
+
+		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_actions)) {
 			item = gnt_menuitem_new(purple_account_get_username(account));
 			gnt_menu_add_item(GNT_MENU(sub), item);
-			build_plugin_actions(item, prpl, gc);
+			build_protocol_actions(item, protocol, gc);
 		}
 	}
 }
@@ -2783,9 +2816,9 @@
 
 	chat = purple_blist_find_chat(account, name);
 	if (chat == NULL) {
-		PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-		if (info->chat_info_defaults != NULL)
-			hash = info->chat_info_defaults(gc, name);
+		PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
+		if (protocol->chat_info_defaults != NULL)
+			hash = protocol->chat_info_defaults(gc, name);
 	} else {
 		hash = purple_chat_get_components(chat);
 	}
--- a/finch/gntconv.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntconv.c	Sun Aug 18 01:53:00 2013 +0530
@@ -175,7 +175,7 @@
 					purple_conversation_write(conv, "", _("That command only works in IMs, not chats."),
 							PURPLE_MESSAGE_NO_LOG, time(NULL));
 				break;
-			case PURPLE_CMD_STATUS_WRONG_PRPL:
+			case PURPLE_CMD_STATUS_WRONG_PROTOCOL:
 				purple_conversation_write(conv, "", _("That command doesn't work on this protocol."),
 						PURPLE_MESSAGE_NO_LOG, time(NULL));
 				break;
@@ -339,7 +339,7 @@
 
 			chat = find_chat_for_conversation(conv);
 			if (chat == NULL) {
-				PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+				PurpleProtocol *info = purple_connection_get_protocol_info(gc);
 				if (info->chat_info_defaults != NULL)
 					comps = info->chat_info_defaults(gc, purple_conversation_get_name(conv));
 			} else {
@@ -636,8 +636,8 @@
 	if (PURPLE_IS_IM_CONVERSATION(ggc->active_conv)) {
 		PurpleAccount *account = purple_conversation_get_account(ggc->active_conv);
 		PurpleConnection *gc = purple_account_get_connection(account);
-		PurplePluginProtocolInfo *pinfo =
-			gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
+		PurpleProtocol *pinfo =
+			gc ? purple_connection_get_protocol_info(gc) : NULL;
 
 		if (pinfo && pinfo->get_info) {
 			item = gnt_menuitem_new(_("Get Info"));
@@ -692,7 +692,7 @@
 {
 	PurpleAccount *account = purple_conversation_get_account(fc->active_conv);
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	char *name, *realname;
 
 	if (!gc) {
@@ -703,9 +703,9 @@
 
 	name = gnt_tree_get_selection_data(GNT_TREE(widget));
 
-	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_chat_conversation_get_id(
+	protocol = purple_connection_get_protocol_info(gc);
+	if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_cb_real_name))
+		realname = protocol->get_cb_real_name(gc, purple_chat_conversation_get_id(
 				PURPLE_CHAT_CONVERSATION(fc->active_conv)), name);
 	else
 		realname = NULL;
@@ -1251,7 +1251,9 @@
 		const GList *plugins = purple_plugins_get_loaded();
 		if (plugins) {
 			for (; plugins; plugins = plugins->next) {
-				str = g_string_append(str, purple_plugin_get_name(plugins->data));
+				PurplePluginInfo *plugin_info = purple_plugin_get_info(plugins->data);
+				str = g_string_append(str, purple_plugin_info_get_name(plugin_info));
+
 				if (plugins->next)
 					str = g_string_append(str, ", ");
 			}
--- a/finch/gntft.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntft.c	Sun Aug 18 01:53:00 2013 +0530
@@ -36,7 +36,7 @@
 #include "debug.h"
 #include "notify.h"
 #include "ft.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 
 #include "gntft.h"
--- a/finch/gntlog.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntlog.c	Sun Aug 18 01:53:00 2013 +0530
@@ -505,7 +505,7 @@
 	for(accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
 
 		PurpleAccount *account = (PurpleAccount *)accounts->data;
-		if(purple_find_prpl(purple_account_get_protocol_id(account)) == NULL)
+		if(purple_find_protocol_info(purple_account_get_protocol_id(account)) == NULL)
 			continue;
 
 		logs = g_list_concat(purple_log_get_system_logs(account), logs);
--- a/finch/gntmedia.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntmedia.c	Sun Aug 18 01:53:00 2013 +0530
@@ -405,7 +405,7 @@
 {
 	PurpleAccount *account = purple_conversation_get_account(conv);
 
-	if (!purple_prpl_initiate_media(account,
+	if (!purple_protocol_initiate_media(account,
 			purple_conversation_get_name(conv),
 			PURPLE_MEDIA_AUDIO))
 		return PURPLE_CMD_STATUS_FAILED;
--- a/finch/gntplugin.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntplugin.c	Sun Aug 18 01:53:00 2013 +0530
@@ -42,6 +42,21 @@
 #include "gntplugin.h"
 #include "gntrequest.h"
 
+#define FINCH_PLUGIN_INFO_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfoPrivate))
+
+typedef struct
+{
+	FinchPluginFrame get_pref_frame;
+} FinchPluginInfoPrivate;
+
+enum
+{
+	PROP_0,
+	PROP_FINCH_PREFERENCES_FRAME,
+	PROP_LAST
+};
+
 static struct
 {
 	GntWidget *tree;
@@ -54,6 +69,97 @@
 
 static GntWidget *process_pref_frame(PurplePluginPrefFrame *frame);
 
+/* Set method for GObject properties */
+static void
+finch_plugin_info_set_property(GObject *obj, guint param_id, const GValue *value,
+		GParamSpec *pspec)
+{
+	FinchPluginInfoPrivate *priv = FINCH_PLUGIN_INFO_GET_PRIVATE(obj);
+
+	switch (param_id) {
+		case PROP_FINCH_PREFERENCES_FRAME:
+			priv->get_pref_frame = g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+/* Get method for GObject properties */
+static void
+finch_plugin_info_get_property(GObject *obj, guint param_id, GValue *value,
+		GParamSpec *pspec)
+{
+	FinchPluginInfoPrivate *priv = FINCH_PLUGIN_INFO_GET_PRIVATE(obj);
+
+	switch (param_id) {
+		case PROP_FINCH_PREFERENCES_FRAME:
+			g_value_set_pointer(value, priv->get_pref_frame);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+/* Class initializer function */
+static void finch_plugin_info_class_init(FinchPluginInfoClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	g_type_class_add_private(klass, sizeof(FinchPluginInfoPrivate));
+
+	/* Setup properties */
+	obj_class->get_property = finch_plugin_info_get_property;
+	obj_class->set_property = finch_plugin_info_set_property;
+
+	g_object_class_install_property(obj_class, PROP_FINCH_PREFERENCES_FRAME,
+		g_param_spec_pointer("finch-preferences-frame",
+		                     "Finch preferences frame callback",
+		                     "Callback that returns a GNT preferences frame",
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+GType
+finch_plugin_info_get_type(void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY(type == 0)) {
+		static const GTypeInfo info = {
+			.class_size = sizeof(FinchPluginInfoClass),
+			.class_init = (GClassInitFunc)finch_plugin_info_class_init,
+			.instance_size = sizeof(FinchPluginInfo),
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_PLUGIN_INFO,
+		                              "FinchPluginInfo", &info, 0);
+	}
+
+	return type;
+}
+
+FinchPluginInfo *
+finch_plugin_info_new(const char *first_property, ...)
+{
+	GObject *info;
+	va_list var_args;
+
+	/* at least ID is required */
+	if (!first_property)
+		return NULL;
+
+	va_start(var_args, first_property);
+	info = g_object_new_valist(FINCH_TYPE_PLUGIN_INFO, first_property,
+	                           var_args);
+	va_end(var_args);
+
+	g_object_set(info, "ui-requirement", FINCH_UI, NULL);
+
+	return FINCH_PLUGIN_INFO(info);
+}
+
 static void
 free_stringlist(GList *list)
 {
@@ -64,15 +170,21 @@
 static void
 decide_conf_button(PurplePlugin *plugin)
 {
-	if (purple_plugin_is_loaded(plugin) &&
-		((PURPLE_IS_GNT_PLUGIN(plugin) &&
-			FINCH_PLUGIN_UI_INFO(plugin) != NULL) ||
-		(plugin->info->prefs_info &&
-			plugin->info->prefs_info->get_plugin_pref_frame)))
-		gnt_widget_set_visible(plugins.conf, TRUE);
-	else
-		gnt_widget_set_visible(plugins.conf, FALSE);
+	gboolean visible = FALSE;
+	PurplePluginInfo *info = purple_plugin_get_info(plugin);
+
+	if (purple_plugin_is_loaded(plugin)) {
+		FinchPluginInfoPrivate *priv = NULL;
+		if (FINCH_IS_PLUGIN_INFO(info))
+			priv = FINCH_PLUGIN_INFO_GET_PRIVATE(info);
 
+		if ((priv && priv->get_pref_frame) ||
+			(purple_plugin_info_get_pref_frame_callback(info))) {
+			visible = TRUE;
+		}
+	}
+
+	gnt_widget_set_visible(plugins.conf, visible);
 	gnt_box_readjust(GNT_BOX(plugins.window));
 	gnt_widget_draw(plugins.window);
 }
@@ -80,21 +192,27 @@
 static void
 plugin_toggled_cb(GntWidget *tree, PurplePlugin *plugin, gpointer null)
 {
+	GError *error = NULL;
+
 	if (gnt_tree_get_choice(GNT_TREE(tree), plugin))
 	{
-		if (!purple_plugin_load(plugin)) {
-			purple_notify_error(NULL, _("ERROR"), _("loading plugin failed"), NULL);
+		if (!purple_plugin_load(plugin, &error)) {
+			purple_notify_error(NULL, _("ERROR"), _("loading plugin failed"),
+					error->message);
 			gnt_tree_set_choice(GNT_TREE(tree), plugin, FALSE);
+			g_error_free(error);
 		}
 	}
 	else
 	{
 		GntWidget *win;
 
-		if (!purple_plugin_unload(plugin)) {
-			purple_notify_error(NULL, _("ERROR"), _("unloading plugin failed"), NULL);
+		if (!purple_plugin_unload(plugin, &error)) {
+			purple_notify_error(NULL, _("ERROR"), _("unloading plugin failed"),
+					error->message);
 			purple_plugin_disable(plugin);
 			gnt_tree_set_choice(GNT_TREE(tree), plugin, TRUE);
+			g_error_free(error);
 		}
 
 		if (confwins && (win = g_hash_table_lookup(confwins, plugin)) != NULL)
@@ -117,12 +235,15 @@
 selection_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
 {
 	PurplePlugin *plugin = current;
+	PurplePluginInfo *info;
 	char *text;
 	GList *list = NULL, *iter = NULL;
 
 	if (!plugin)
 		return;
 
+	info = purple_plugin_get_info(plugin);
+
 	/* If the selected plugin was unseen before, mark it as seen. But save the list
 	 * only when the plugin list is closed. So if the user enables a plugin, and it
 	 * crashes, it won't get marked as seen so the user can fix the bug and still
@@ -130,17 +251,23 @@
 	 * I probably mean 'plugin developers' by 'users' here. */
 	list = g_object_get_data(G_OBJECT(widget), "seen-list");
 	if (list)
-		iter = g_list_find_custom(list, plugin->path, (GCompareFunc)strcmp);
+		iter = g_list_find_custom(list, purple_plugin_get_filename(plugin),
+					(GCompareFunc)strcmp);
 	if (!iter) {
-		list = g_list_prepend(list, g_strdup(plugin->path));
+		list = g_list_prepend(list, g_strdup(purple_plugin_get_filename(plugin)));
 		g_object_set_data(G_OBJECT(widget), "seen-list", list);
 	}
 
 	/* XXX: Use formatting and stuff */
 	gnt_text_view_clear(GNT_TEXT_VIEW(plugins.aboot));
 	text = g_strdup_printf(_("Name: %s\nVersion: %s\nDescription: %s\nAuthor: %s\nWebsite: %s\nFilename: %s\n"),
-			SAFE(_(plugin->info->name)), SAFE(_(plugin->info->version)), SAFE(_(plugin->info->description)),
-			SAFE(_(plugin->info->author)), SAFE(_(plugin->info->homepage)), SAFE(plugin->path));
+			SAFE(_(purple_plugin_info_get_name(info))),
+			SAFE(_(purple_plugin_info_get_version(info))),
+			SAFE(_(purple_plugin_info_get_description(info))),
+			SAFE(_(purple_plugin_info_get_author(info))),
+			SAFE(_(purple_plugin_info_get_website(info))),
+			SAFE(purple_plugin_get_filename(plugin)));
+
 	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(plugins.aboot),
 			text, GNT_TEXT_FLAG_NORMAL);
 	gnt_text_view_scroll(GNT_TEXT_VIEW(plugins.aboot), 0);
@@ -164,11 +291,12 @@
 static int
 plugin_compare(PurplePlugin *p1, PurplePlugin *p2)
 {
-	char *s1 = g_utf8_strup(p1->info->name, -1);
-	char *s2 = g_utf8_strup(p2->info->name, -1);
+	char *s1 = g_utf8_strup(purple_plugin_info_get_name(purple_plugin_get_info(p1)), -1);
+	char *s2 = g_utf8_strup(purple_plugin_info_get_name(purple_plugin_get_info(p2)), -1);
 	int ret = g_utf8_collate(s1, s2);
 	g_free(s1);
 	g_free(s2);
+
 	return ret;
 }
 
@@ -188,7 +316,8 @@
 configure_plugin_cb(GntWidget *button, gpointer null)
 {
 	PurplePlugin *plugin;
-	FinchPluginFrame callback;
+	PurplePluginInfo *info;
+	FinchPluginInfoPrivate *priv = NULL;
 
 	g_return_if_fail(plugins.tree != NULL);
 
@@ -203,17 +332,21 @@
 	if (confwins && g_hash_table_lookup(confwins, plugin))
 		return;
 
-	if (PURPLE_IS_GNT_PLUGIN(plugin) &&
-			(callback = FINCH_PLUGIN_UI_INFO(plugin)) != NULL)
+	info = purple_plugin_get_info(plugin);
+	if (FINCH_IS_PLUGIN_INFO(info))
+		priv = FINCH_PLUGIN_INFO_GET_PRIVATE(info);
+
+	if (priv && priv->get_pref_frame != NULL)
 	{
 		GntWidget *window = gnt_vbox_new(FALSE);
 		GntWidget *box, *button;
 
 		gnt_box_set_toplevel(GNT_BOX(window), TRUE);
-		gnt_box_set_title(GNT_BOX(window), plugin->info->name);
+		gnt_box_set_title(GNT_BOX(window),
+				purple_plugin_info_get_name(info));
 		gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
 
-		box = callback();
+		box = priv->get_pref_frame();
 		gnt_box_add_widget(GNT_BOX(window), box);
 
 		box = gnt_hbox_new(FALSE);
@@ -231,24 +364,23 @@
 			confwin_init();
 		g_hash_table_insert(confwins, plugin, window);
 	}
-	else if (plugin->info->prefs_info &&
-			plugin->info->prefs_info->get_plugin_pref_frame)
+	else if (purple_plugin_info_get_pref_frame_callback(info))
 	{
-		GntWidget *win = process_pref_frame(plugin->info->prefs_info->get_plugin_pref_frame(plugin));
+		PurplePluginPrefFrameCallback get_pref_frame = purple_plugin_info_get_pref_frame_callback(info);
+		GntWidget *win = process_pref_frame(get_pref_frame(plugin));
 		if (confwins == NULL)
 			confwin_init();
 		g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(remove_confwin), plugin);
 		g_hash_table_insert(confwins, plugin, win);
-		return;
 	}
 	else
 	{
 		purple_notify_info(plugin, _("Error"),
 			_("No configuration options for this plugin."), NULL);
-		return;
 	}
 }
 
+#if 0
 static void
 install_selected_file_cb(gpointer handle, const char *filename)
 {
@@ -335,11 +467,12 @@
 			NULL, NULL, NULL, &handle);
 	g_signal_connect_swapped(G_OBJECT(w), "destroy", G_CALLBACK(purple_request_close_with_handle), &handle);
 }
+#endif
 
-void finch_plugins_show_all()
+void finch_plugins_show_all(void)
 {
 	GntWidget *window, *tree, *box, *aboot, *button;
-	GList *iter;
+	GList *plugin_list, *iter;
 	GList *seen;
 
 	if (plugins.window) {
@@ -347,7 +480,7 @@
 		return;
 	}
 
-	purple_plugins_probe(G_MODULE_SUFFIX);
+	purple_plugins_refresh();
 
 	plugins.window = window = gnt_vbox_new(FALSE);
 	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
@@ -376,29 +509,26 @@
 	gnt_box_add_widget(GNT_BOX(box), aboot);
 
 	seen = purple_prefs_get_path_list("/finch/plugins/seen");
-	for (iter = purple_plugins_get_all(); iter; iter = iter->next)
-	{
-		PurplePlugin *plug = iter->data;
 
-		if (plug->info->type == PURPLE_PLUGIN_LOADER) {
-			GList *cur;
-			for (cur = PURPLE_PLUGIN_LOADER_INFO(plug)->exts; cur != NULL;
-					 cur = cur->next)
-				purple_plugins_probe(cur->data);
-			continue;
-		}
+	plugin_list = purple_plugins_find_all();
+	for (iter = plugin_list; iter; iter = iter->next)
+	{
+		PurplePlugin *plug = PURPLE_PLUGIN(iter->data);
 
-		if (plug->info->type != PURPLE_PLUGIN_STANDARD ||
-			(plug->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE) ||
-			plug->error)
+		if (purple_plugin_is_internal(plug))
 			continue;
 
 		gnt_tree_add_choice(GNT_TREE(tree), plug,
-				gnt_tree_create_row(GNT_TREE(tree), plug->info->name), NULL, NULL);
+				gnt_tree_create_row(GNT_TREE(tree),
+				purple_plugin_info_get_name(purple_plugin_get_info(plug))),
+				NULL, NULL);
 		gnt_tree_set_choice(GNT_TREE(tree), plug, purple_plugin_is_loaded(plug));
-		if (!g_list_find_custom(seen, plug->path, (GCompareFunc)strcmp))
+		if (!g_list_find_custom(seen, purple_plugin_get_filename(plug),
+				(GCompareFunc)strcmp))
 			gnt_tree_set_row_flags(GNT_TREE(tree), plug, GNT_TEXT_FLAG_BOLD);
 	}
+	g_list_free(plugin_list);
+
 	gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
 	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(plugin_toggled_cb), NULL);
 	g_signal_connect(G_OBJECT(tree), "selection_changed", G_CALLBACK(selection_changed), NULL);
@@ -407,10 +537,12 @@
 	box = gnt_hbox_new(FALSE);
 	gnt_box_add_widget(GNT_BOX(window), box);
 
+#if 0
 	button = gnt_button_new(_("Install Plugin..."));
 	gnt_box_add_widget(GNT_BOX(box), button);
 	gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_INS, button);
 	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(install_plugin_cb), NULL);
+#endif
 
 	button = gnt_button_new(_("Close"));
 	gnt_box_add_widget(GNT_BOX(box), button);
--- a/finch/gntplugin.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntplugin.h	Sun Aug 18 01:53:00 2013 +0530
@@ -28,36 +28,87 @@
 
 #include <gnt.h>
 
-#include <plugin.h>
+#include <plugins.h>
 #include <pluginpref.h>
 
 #include <string.h>
 
 #include "finch.h"
 
+#define FINCH_TYPE_PLUGIN_INFO             (finch_plugin_info_get_type())
+#define FINCH_PLUGIN_INFO(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfo))
+#define FINCH_PLUGIN_INFO_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfoClass))
+#define FINCH_IS_PLUGIN_INFO(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), FINCH_TYPE_PLUGIN_INFO))
+#define FINCH_IS_PLUGIN_INFO_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), FINCH_TYPE_PLUGIN_INFO))
+#define FINCH_PLUGIN_INFO_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfoClass))
+
+/** @copydoc _FinchPluginInfo */
+typedef struct _FinchPluginInfo FinchPluginInfo;
+/** @copydoc _FinchPluginInfoClass */
+typedef struct _FinchPluginInfoClass FinchPluginInfoClass;
+
+typedef GntWidget* (*FinchPluginFrame) (void);
+
+/**
+ * Extends #PurplePluginInfo to hold UI information for finch.
+ */
+struct _FinchPluginInfo {
+	/*< private >*/
+	PurplePluginInfo parent;
+};
+
+/**
+ * FinchPluginInfoClass:
+ *
+ * The base class for all #FinchPluginInfo's.
+ */
+struct _FinchPluginInfoClass {
+	/*< private >*/
+	PurplePluginInfoClass parent_class;
+
+	void (*_gnt_reserved1)(void);
+	void (*_gnt_reserved2)(void);
+	void (*_gnt_reserved3)(void);
+	void (*_gnt_reserved4)(void);
+};
+
+/**********************************************************************
+ * @name Plugin Info API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Returns the GType for the FinchPluginInfo object.
+ */
+GType finch_plugin_info_get_type(void);
+
+/**
+ * Creates a new #FinchPluginInfo instance to be returned from
+ * gplugin_plugin_query() of a finch plugin, using the provided name/value
+ * pairs.
+ *
+ * See purple_plugin_info_new() for a list of available property names.
+ * Additionally, you can provide the property "finch-preferences-frame",
+ * which should be a callback that returns a GntWidget for the plugin's
+ * preferences (see FinchPluginFrame).
+ *
+ * @param first_property  The first property name
+ * @param ...  The value of the first property, followed optionally by more
+ *             name/value pairs, followed by @c NULL
+ *
+ * @return A new #FinchPluginInfo instance.
+ *
+ * @see purple_plugin_info_new()
+ */
+FinchPluginInfo *finch_plugin_info_new(const char *first_property, ...);
+
+/*@}*/
+
 /**********************************************************************
  * @name GNT Plugins API
  **********************************************************************/
 /*@{*/
 
-typedef GntWidget* (*FinchPluginFrame) (void);
-
-/* Guess where these came from */
-#define FINCH_PLUGIN_TYPE FINCH_UI
-
-/**
- * Decide whether a plugin is a GNT-plugin.
- */
-#define PURPLE_IS_GNT_PLUGIN(plugin) \
-	((plugin)->info != NULL && (plugin)->info->ui_info != NULL && \
-	 !strcmp((plugin)->info->ui_requirement, FINCH_PLUGIN_TYPE))
-
-/**
- * Get the ui-info from GNT-plugins.
- */
-#define FINCH_PLUGIN_UI_INFO(plugin) \
-	(FinchPluginFrame)((plugin)->info->ui_info)
-
 /**
  * Show a list of plugins.
  */
--- a/finch/gntpounce.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntpounce.c	Sun Aug 18 01:53:00 2013 +0530
@@ -43,7 +43,7 @@
 #include "conversation.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "server.h"
 #include "util.h"
--- a/finch/gntroomlist.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/gntroomlist.c	Sun Aug 18 01:53:00 2013 +0530
@@ -113,15 +113,15 @@
 	char *name;
 	PurpleRoomlistRoom *room = gnt_tree_get_selection_data(GNT_TREE(froomlist.tree));
 	PurpleConnection *gc = purple_account_get_connection(froomlist.account);
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	if (gc == NULL || room == NULL)
 		return;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+	protocol = purple_connection_get_protocol_info(gc);
 
-	if(prpl_info != NULL && prpl_info->roomlist_room_serialize)
-		name = prpl_info->roomlist_room_serialize(room);
+	if(protocol != NULL && protocol->roomlist_room_serialize)
+		name = protocol->roomlist_room_serialize(room);
 	else
 		name = g_strdup(purple_roomlist_room_get_name(room));
 
@@ -237,12 +237,12 @@
 	GntComboBox *accounts = GNT_COMBO_BOX(froomlist.accounts);
 	gnt_combo_box_remove_all(accounts);
 	for (list = purple_connections_get_all(); list; list = list->next) {
-		PurplePluginProtocolInfo *prpl_info = NULL;
+		PurpleProtocol *protocol = NULL;
 		PurpleConnection *gc = list->data;
 
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = purple_connection_get_protocol_info(gc);
 		if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
-		        prpl_info->roomlist_get_list != NULL) {
+		        protocol->roomlist_get_list != NULL) {
 			PurpleAccount *account = purple_connection_get_account(gc);
 			char *text = g_strdup_printf("%s (%s)",
 					purple_account_get_username(account),
--- a/finch/libgnt/wms/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/libgnt/wms/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -35,6 +35,7 @@
 	-I$(top_srcdir)/finch/libgnt \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(GNT_CFLAGS) \
 	$(PLUGIN_CFLAGS)
 
--- a/finch/plugins/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/plugins/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -1,63 +1,64 @@
-gntclipboard_la_LDFLAGS = -module -avoid-version
-gntgf_la_LDFLAGS      = -module -avoid-version
-gnthistory_la_LDFLAGS = -module -avoid-version
-gntlastlog_la_LDFLAGS = -module -avoid-version
-gnttinyurl_la_LDFLAGS = -module -avoid-version
-grouping_la_LDFLAGS   = -module -avoid-version
-
-if PLUGINS
-
-plugin_LTLIBRARIES = \
-	gntclipboard.la \
-	gntgf.la \
-	gnthistory.la \
-	gntlastlog.la \
-	gnttinyurl.la \
-	grouping.la
-
-plugindir = $(libdir)/finch
-
-gntclipboard_la_SOURCES = gntclipboard.c
-gntgf_la_SOURCES      = gntgf.c
-gnthistory_la_SOURCES = gnthistory.c
-gntlastlog_la_SOURCES = lastlog.c
-gnttinyurl_la_SOURCES = gnttinyurl.c
-grouping_la_SOURCES   = grouping.c
-
-gntclipboard_la_CFLAGS = $(X11_CFLAGS)
-gntgf_la_CFLAGS = $(X11_CFLAGS)
-
-gntclipboard_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS)
-gntgf_la_LIBADD       = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/finch/libgnt/libgnt.la
-gnthistory_la_LIBADD  = $(GLIB_LIBS)
-gntlastlog_la_LIBADD  = $(GLIB_LIBS)
-gnttinyurl_la_LIBADD  = $(GLIB_LIBS)
-grouping_la_LIBADD    = $(GLIB_LIBS) $(top_builddir)/finch/libgnt/libgnt.la
-
-endif # PLUGINS
-
-EXTRA_DIST = pietray.py
-
-AM_CPPFLAGS = \
-	-DDATADIR=\"$(datadir)\" \
-	-I$(top_builddir)/libpurple \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/finch \
-	-I$(top_srcdir)/finch/libgnt \
-	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(GNT_CFLAGS) \
-	$(PLUGIN_CFLAGS)
-
+#gntclipboard_la_LDFLAGS = -module -avoid-version
+#gntgf_la_LDFLAGS      = -module -avoid-version
+#gnthistory_la_LDFLAGS = -module -avoid-version
+#gntlastlog_la_LDFLAGS = -module -avoid-version
+#gnttinyurl_la_LDFLAGS = -module -avoid-version
+#grouping_la_LDFLAGS   = -module -avoid-version
+#
+#if PLUGINS
+#
+#plugin_LTLIBRARIES = \
+#	gntclipboard.la \
+#	gntgf.la \
+#	gnthistory.la \
+#	gntlastlog.la \
+#	gnttinyurl.la \
+#	grouping.la
+#
+#plugindir = $(libdir)/finch
+#
+#gntclipboard_la_SOURCES = gntclipboard.c
+#gntgf_la_SOURCES      = gntgf.c
+#gnthistory_la_SOURCES = gnthistory.c
+#gntlastlog_la_SOURCES = lastlog.c
+#gnttinyurl_la_SOURCES = gnttinyurl.c
+#grouping_la_SOURCES   = grouping.c
+#
+#gntclipboard_la_CFLAGS = $(X11_CFLAGS)
+#gntgf_la_CFLAGS = $(X11_CFLAGS)
 #
-# This part allows people to build their own plugins in here.
-# Yes, it's a mess.
+#gntclipboard_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS)
+#gntgf_la_LIBADD       = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/finch/libgnt/libgnt.la
+#gnthistory_la_LIBADD  = $(GLIB_LIBS)
+#gntlastlog_la_LIBADD  = $(GLIB_LIBS)
+#gnttinyurl_la_LIBADD  = $(GLIB_LIBS)
+#grouping_la_LIBADD    = $(GLIB_LIBS) $(top_builddir)/finch/libgnt/libgnt.la
+#
+#endif # PLUGINS
+#
+#EXTRA_DIST = pietray.py
 #
-SUFFIXES = .c .so
-.c.so:
-	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
-	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
-	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
-	@cp .libs/libtmp$@.so.so $@
-	@rm -rf .libs/libtmp$@.*
+#AM_CPPFLAGS = \
+#	-DDATADIR=\"$(datadir)\" \
+#	-I$(top_builddir)/libpurple \
+#	-I$(top_srcdir)/libpurple \
+#	-I$(top_srcdir) \
+#	-I$(top_srcdir)/finch \
+#	-I$(top_srcdir)/finch/libgnt \
+#	$(DEBUG_CFLAGS) \
+#	$(GLIB_CFLAGS) \
+#	$(GPLUGIN_CFLAGS) \
+#	$(GNT_CFLAGS) \
+#	$(PLUGIN_CFLAGS)
+#
+##
+## This part allows people to build their own plugins in here.
+## Yes, it's a mess.
+##
+#SUFFIXES = .c .so
+#.c.so:
+#	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
+#	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
+#	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
+#	@cp .libs/libtmp$@.so.so $@
+#	@rm -rf .libs/libtmp$@.*
--- a/finch/plugins/gntclipboard.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/plugins/gntclipboard.c	Sun Aug 18 01:53:00 2013 +0530
@@ -35,7 +35,7 @@
 
 #include <glib.h>
 
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 #include <debug.h>
 #include <notify.h>
--- a/finch/plugins/gntgf.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/plugins/gntgf.c	Sun Aug 18 01:53:00 2013 +0530
@@ -42,7 +42,7 @@
 
 #include <glib.h>
 
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 #include <buddylist.h>
 #include <conversation.h>
--- a/finch/plugins/gnttinyurl.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/plugins/gnttinyurl.c	Sun Aug 18 01:53:00 2013 +0530
@@ -34,7 +34,7 @@
 
 #include <glib.h>
 
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 #include <debug.h>
 #include <notify.h>
--- a/finch/plugins/lastlog.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/finch/plugins/lastlog.c	Sun Aug 18 01:53:00 2013 +0530
@@ -23,7 +23,7 @@
 
 #include "internal.h"
 
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 
 #include <cmds.h>
--- a/libpurple/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -75,13 +75,13 @@
 	network.c \
 	ntlm.c \
 	notify.c \
-	plugin.c \
+	plugins.c \
 	pluginpref.c \
 	pounce.c \
 	prefs.c \
 	presence.c \
 	proxy.c \
-	prpl.c \
+	protocol.c \
 	request.c \
 	roomlist.c \
 	savedstatuses.c \
@@ -146,13 +146,13 @@
 	network.h \
 	notify.h \
 	ntlm.h \
-	plugin.h \
+	plugins.h \
 	pluginpref.h \
 	pounce.h \
 	prefs.h \
 	presence.h \
 	proxy.h \
-	prpl.h \
+	protocol.h \
 	request.h \
 	roomlist.h \
 	savedstatuses.h \
@@ -231,7 +231,7 @@
                 blistnodetypes.h buddylist.h buddyicon.h connection.h conversation.h \
                 conversationtypes.h conversations.h core.h ft.h log.h notify.h \
                 prefs.h presence.h roomlist.h savedstatuses.h smiley.h status.h \
-                server.h util.h xmlnode.h prpl.h
+                server.h util.h xmlnode.h protocol.h
 
 purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \
 		$(addprefix $(srcdir)/media/, $(purple_mediaheaders)) \
@@ -340,6 +340,7 @@
 	$(STATIC_LINK_LIBS) \
 	$(DBUS_LIBS) \
 	$(GLIB_LIBS) \
+	$(GPLUGIN_LIBS) \
 	$(LIBXML_LIBS) \
 	$(NETWORKMANAGER_LIBS) \
 	$(INTLLIBS) \
@@ -360,6 +361,7 @@
 	-DLOCALEDIR=\"$(datadir)/locale\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(LIBXML_CFLAGS) \
--- a/libpurple/account.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/account.c	Sun Aug 18 01:53:00 2013 +0530
@@ -293,11 +293,11 @@
 purple_account_connect_got_password_cb(PurpleAccount *account,
 	const gchar *password, GError *error, gpointer data)
 {
-	PurplePluginProtocolInfo *prpl_info = data;
+	PurpleProtocol *protocol = data;
 
 	if ((password == NULL || *password == '\0') &&
-		!(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
-		!(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+		!(protocol->options & OPT_PROTO_NO_PASSWORD) &&
+		!(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL))
 		purple_account_request_password(account,
 			G_CALLBACK(request_password_ok_cb),
 			G_CALLBACK(request_password_cancel_cb), account);
@@ -308,9 +308,8 @@
 void
 purple_account_connect(PurpleAccount *account)
 {
-	PurplePlugin *prpl;
 	const char *username;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleAccountPrivate *priv;
 
 	g_return_if_fail(account != NULL);
@@ -324,8 +323,8 @@
 		return;
 	}
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	if (prpl == NULL) {
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+	if (protocol == NULL) {
 		gchar *message;
 
 		message = g_strdup_printf(_("Missing protocol plugin for %s"), username);
@@ -338,13 +337,12 @@
 
 	purple_debug_info("account", "Connecting to account %s.\n", username);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 	if (priv->password != NULL) {
 		purple_account_connect_got_password_cb(account,
-			priv->password, NULL, prpl_info);
+			priv->password, NULL, protocol);
 	} else {
 		purple_keyring_get_password(account,
-			purple_account_connect_got_password_cb, prpl_info);
+			purple_account_connect_got_password_cb, protocol);
 	}
 }
 
@@ -616,8 +614,7 @@
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
 	PurpleConnection *gc;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	char primary[256];
 
 	g_return_if_fail(account != NULL);
@@ -625,9 +622,7 @@
 
 	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);
+		protocol = purple_connection_get_protocol_info(gc);
 
 	fields = purple_request_fields_new();
 
@@ -637,7 +632,7 @@
 	field = purple_request_field_string_new("password", _("Original password"),
 										  NULL, FALSE);
 	purple_request_field_string_set_masked(field, TRUE);
-	if (!prpl_info || !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+	if (!protocol || !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL))
 		purple_request_field_set_required(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
@@ -645,7 +640,7 @@
 										  _("New password"),
 										  NULL, FALSE);
 	purple_request_field_string_set_masked(field, TRUE);
-	if (!prpl_info || !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+	if (!protocol || !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL))
 		purple_request_field_set_required(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
@@ -653,7 +648,7 @@
 										  _("New password (again)"),
 										  NULL, FALSE);
 	purple_request_field_string_set_masked(field, TRUE);
-	if (!prpl_info || !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+	if (!protocol || !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL))
 		purple_request_field_set_required(field, TRUE);
 	purple_request_field_group_add_field(group, field);
 
@@ -1020,18 +1015,16 @@
 		PurpleSetPublicAliasFailureCallback failure_cb)
 {
 	PurpleConnection *gc;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(purple_account_is_connected(account));
 
 	gc = purple_account_get_connection(account);
-	prpl = purple_connection_get_prpl(gc);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, set_public_alias))
-		prpl_info->set_public_alias(gc, alias, success_cb, failure_cb);
+	protocol = purple_connection_get_protocol_info(gc);
+
+	if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, set_public_alias))
+		protocol->set_public_alias(gc, alias, success_cb, failure_cb);
 	else if (failure_cb) {
 		struct public_alias_closure *closure =
 				g_new0(struct public_alias_closure, 1);
@@ -1060,18 +1053,16 @@
 		PurpleGetPublicAliasFailureCallback failure_cb)
 {
 	PurpleConnection *gc;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(purple_account_is_connected(account));
 
 	gc = purple_account_get_connection(account);
-	prpl = purple_connection_get_prpl(gc);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_public_alias))
-		prpl_info->get_public_alias(gc, success_cb, failure_cb);
+	protocol = purple_connection_get_protocol_info(gc);
+
+	if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_public_alias))
+		protocol->get_public_alias(gc, success_cb, failure_cb);
 	else if (failure_cb) {
 		struct public_alias_closure *closure =
 				g_new0(struct public_alias_closure, 1);
@@ -1429,13 +1420,13 @@
 const char *
 purple_account_get_protocol_name(const PurpleAccount *account)
 {
-	PurplePlugin *p;
+	PurpleProtocol *p;
 
 	g_return_val_if_fail(account != NULL, NULL);
 
-	p = purple_find_prpl(purple_account_get_protocol_id(account));
-
-	return ((p && p->info->name) ? _(p->info->name) : _("Unknown"));
+	p = purple_find_protocol_info(purple_account_get_protocol_id(account));
+
+	return ((p && p->name) ? _(p->name) : _("Unknown"));
 }
 
 PurpleConnection *
@@ -2218,40 +2209,32 @@
 void
 purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = 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))
-			prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy), message);
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol != NULL) {
+		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, add_buddy))
+			protocol->add_buddy(gc, buddy, purple_buddy_get_group(buddy), message);
 	}
 }
 
 void
 purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = 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) {
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol) {
 		GList *cur, *groups = NULL;
 
 		/* Make a list of what group each buddy is in */
@@ -2260,13 +2243,13 @@
 			groups = g_list_append(groups, purple_buddy_get_group(buddy));
 		}
 
-		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)) {
+		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, add_buddies))
+			protocol->add_buddies(gc, buddies, groups, message);
+		else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, add_buddy)) {
 			GList *curb = buddies, *curg = groups;
 
 			while ((curb != NULL) && (curg != NULL)) {
-				prpl_info->add_buddy(gc, curb->data, curg->data, message);
+				protocol->add_buddy(gc, curb->data, curg->data, message);
 				curb = curb->next;
 				curg = curg->next;
 			}
@@ -2280,36 +2263,28 @@
 purple_account_remove_buddy(PurpleAccount *account, PurpleBuddy *buddy,
 		PurpleGroup *group)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = 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 && prpl_info->remove_buddy)
-		prpl_info->remove_buddy(gc, buddy, group);
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && protocol->remove_buddy)
+		protocol->remove_buddy(gc, buddy, group);
 }
 
 void
 purple_account_remove_buddies(PurpleAccount *account, GList *buddies, GList *groups)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = 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) {
-		if (prpl_info->remove_buddies)
-			prpl_info->remove_buddies(gc, buddies, groups);
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol) {
+		if (protocol->remove_buddies)
+			protocol->remove_buddies(gc, buddies, groups);
 		else {
 			GList *curb = buddies;
 			GList *curg = groups;
@@ -2325,45 +2300,36 @@
 void
 purple_account_remove_group(PurpleAccount *account, PurpleGroup *group)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = 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 && prpl_info->remove_group)
-		prpl_info->remove_group(gc, group);
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && protocol->remove_group)
+		protocol->remove_group(gc, group);
 }
 
 void
 purple_account_change_password(PurpleAccount *account, const char *orig_pw,
 		const char *new_pw)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurplePlugin *prpl = NULL;
 
 	purple_account_set_password(account, new_pw, NULL, NULL);
 
 	if (gc != NULL)
-		prpl = purple_connection_get_prpl(gc);
-
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info && prpl_info->change_passwd)
-		prpl_info->change_passwd(gc, orig_pw, new_pw);
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && protocol->change_passwd)
+		protocol->change_passwd(gc, orig_pw, new_pw);
 }
 
 gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy)
 {
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info = NULL;
-	PurplePlugin *prpl = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	g_return_val_if_fail(account, FALSE);
 	g_return_val_if_fail(buddy, FALSE);
@@ -2372,14 +2338,11 @@
 	if (gc == NULL)
 		return FALSE;
 
-	prpl = purple_connection_get_prpl(gc);
-
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (!prpl_info || !prpl_info->offline_message)
+	protocol = purple_connection_get_protocol_info(gc);
+
+	if (!protocol || !protocol->offline_message)
 		return FALSE;
-	return prpl_info->offline_message(buddy);
+	return protocol->offline_message(buddy);
 }
 
 void
@@ -2906,8 +2869,7 @@
 	PurpleAccount *account = PURPLE_ACCOUNT(object);
 	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
 	gchar *username, *protocol_id;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleStatusType *status_type;
 
 	parent_class->constructed(object);
@@ -2920,17 +2882,16 @@
 	purple_signal_emit(purple_accounts_get_handle(), "account-created",
 			account);
 
-	prpl = purple_find_prpl(protocol_id);
-	if (prpl == NULL) {
+	protocol = purple_find_protocol_info(protocol_id);
+	if (protocol == NULL) {
 		g_free(username);
 		g_free(protocol_id);
 		return;
 	}
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info != NULL && prpl_info->status_types != NULL)
+	if (protocol->status_types != NULL)
 		purple_account_set_status_types(account,
-				prpl_info->status_types(account));
+				protocol->status_types(account));
 
 	priv->presence = PURPLE_PRESENCE(purple_account_presence_new(account));
 
--- a/libpurple/account.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/account.h	Sun Aug 18 01:53:00 2013 +0530
@@ -53,7 +53,7 @@
 #include "connection.h"
 #include "log.h"
 #include "proxy.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "status.h"
 #include "keyring.h"
 #include "xmlnode.h"
--- a/libpurple/blistnodetypes.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/blistnodetypes.c	Sun Aug 18 01:53:00 2013 +0530
@@ -628,19 +628,15 @@
 {
 	PurpleBuddy *buddy = PURPLE_BUDDY(object);
 	PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy);
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	/*
 	 * Tell the owner PRPL that we're about to free the buddy so it
 	 * can free proto_data
 	 */
-	prpl = purple_find_prpl(purple_account_get_protocol_id(priv->account));
-	if (prpl) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-		if (prpl_info && prpl_info->buddy_free)
-			prpl_info->buddy_free(buddy);
-	}
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(priv->account));
+	if (protocol && protocol->buddy_free)
+		protocol->buddy_free(buddy);
 
 	/* Delete the node */
 	purple_buddy_icon_unref(priv->icon);
@@ -1119,18 +1115,16 @@
 const char *purple_chat_get_name_only(PurpleChat *chat)
 {
 	char *ret = NULL;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
 
 	g_return_val_if_fail(priv != NULL, NULL);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(priv->account));
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(priv->account));
 
-	if (prpl_info->chat_info) {
+	if (protocol->chat_info) {
 		struct proto_chat_entry *pce;
-		GList *parts = prpl_info->chat_info(purple_account_get_connection(priv->account));
+		GList *parts = protocol->chat_info(purple_account_get_connection(priv->account));
 		pce = parts->data;
 		ret = g_hash_table_lookup(priv->components, pce->identifier);
 		g_list_foreach(parts, (GFunc)g_free, NULL);
@@ -1522,19 +1516,15 @@
 		for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) {
 			PurpleAccount *account = accts->data;
 			PurpleConnection *gc = NULL;
-			PurplePlugin *prpl = NULL;
-			PurplePluginProtocolInfo *prpl_info = NULL;
+			PurpleProtocol *protocol = NULL;
 			GList *l = NULL, *buddies = NULL;
 
 			gc = purple_account_get_connection(account);
 
 			if(gc)
-				prpl = purple_connection_get_prpl(gc);
+				protocol = purple_connection_get_protocol_info(gc);
 
-			if(gc && prpl)
-				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-			if(!prpl_info)
+			if(!protocol)
 				continue;
 
 			for(l = moved_buddies; l; l = l->next) {
@@ -1544,8 +1534,8 @@
 					buddies = g_list_append(buddies, (PurpleBlistNode *)buddy);
 			}
 
-			if(prpl_info->rename_group) {
-				prpl_info->rename_group(gc, old_name, source, buddies);
+			if(protocol->rename_group) {
+				protocol->rename_group(gc, old_name, source, buddies);
 			} else {
 				GList *cur, *groups = NULL;
 
--- a/libpurple/buddyicon.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/buddyicon.c	Sun Aug 18 01:53:00 2013 +0530
@@ -745,13 +745,13 @@
 	if (!purple_account_is_disconnected(account))
 	{
 		PurpleConnection *gc;
-		PurplePluginProtocolInfo *prpl_info;
+		PurpleProtocol *protocol;
 
 		gc = purple_account_get_connection(account);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info && prpl_info->set_buddy_icon)
-			prpl_info->set_buddy_icon(gc, img);
+		if (protocol && protocol->set_buddy_icon)
+			protocol->set_buddy_icon(gc, img);
 	}
 
 	if (old_img)
--- a/libpurple/buddyicon.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/buddyicon.h	Sun Aug 18 01:53:00 2013 +0530
@@ -38,7 +38,7 @@
 #include "account.h"
 #include "buddylist.h"
 #include "imgstore.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 
 G_BEGIN_DECLS
--- a/libpurple/buddylist.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/buddylist.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "notify.h"
 #include "pounce.h"
 #include "prefs.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "server.h"
 #include "signals.h"
 #include "util.h"
@@ -1622,8 +1622,7 @@
 {
 	char *chat_name;
 	PurpleChat *chat;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	struct proto_chat_entry *pce;
 	PurpleBlistNode *node, *group;
 	GList *parts;
@@ -1635,11 +1634,10 @@
 	if (!purple_account_is_connected(account))
 		return NULL;
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
-	if (prpl_info->find_blist_chat != NULL)
-		return prpl_info->find_blist_chat(account, name);
+	if (protocol->find_blist_chat != NULL)
+		return protocol->find_blist_chat(account, name);
 
 	normname = g_strdup(purple_normalize(account, name));
 	for (group = purplebuddylist->root; group != NULL; group = group->next) {
@@ -1651,7 +1649,7 @@
 				if (account != purple_chat_get_account(chat))
 					continue;
 
-				parts = prpl_info->chat_info(
+				parts = protocol->chat_info(
 					purple_account_get_connection(purple_chat_get_account(chat)));
 
 				pce = parts->data;
--- a/libpurple/ciphers/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/ciphers/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -24,6 +24,7 @@
 	$(INTGG_CFLAGS) \
 	$(AM_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS) \
 	$(GNUTLS_CFLAGS) \
 	$(NSS_CFLAGS)
--- a/libpurple/cmds.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/cmds.c	Sun Aug 18 01:53:00 2013 +0530
@@ -36,7 +36,7 @@
 	gchar *args;
 	PurpleCmdPriority priority;
 	PurpleCmdFlag flags;
-	gchar *prpl_id;
+	gchar *protocol_id;
 	PurpleCmdFunc func;
 	gchar *help;
 	void *data;
@@ -54,7 +54,7 @@
 
 PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args,
                             PurpleCmdPriority p, PurpleCmdFlag f,
-                            const gchar *prpl_id, PurpleCmdFunc func,
+                            const gchar *protocol_id, PurpleCmdFunc func,
                             const gchar *helpstr, void *data)
 {
 	PurpleCmdId id;
@@ -72,7 +72,7 @@
 	c->args = g_strdup(args);
 	c->priority = p;
 	c->flags = f;
-	c->prpl_id = g_strdup(prpl_id);
+	c->protocol_id = g_strdup(protocol_id);
 	c->func = func;
 	c->help = g_strdup(helpstr);
 	c->data = data;
@@ -88,7 +88,7 @@
 {
 	g_free(c->cmd);
 	g_free(c->args);
-	g_free(c->prpl_id);
+	g_free(c->protocol_id);
 	g_free(c->help);
 	g_free(c);
 }
@@ -203,14 +203,14 @@
 	GList *l;
 	gchar *err = NULL;
 	gboolean is_im = TRUE;
-	gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_prpl = FALSE;
-	const gchar *prpl_id;
+	gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_protocol = FALSE;
+	const gchar *protocol_id;
 	gchar **args = NULL;
 	gchar *cmd, *rest, *mrest;
 	PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE;
 
 	*error = NULL;
-	prpl_id = purple_account_get_protocol_id(purple_conversation_get_account(conv));
+	protocol_id = purple_account_get_protocol_id(purple_conversation_get_account(conv));
 
 	if (PURPLE_IS_CHAT_CONVERSATION(conv))
 		is_im = FALSE;
@@ -244,11 +244,11 @@
 
 		right_type = TRUE;
 
-		if ((c->flags & PURPLE_CMD_FLAG_PRPL_ONLY) &&
-		    !purple_strequal(c->prpl_id, prpl_id))
+		if ((c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) &&
+		    !purple_strequal(c->protocol_id, protocol_id))
 			continue;
 
-		right_prpl = TRUE;
+		right_protocol = TRUE;
 
 		/* this checks the allow bad args flag for us */
 		if (!purple_cmd_parse_args(c, rest, mrest, &args)) {
@@ -280,8 +280,8 @@
 
 	if (!right_type)
 		return PURPLE_CMD_STATUS_WRONG_TYPE;
-	if (!right_prpl)
-		return PURPLE_CMD_STATUS_WRONG_PRPL;
+	if (!right_protocol)
+		return PURPLE_CMD_STATUS_WRONG_PROTOCOL;
 	if (!tried_cmd)
 		return PURPLE_CMD_STATUS_WRONG_ARGS;
 
@@ -314,8 +314,8 @@
 			if (!(c->flags & PURPLE_CMD_FLAG_CHAT))
 				continue;
 
-		if (conv && (c->flags & PURPLE_CMD_FLAG_PRPL_ONLY) &&
-		    !purple_strequal(c->prpl_id, purple_account_get_protocol_id(purple_conversation_get_account(conv))))
+		if (conv && (c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) &&
+		    !purple_strequal(c->protocol_id, purple_account_get_protocol_id(purple_conversation_get_account(conv))))
 			continue;
 
 		ret = g_list_append(ret, c->cmd);
@@ -346,8 +346,8 @@
 			if (!(c->flags & PURPLE_CMD_FLAG_CHAT))
 				continue;
 
-		if (conv && (c->flags & PURPLE_CMD_FLAG_PRPL_ONLY) &&
-		    !purple_strequal(c->prpl_id, purple_account_get_protocol_id(purple_conversation_get_account(conv))))
+		if (conv && (c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) &&
+		    !purple_strequal(c->protocol_id, purple_account_get_protocol_id(purple_conversation_get_account(conv))))
 			continue;
 
 		ret = g_list_append(ret, c->help);
--- a/libpurple/cmds.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/cmds.h	Sun Aug 18 01:53:00 2013 +0530
@@ -37,7 +37,7 @@
 	PURPLE_CMD_STATUS_FAILED,
 	PURPLE_CMD_STATUS_NOT_FOUND,
 	PURPLE_CMD_STATUS_WRONG_ARGS,
-	PURPLE_CMD_STATUS_WRONG_PRPL,
+	PURPLE_CMD_STATUS_WRONG_PROTOCOL,
 	PURPLE_CMD_STATUS_WRONG_TYPE
 } PurpleCmdStatus;
 
@@ -72,7 +72,7 @@
 	PURPLE_CMD_P_VERY_LOW  = -1000,
 	PURPLE_CMD_P_LOW       =     0,
 	PURPLE_CMD_P_DEFAULT   =  1000,
-	PURPLE_CMD_P_PRPL      =  2000,
+	PURPLE_CMD_P_PROTOCOL      =  2000,
 	PURPLE_CMD_P_PLUGIN    =  3000,
 	PURPLE_CMD_P_ALIAS     =  4000,
 	PURPLE_CMD_P_HIGH      =  5000,
@@ -91,7 +91,7 @@
 	/** Command is usable in multi-user chats. */
 	PURPLE_CMD_FLAG_CHAT             = 0x02,
 	/** Command is usable only for a particular prpl. */
-	PURPLE_CMD_FLAG_PRPL_ONLY        = 0x04,
+	PURPLE_CMD_FLAG_PROTOCOL_ONLY        = 0x04,
 	/** Incorrect arguments to this command should be accepted anyway. */
 	PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS = 0x08
 } PurpleCmdFlag;
@@ -139,7 +139,7 @@
  *          <tt>|</tt> (bitwise OR). You need to at least pass one of
  *          #PURPLE_CMD_FLAG_IM or #PURPLE_CMD_FLAG_CHAT (you may pass both) in
  *          order for the command to ever actually be called.
- * @param prpl_id If the #PURPLE_CMD_FLAG_PRPL_ONLY flag is set, this is the id
+ * @param protocol_id If the #PURPLE_CMD_FLAG_PROTOCOL_ONLY flag is set, this is the id
  *                of the prpl to which the command applies (such as
  *                <tt>"prpl-msn"</tt>). If the flag is not set, this parameter
  *                is ignored; pass @c NULL (or a humourous string of your
@@ -157,7 +157,7 @@
  *         #purple_cmd_unregister, or @a 0 on failure.
  */
 PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args, PurpleCmdPriority p, PurpleCmdFlag f,
-                             const gchar *prpl_id, PurpleCmdFunc func, const gchar *helpstr, void *data);
+                             const gchar *protocol_id, PurpleCmdFunc func, const gchar *helpstr, void *data);
 
 /**
  * Unregister a command with the core.
--- a/libpurple/connection.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/connection.c	Sun Aug 18 01:53:00 2013 +0530
@@ -53,7 +53,7 @@
 /** Private data for a connection */
 struct _PurpleConnectionPrivate
 {
-	PurplePlugin *prpl;           /**< The protocol plugin.              */
+	PurpleProtocol *protocol;     /**< The protocol.                     */
 	PurpleConnectionFlags flags;  /**< Connection flags.                 */
 
 	PurpleConnectionState state;  /**< The connection state.             */
@@ -88,7 +88,7 @@
 enum
 {
 	PROP_0,
-	PROP_PRPL,
+	PROP_PROTOCOL,
 	PROP_FLAGS,
 	PROP_STATE,
 	PROP_ACCOUNT,
@@ -112,7 +112,6 @@
 send_keepalive(gpointer data)
 {
 	PurpleConnection *gc = data;
-	PurplePluginProtocolInfo *prpl_info;
 	PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc);
 
 	/* Only send keep-alives if we haven't heard from the
@@ -121,9 +120,8 @@
 	if ((time(NULL) - priv->last_received) < KEEPALIVE_INTERVAL)
 		return TRUE;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl);
-	if (prpl_info->keepalive)
-		prpl_info->keepalive(gc);
+	if (priv->protocol->keepalive)
+		priv->protocol->keepalive(gc);
 
 	return TRUE;
 }
@@ -131,13 +129,11 @@
 static void
 update_keepalive(PurpleConnection *gc, gboolean on)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc);
 
-	if (priv != NULL && priv->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl);
+	g_return_if_fail(priv != NULL);
 
-	if (!prpl_info || !prpl_info->keepalive)
+	if (!priv->protocol->keepalive)
 		return;
 
 	if (on && !priv->keepalive)
@@ -320,14 +316,14 @@
 	return priv->account;
 }
 
-PurplePlugin *
-purple_connection_get_prpl(const PurpleConnection *gc)
+PurpleProtocol *
+purple_connection_get_protocol_info(const PurpleConnection *gc)
 {
 	PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc);
 
 	g_return_val_if_fail(priv != NULL, NULL);
 
-	return priv->prpl;
+	return priv->protocol;
 }
 
 const char *
@@ -604,7 +600,7 @@
  * GObject code
  **************************************************************************/
 /* GObject Property names */
-#define PROP_PRPL_S          "prpl"
+#define PROP_PROTOCOL_S      "protocol"
 #define PROP_FLAGS_S         "flags"
 #define PROP_STATE_S         "state"
 #define PROP_ACCOUNT_S       "account"
@@ -620,9 +616,8 @@
 	PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc);
 
 	switch (param_id) {
-		case PROP_PRPL:
-#warning TODO: change get_pointer to get_object when prpl is a GObject
-			priv->prpl = g_value_get_pointer(value);
+		case PROP_PROTOCOL:
+			priv->protocol = g_value_get_object(value);
 			break;
 		case PROP_FLAGS:
 			purple_connection_set_flags(gc, g_value_get_flags(value));
@@ -654,9 +649,8 @@
 	PurpleConnection *gc = PURPLE_CONNECTION(obj);
 
 	switch (param_id) {
-		case PROP_PRPL:
-#warning TODO: change set_pointer to set_object when prpl is a GObject
-			g_value_set_pointer(value, purple_connection_get_prpl(gc));
+		case PROP_PROTOCOL:
+			g_value_set_object(value, purple_connection_get_protocol_info(gc));
 			break;
 		case PROP_FLAGS:
 			g_value_set_flags(value, purple_connection_get_flags(gc));
@@ -714,7 +708,6 @@
 	PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc);
 	PurpleAccount *account;
 	GSList *buddies;
-	PurplePluginProtocolInfo *prpl_info = NULL;
 	gboolean remove = FALSE;
 
 	account = purple_connection_get_account(gc);
@@ -739,9 +732,8 @@
 	purple_http_conn_cancel_all(gc);
 	purple_proxy_connect_cancel_with_handle(gc);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl);
-	if (prpl_info->close)
-		(prpl_info->close)(gc);
+	if (priv->protocol->close)
+		priv->protocol->close(gc);
 
 	/* Clear out the proto data that was freed in the prpl close method*/
 	buddies = purple_blist_find_buddies(account, NULL);
@@ -803,10 +795,10 @@
 	obj_class->get_property = purple_connection_get_property;
 	obj_class->set_property = purple_connection_set_property;
 
-#warning TODO: change spec_pointer to spec_object when prpl is a GObject
-	g_object_class_install_property(obj_class, PROP_PRPL,
-			g_param_spec_pointer(PROP_PRPL_S, _("Protocol plugin"),
-				_("The prpl that is using the connection."),
+	g_object_class_install_property(obj_class, PROP_PROTOCOL,
+			g_param_spec_object(PROP_PROTOCOL_S, _("Protocol"),
+				_("The protocol that the connection is using."),
+				PURPLE_TYPE_PROTOCOL,
 				G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)
 			);
 
@@ -875,19 +867,16 @@
 _purple_connection_new(PurpleAccount *account, gboolean regist, const char *password)
 {
 	PurpleConnection *gc;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	g_return_if_fail(account != NULL);
 
 	if (!purple_account_is_disconnected(account))
 		return;
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	else {
+	if (protocol == NULL) {
 		gchar *message;
 
 		message = g_strdup_printf(_("Missing protocol plugin for %s"),
@@ -900,14 +889,14 @@
 
 	if (regist)
 	{
-		if (prpl_info->register_user == NULL)
+		if (protocol->register_user == NULL)
 			return;
 	}
 	else
 	{
 		if (((password == NULL) || (*password == '\0')) &&
-			!(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
-			!(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+			!(protocol->options & OPT_PROTO_NO_PASSWORD) &&
+			!(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL))
 		{
 			purple_debug_error("connection", "Cannot connect to account %s without "
 							 "a password.\n", purple_account_get_username(account));
@@ -916,7 +905,7 @@
 	}
 
 	gc = g_object_new(PURPLE_TYPE_CONNECTION,
-			PROP_PRPL_S,      prpl,
+			PROP_PROTOCOL_S,  protocol,
 			PROP_PASSWORD_S,  password,
 			PROP_ACCOUNT_S,   account,
 			NULL);
@@ -928,14 +917,14 @@
 		/* set this so we don't auto-reconnect after registering */
 		PURPLE_CONNECTION_GET_PRIVATE(gc)->wants_to_die = TRUE;
 
-		prpl_info->register_user(account);
+		protocol->register_user(account);
 	}
 	else
 	{
 		purple_debug_info("connection", "Connecting. gc = %p\n", gc);
 
 		purple_signal_emit(purple_accounts_get_handle(), "account-connecting", account);
-		prpl_info->login(account);
+		protocol->login(account);
 	}
 }
 
@@ -945,16 +934,13 @@
 {
 	/* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */
 	PurpleConnection *gc;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	g_return_if_fail(account != NULL);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	else {
+	if (protocol == NULL) {
 		gchar *message;
 
 		message = g_strdup_printf(_("Missing protocol plugin for %s"),
@@ -965,13 +951,13 @@
 	}
 
 	if (!purple_account_is_disconnected(account)) {
-		prpl_info->unregister_user(account, cb, user_data);
+		protocol->unregister_user(account, cb, user_data);
 		return;
 	}
 
 	if (((password == NULL) || (*password == '\0')) &&
-		!(prpl_info->options & OPT_PROTO_NO_PASSWORD) &&
-		!(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL))
+		!(protocol->options & OPT_PROTO_NO_PASSWORD) &&
+		!(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL))
 	{
 		purple_debug_error("connection", "Cannot connect to account %s without "
 						   "a password.\n", purple_account_get_username(account));
@@ -979,14 +965,14 @@
 	}
 
 	gc = g_object_new(PURPLE_TYPE_CONNECTION,
-			PROP_PRPL_S,      prpl,
+			PROP_PROTOCOL_S,  protocol,
 			PROP_PASSWORD_S,  password,
 			PROP_ACCOUNT_S,   account,
 			NULL);
 
 	purple_debug_info("connection", "Unregistering.  gc = %p\n", gc);
 
-	prpl_info->unregister_user(account, cb, user_data);
+	protocol->unregister_user(account, cb, user_data);
 }
 
 /**************************************************************************
--- a/libpurple/connection.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/connection.h	Sun Aug 18 01:53:00 2013 +0530
@@ -155,7 +155,7 @@
 #include <time.h>
 
 #include "account.h"
-#include "plugin.h"
+#include "protocol.h"
 #include "status.h"
 #include "sslconn.h"
 
@@ -357,7 +357,7 @@
  *
  * @return The protocol plugin.
  */
-PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc);
+PurpleProtocol *purple_connection_get_protocol_info(const PurpleConnection *gc);
 
 /**
  * Returns the connection's password.
--- a/libpurple/conversation.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/conversation.c	Sun Aug 18 01:53:00 2013 +0530
@@ -29,7 +29,7 @@
 #include "imgstore.h"
 #include "notify.h"
 #include "prefs.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "signals.h"
 #include "util.h"
@@ -478,7 +478,7 @@
 						const char *message, PurpleMessageFlags flags,
 						time_t mtime)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConnection *gc = NULL;
 	PurpleAccount *account;
 	PurpleConversationUiOps *ops;
@@ -528,10 +528,10 @@
 	}
 
 	if (account != NULL) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
 		if (PURPLE_IS_IM_CONVERSATION(conv) ||
-			!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+			!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 
 			if (flags & PURPLE_MESSAGE_SEND) {
 				b = purple_blist_find_buddy(account,
--- a/libpurple/conversationtypes.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/conversationtypes.c	Sun Aug 18 01:53:00 2013 +0530
@@ -454,19 +454,19 @@
 {
 	PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object);
 	PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im));
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	const char *name = purple_conversation_get_name(PURPLE_CONVERSATION(im));
 
 	if (gc != NULL)
 	{
 		/* Still connected */
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = purple_connection_get_protocol_info(gc);
 
 		if (purple_prefs_get_bool("/purple/conversations/im/send_typing"))
 			serv_send_typing(gc, name, PURPLE_IM_NOT_TYPING);
 
-		if (gc && prpl_info->convo_closed != NULL)
-			prpl_info->convo_closed(gc, name);
+		if (gc && protocol->convo_closed != NULL)
+			protocol->convo_closed(gc, name);
 	}
 
 	purple_im_conversation_stop_typing_timeout(im);
@@ -833,7 +833,7 @@
 	PurpleChatConversationPrivate *priv;
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	GList *ul, *fl;
 	GList *cbuddies = NULL;
 
@@ -848,8 +848,8 @@
 	account = purple_conversation_get_account(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);
+	protocol = purple_connection_get_protocol_info(gc);
+	g_return_if_fail(protocol != NULL);
 
 	ul = users;
 	fl = flags;
@@ -860,7 +860,7 @@
 		PurpleChatUserFlags flag = GPOINTER_TO_INT(fl->data);
 		const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL);
 
-		if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+		if(!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 			if (purple_strequal(priv->nick, purple_normalize(account, user))) {
 				const char *alias2 = purple_account_get_private_alias(account);
 				if (alias2 != NULL)
@@ -935,7 +935,7 @@
 	PurpleConversationUiOps *ops;
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleChatUser *cb;
 	PurpleChatUserFlags flags;
 	PurpleChatConversationPrivate *priv;
@@ -955,8 +955,8 @@
 
 	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);
+	protocol = purple_connection_get_protocol_info(gc);
+	g_return_if_fail(protocol != NULL);
 
 	if (purple_strequal(priv->nick, purple_normalize(account, old_user))) {
 		const char *alias;
@@ -964,7 +964,7 @@
 		/* Note this for later. */
 		is_me = TRUE;
 
-		if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+		if(!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 			alias = purple_account_get_private_alias(account);
 			if (alias != NULL)
 				new_alias = alias;
@@ -975,7 +975,7 @@
 					new_alias = display_name;
 			}
 		}
-	} else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+	} else if (!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 		PurpleBuddy *buddy;
 		if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), new_user)) != NULL)
 			new_alias = purple_buddy_get_contact_alias(buddy);
@@ -1024,7 +1024,7 @@
 			char *escaped;
 			char *escaped2;
 
-			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+			if (!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 				PurpleBuddy *buddy;
 
 				if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), old_user)) != NULL)
@@ -1062,7 +1062,7 @@
 {
 	PurpleConversation *conv;
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleConversationUiOps *ops;
 	PurpleChatUser *cb;
 	PurpleChatConversationPrivate *priv;
@@ -1078,8 +1078,8 @@
 
 	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);
+	protocol = purple_connection_get_protocol_info(gc);
+	g_return_if_fail(protocol != NULL);
 
 	ops  = purple_conversation_get_ui_ops(conv);
 
@@ -1104,7 +1104,7 @@
 			char *alias_esc;
 			char *tmp;
 
-			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+			if (!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 				PurpleBuddy *buddy;
 
 				if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), user)) != NULL)
--- a/libpurple/core.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/core.c	Sun Aug 18 01:53:00 2013 +0530
@@ -40,7 +40,7 @@
 #include "keyring.h"
 #include "network.h"
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "pounce.h"
 #include "prefs.h"
 #include "proxy.h"
@@ -75,7 +75,8 @@
 static PurpleCoreUiOps *_ops  = NULL;
 static PurpleCore      *_core = NULL;
 
-STATIC_PROTO_INIT
+STATIC_PROTO_LOAD
+STATIC_PROTO_UNLOAD
 
 static void
 purple_core_print_version(void)
@@ -166,17 +167,16 @@
 #endif
 
 	purple_cmds_init();
+	purple_protocols_init();
+
+	/* Load all static protocols. */
+	static_proto_load();
 
 	/* Since plugins get probed so early we should probably initialize their
 	 * subsystem right away too.
 	 */
 	purple_plugins_init();
 
-	/* Initialize all static protocols. */
-	static_proto_init();
-
-	purple_plugins_probe(G_MODULE_SUFFIX);
-
 	purple_keyring_init(); /* before accounts */
 	purple_theme_manager_init();
 
@@ -253,11 +253,6 @@
 	/* The SSL plugins must be uninit before they're unloaded */
 	purple_ssl_uninit();
 
-	/* Unload all non-loader, non-prpl plugins before shutting down
-	 * subsystems. */
-	purple_debug_info("main", "Unloading normal plugins\n");
-	purple_plugins_unload(PURPLE_PLUGIN_STANDARD);
-
 	/* Save .xml files, remove signals, etc. */
 	purple_smileys_uninit();
 	purple_http_uninit();
@@ -280,11 +275,6 @@
 	purple_imgstore_uninit();
 	purple_network_uninit();
 
-	/* Everything after unloading all plugins must not fail if prpls aren't
-	 * around */
-	purple_debug_info("main", "Unloading all plugins\n");
-	purple_plugins_destroy_all();
-
 	ops = purple_core_get_ui_ops();
 	if (ops != NULL && ops->quit != NULL)
 		ops->quit();
@@ -292,6 +282,10 @@
 	/* Everything after prefs_uninit must not try to read any prefs */
 	purple_prefs_uninit();
 	purple_plugins_uninit();
+
+	static_proto_unload();	
+	purple_protocols_uninit();
+
 #ifdef HAVE_DBUS
 	purple_dbus_uninit();
 #endif
--- a/libpurple/example/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/example/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -7,6 +7,7 @@
 	$(DBUS_LIBS) \
 	$(INTLLIBS) \
 	$(GLIB_LIBS) \
+	$(GPLUGIN_LIBS) \
 	$(LIBXML_LIBS) \
 	$(top_builddir)/libpurple/libpurple.la
 
@@ -21,5 +22,6 @@
 	-I$(top_srcdir) \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(LIBXML_CFLAGS)
--- a/libpurple/example/nullclient.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/example/nullclient.c	Sun Aug 18 01:53:00 2013 +0530
@@ -198,11 +198,6 @@
 	 * copy this verbatim. */
 	purple_eventloop_set_ui_ops(&glib_eventloops);
 
-	/* Set path to search for plugins. The core (libpurple) takes care of loading the
-	 * core-plugins, which includes the protocol-plugins. So it is not essential to add
-	 * any path here, but it might be desired, especially for ui-specific plugins. */
-	purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH);
-
 	/* Now that all the essential stuff has been set, let's try to init the core. It's
 	 * necessary to provide a non-NULL name for the current ui to the core. This name
 	 * is used by stuff that depends on this ui, for example the ui-specific plugins. */
@@ -214,6 +209,12 @@
 		abort();
 	}
 
+	/* Set path to search for plugins. The core (libpurple) takes care of loading the
+	 * core-plugins, which includes the protocol-plugins. So it is not essential to add
+	 * any path here, but it might be desired, especially for ui-specific plugins. */
+	purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH);
+	purple_plugins_refresh();
+
 	/* Load the preferences. */
 	purple_prefs_load();
 
@@ -263,10 +264,9 @@
 
 	printf("libpurple initialized.\n");
 
-	iter = purple_plugins_get_protocols();
+	iter = purple_protocols_get_all();
 	for (i = 0; iter; iter = iter->next) {
-		PurplePlugin *plugin = iter->data;
-		PurplePluginInfo *info = plugin->info;
+		PurpleProtocol *info = iter->data;
 		if (info && info->name) {
 			printf("\t%d: %s\n", i++, info->name);
 			names = g_list_append(names, (gpointer)info->id);
--- a/libpurple/ft.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/ft.c	Sun Aug 18 01:53:00 2013 +0530
@@ -55,7 +55,7 @@
 	enum {
 		PURPLE_XFER_READY_NONE = 0x0,
 		PURPLE_XFER_READY_UI   = 0x1,
-		PURPLE_XFER_READY_PRPL = 0x2,
+		PURPLE_XFER_READY_PROTOCOL = 0x2,
 	} ready;
 
 	/* TODO: Should really use a PurpleCircBuffer for this. */
@@ -1307,7 +1307,7 @@
 				}
 
 				/* Need to indicate the prpl is still ready... */
-				priv->ready |= PURPLE_XFER_READY_PRPL;
+				priv->ready |= PURPLE_XFER_READY_PROTOCOL;
 
 				g_return_if_reached();
 			}
@@ -1383,7 +1383,7 @@
 		/* The UI is moderating its side manually */
 		PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
 		if (0 == (priv->ready & PURPLE_XFER_READY_UI)) {
-			priv->ready |= PURPLE_XFER_READY_PRPL;
+			priv->ready |= PURPLE_XFER_READY_PROTOCOL;
 
 			purple_input_remove(xfer->watcher);
 			xfer->watcher = 0;
@@ -1458,7 +1458,7 @@
 	priv = g_hash_table_lookup(xfers_data, xfer);
 	priv->ready |= PURPLE_XFER_READY_UI;
 
-	if (0 == (priv->ready & PURPLE_XFER_READY_PRPL)) {
+	if (0 == (priv->ready & PURPLE_XFER_READY_PROTOCOL)) {
 		purple_debug_misc("xfer", "UI is ready on ft %p, waiting for prpl\n", xfer);
 		return;
 	}
@@ -1480,14 +1480,14 @@
 }
 
 void
-purple_xfer_prpl_ready(PurpleXfer *xfer)
+purple_xfer_protocol_ready(PurpleXfer *xfer)
 {
 	PurpleXferPrivData *priv;
 
 	g_return_if_fail(xfer != NULL);
 
 	priv = g_hash_table_lookup(xfers_data, xfer);
-	priv->ready |= PURPLE_XFER_READY_PRPL;
+	priv->ready |= PURPLE_XFER_READY_PROTOCOL;
 
 	/* I don't think fwrite/fread are ever *not* ready */
 	if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) {
--- a/libpurple/ft.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/ft.h	Sun Aug 18 01:53:00 2013 +0530
@@ -757,7 +757,7 @@
  *
  * @param xfer The file transfer which is ready.
  */
-void purple_xfer_prpl_ready(PurpleXfer *xfer);
+void purple_xfer_protocol_ready(PurpleXfer *xfer);
 
 /**
  * Gets the thumbnail data for a transfer
--- a/libpurple/internal.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/internal.h	Sun Aug 18 01:53:00 2013 +0530
@@ -98,8 +98,6 @@
 #include <langinfo.h>
 #endif
 
-#include <gmodule.h>
-
 #ifdef PURPLE_PLUGINS
 # ifdef HAVE_DLFCN_H
 #  include <dlfcn.h>
@@ -158,6 +156,7 @@
 
 #include "accounts.h"
 #include "connection.h"
+#include "prefs.h"
 
 /* This is for the accounts code to notify the buddy icon code that
  * it's done loading.  We may want to replace this with a signal. */
--- a/libpurple/keyring.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/keyring.c	Sun Aug 18 01:53:00 2013 +0530
@@ -33,6 +33,7 @@
 #include "debug.h"
 #include "internal.h"
 #include "dbus-maybe.h"
+#include "plugins.h"
 
 struct _PurpleKeyring
 {
@@ -1228,7 +1229,7 @@
 purple_keyring_init(void)
 {
 	const gchar *touse;
-	GList *it;
+	GList *plugins, *it;
 
 	purple_keyring_keyrings = NULL;
 	purple_keyring_inuse = NULL;
@@ -1282,24 +1283,28 @@
 
 	purple_keyring_pref_connect();
 
-	for (it = purple_plugins_get_all(); it != NULL; it = it->next)
+	plugins = purple_plugins_find_all();
+	for (it = plugins; it != NULL; it = it->next)
 	{
-		PurplePlugin *plugin = (PurplePlugin *)it->data;
+		PurplePlugin *plugin = PURPLE_PLUGIN(it->data);
+		PurplePluginInfo *info = purple_plugin_get_info(plugin);
 
-		if (plugin->info == NULL || plugin->info->id == NULL)
+		if (info == NULL || purple_plugin_info_get_id(info) == NULL)
 			continue;
-		if (strncmp(plugin->info->id, "keyring-", 8) != 0)
+
+		if (strncmp(purple_plugin_info_get_id(info), "keyring-", 8) != 0)
 			continue;
 
 		if (purple_plugin_is_loaded(plugin))
 			continue;
 
-		if (purple_plugin_load(plugin))
+		if (purple_plugin_load(plugin, NULL))
 		{
 			purple_keyring_loaded_plugins = g_list_append(
 				purple_keyring_loaded_plugins, plugin);
 		}
 	}
+	g_list_free(plugins);
 
 	if (purple_keyring_inuse == NULL)
 		purple_debug_error("keyring", "Selected keyring failed to load\n");
@@ -1328,10 +1333,10 @@
 	for (it = g_list_first(purple_keyring_loaded_plugins); it != NULL;
 		it = g_list_next(it))
 	{
-		PurplePlugin *plugin = (PurplePlugin *)it->data;
+		PurplePlugin *plugin = PURPLE_PLUGIN(it->data);
 		if (g_list_find(purple_plugins_get_loaded(), plugin) == NULL)
 			continue;
-		purple_plugin_unload(plugin);
+		purple_plugin_unload(plugin, NULL);
 	}
 	g_list_free(purple_keyring_loaded_plugins);
 	purple_keyring_loaded_plugins = NULL;
--- a/libpurple/log.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/log.c	Sun Aug 18 01:53:00 2013 +0530
@@ -336,18 +336,17 @@
 char *
 purple_log_get_log_dir(PurpleLogType type, const char *name, PurpleAccount *account)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
-	const char *prpl_name;
+	PurpleProtocol *protocol;
+	const char *protocol_name;
 	char *acct_name;
 	const char *target;
 	char *dir;
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	if (!prpl)
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+	if (!protocol)
 		return NULL;
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	prpl_name = prpl_info->list_icon(account, NULL);
+
+	protocol_name = protocol->list_icon(account, NULL);
 
 	acct_name = g_strdup(purple_escape_filename(purple_normalize(account,
 				purple_account_get_username(account))));
@@ -362,7 +361,7 @@
 		target = purple_escape_filename(purple_normalize(account, name));
 	}
 
-	dir = g_build_filename(purple_user_dir(), "logs", prpl_name, acct_name, target, NULL);
+	dir = g_build_filename(purple_user_dir(), "logs", protocol_name, acct_name, target, NULL);
 
 	g_free(acct_name);
 
@@ -1104,15 +1103,13 @@
 
 		/* Find all the accounts for protocol. */
 		for (account_iter = purple_accounts_get_all() ; account_iter != NULL ; account_iter = account_iter->next) {
-			PurplePlugin *prpl;
-			PurplePluginProtocolInfo *prpl_info;
+			PurpleProtocol *protocol;
 
-			prpl = purple_find_prpl(purple_account_get_protocol_id((PurpleAccount *)account_iter->data));
-			if (!prpl)
+			protocol = purple_find_protocol_info(purple_account_get_protocol_id((PurpleAccount *)account_iter->data));
+			if (!protocol)
 				continue;
-			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-			if (purple_strequal(protocol_unescaped, prpl_info->list_icon((PurpleAccount *)account_iter->data, NULL)))
+			if (purple_strequal(protocol_unescaped, protocol->list_icon((PurpleAccount *)account_iter->data, NULL)))
 				accounts = g_list_prepend(accounts, account_iter->data);
 		}
 		g_free(protocol_unescaped);
@@ -1406,13 +1403,13 @@
 	char *date;
 	char *header;
 	char *escaped_from;
-	PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(log->account));
+	PurpleProtocol *protocol =
+			purple_find_protocol_info(purple_account_get_protocol_id(log->account));
 	PurpleLogCommonLoggerData *data = log->logger_data;
 	gsize written = 0;
 
 	if(!data) {
-		const char *prpl =
-			PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL);
+		const char *prpl = protocol->list_icon(log->account, NULL);
 		const char *date;
 		purple_log_common_writer(log, ".html");
 
@@ -1561,7 +1558,8 @@
 							 const char *from, time_t time, const char *message)
 {
 	char *date;
-	PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(log->account));
+	PurpleProtocol *protocol =
+			purple_find_protocol_info(purple_account_get_protocol_id(log->account));
 	PurpleLogCommonLoggerData *data = log->logger_data;
 	char *stripped = NULL;
 
@@ -1572,8 +1570,7 @@
 		 * creating a new file there would result in empty files in the case
 		 * that you open a convo with someone, but don't say anything.
 		 */
-		const char *prpl =
-			PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL);
+		const char *prpl = protocol->list_icon(log->account, NULL);
 		purple_log_common_writer(log, ".txt");
 
 		data = log->logger_data;
--- a/libpurple/media.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/media.c	Sun Aug 18 01:53:00 2013 +0530
@@ -78,7 +78,7 @@
 	PurpleMediaBackend *backend;
 	gchar *conference_type;
 	gboolean initiator;
-	gpointer prpl_data;
+	gpointer protocol_data;
 
 	GHashTable *sessions;	/* PurpleMediaSession table */
 	GList *participants;
@@ -135,7 +135,7 @@
 	PROP_ACCOUNT,
 	PROP_CONFERENCE_TYPE,
 	PROP_INITIATOR,
-	PROP_PRPL_DATA,
+	PROP_PROTOCOL_DATA,
 };
 #endif
 
@@ -217,7 +217,7 @@
 			FALSE,
 			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
-	g_object_class_install_property(gobject_class, PROP_PRPL_DATA,
+	g_object_class_install_property(gobject_class, PROP_PROTOCOL_DATA,
 			g_param_spec_pointer("prpl-data",
 			"gpointer",
 			"Data the prpl plugin set on the media session.",
@@ -395,8 +395,8 @@
 		case PROP_INITIATOR:
 			media->priv->initiator = g_value_get_boolean(value);
 			break;
-		case PROP_PRPL_DATA:
-			media->priv->prpl_data = g_value_get_pointer(value);
+		case PROP_PROTOCOL_DATA:
+			media->priv->protocol_data = g_value_get_pointer(value);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -429,8 +429,8 @@
 		case PROP_INITIATOR:
 			g_value_set_boolean(value, media->priv->initiator);
 			break;
-		case PROP_PRPL_DATA:
-			g_value_set_pointer(value, media->priv->prpl_data);
+		case PROP_PROTOCOL_DATA:
+			g_value_set_pointer(value, media->priv->protocol_data);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -589,24 +589,24 @@
 }
 
 gpointer
-purple_media_get_prpl_data(PurpleMedia *media)
+purple_media_get_protocol_data(PurpleMedia *media)
 {
 #ifdef USE_VV
-	gpointer prpl_data;
+	gpointer protocol_data;
 	g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
-	g_object_get(G_OBJECT(media), "prpl-data", &prpl_data, NULL);
-	return prpl_data;
+	g_object_get(G_OBJECT(media), "prpl-data", &protocol_data, NULL);
+	return protocol_data;
 #else
 	return NULL;
 #endif
 }
 
 void
-purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data)
+purple_media_set_protocol_data(PurpleMedia *media, gpointer protocol_data)
 {
 #ifdef USE_VV
 	g_return_if_fail(PURPLE_IS_MEDIA(media));
-	g_object_set(G_OBJECT(media), "prpl-data", prpl_data, NULL);
+	g_object_set(G_OBJECT(media), "prpl-data", protocol_data, NULL);
 #endif
 }
 
--- a/libpurple/media.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/media.h	Sun Aug 18 01:53:00 2013 +0530
@@ -108,15 +108,15 @@
  *
  * @return The prpl data retrieved.
  */
-gpointer purple_media_get_prpl_data(PurpleMedia *media);
+gpointer purple_media_get_protocol_data(PurpleMedia *media);
 
 /**
  * Sets the prpl data on the media session.
  *
  * @param media The media session to set the prpl data on.
- * @param prpl_data The data to set on the media session.
+ * @param protocol_data The data to set on the media session.
  */
-void purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data);
+void purple_media_set_protocol_data(PurpleMedia *media, gpointer protocol_data);
 
 /**
  * Signals an error in the media session.
--- a/libpurple/media/backend-fs2.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/media/backend-fs2.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1975,7 +1975,7 @@
 	/* check if the prpl has already specified a relay-info
 	  we need to do this to allow them to override when using non-standard
 	  TURN modes, like Google f.ex. */
-	gboolean got_turn_from_prpl = FALSE;
+	gboolean got_turn_from_protocol = FALSE;
 	int i;
 
 	session = get_session(self, sess_id);
@@ -2015,7 +2015,7 @@
 
 	for (i = 0 ; i < num_params ; i++) {
 		if (purple_strequal(params[i].name, "relay-info")) {
-			got_turn_from_prpl = TRUE;
+			got_turn_from_protocol = TRUE;
 			break;
 		}
 	}
@@ -2039,7 +2039,7 @@
 		++_num_params;
 	}
 
-	if (turn_ip && !strcmp("nice", transmitter) && !got_turn_from_prpl) {
+	if (turn_ip && !strcmp("nice", transmitter) && !got_turn_from_protocol) {
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 		GValueArray *relay_info = g_value_array_new(0);
 G_GNUC_END_IGNORE_DEPRECATIONS
--- a/libpurple/mediamanager.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/mediamanager.c	Sun Aug 18 01:53:00 2013 +0530
@@ -456,7 +456,7 @@
 		GstElement *src = gst_bin_get_by_name(GST_BIN(manager->priv->pipeline), id);
 
 		if (src) {
-			GstElement *capsfilter = gst_bin_get_by_name(GST_BIN(src), "prpl_video_caps");
+			GstElement *capsfilter = gst_bin_get_by_name(GST_BIN(src), "protocol_video_caps");
 			g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
 		}
 
@@ -530,7 +530,7 @@
 				GstElement *capsfilter;
 
 				videoscale = gst_element_factory_make("videoscale", NULL);
-				capsfilter = gst_element_factory_make("capsfilter", "prpl_video_caps");
+				capsfilter = gst_element_factory_make("capsfilter", "protocol_video_caps");
 
 				g_object_set(G_OBJECT(capsfilter),
 					"caps", purple_media_manager_get_video_caps(manager), NULL);
--- a/libpurple/notify.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/notify.h	Sun Aug 18 01:53:00 2013 +0530
@@ -54,8 +54,8 @@
 typedef enum
 {
 	PURPLE_NOTIFY_MESSAGE = 0,   /**< Message notification.         */
-	PURPLE_NOTIFY_EMAIL,         /**< Single email notification.   */
-	PURPLE_NOTIFY_EMAILS,        /**< Multiple email notification. */
+	PURPLE_NOTIFY_EMAIL,         /**< Single email notification.    */
+	PURPLE_NOTIFY_EMAILS,        /**< Multiple email notification.  */
 	PURPLE_NOTIFY_FORMATTED,     /**< Formatted text.               */
 	PURPLE_NOTIFY_SEARCHRESULTS, /**< Buddy search results.         */
 	PURPLE_NOTIFY_USERINFO,      /**< Formatted userinfo text.      */
@@ -716,7 +716,7 @@
 /*@}*/
 
 /**************************************************************************/
-/** @name Notify Subsystem                                         */
+/** @name Notify Subsystem                                                */
 /**************************************************************************/
 /*@{*/
 
--- a/libpurple/plugin.c	Sun Aug 18 01:52:32 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1626 +0,0 @@
-/*
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#define _PURPLE_PLUGIN_C_
-
-#include "internal.h"
-
-#include "accountopt.h"
-#include "core.h"
-#include "dbus-maybe.h"
-#include "debug.h"
-#include "notify.h"
-#include "prefs.h"
-#include "prpl.h"
-#include "request.h"
-#include "signals.h"
-#include "util.h"
-#include "valgrind.h"
-#include "version.h"
-
-typedef struct
-{
-	GHashTable *commands;
-	size_t command_count;
-
-} PurplePluginIpcInfo;
-
-typedef struct
-{
-	PurpleCallback func;
-	PurpleSignalMarshalFunc marshal;
-
-	int num_params;
-	GType *param_types;
-	GType ret_type;
-
-} PurplePluginIpcCommand;
-
-static GList *search_paths     = NULL;
-static GList *plugins          = NULL;
-static GList *loaded_plugins   = NULL;
-static GList *protocol_plugins = NULL;
-#ifdef PURPLE_PLUGINS
-static GList *load_queue       = NULL;
-static GList *plugin_loaders   = NULL;
-static GList *plugins_to_disable = NULL;
-#endif
-
-#ifdef PURPLE_PLUGINS
-
-static gboolean
-has_file_extension(const char *filename, const char *ext)
-{
-	int len, extlen;
-
-	if (filename == NULL || *filename == '\0' || ext == NULL)
-		return 0;
-
-	extlen = strlen(ext);
-	len = strlen(filename) - extlen;
-
-	if (len < 0)
-		return 0;
-
-	return (strncmp(filename + len, ext, extlen) == 0);
-}
-
-static gboolean
-is_native(const char *filename)
-{
-	const char *last_period;
-
-	last_period = strrchr(filename, '.');
-	if (last_period == NULL)
-		return FALSE;
-
-	return !(strcmp(last_period, ".dll") &
-			 strcmp(last_period, ".sl") &
-			 strcmp(last_period, ".so"));
-}
-
-static char *
-purple_plugin_get_basename(const char *filename)
-{
-	const char *basename;
-	const char *last_period;
-
-	basename = strrchr(filename, G_DIR_SEPARATOR);
-	if (basename != NULL)
-		basename++;
-	else
-		basename = filename;
-
-	if (is_native(basename) &&
-		((last_period = strrchr(basename, '.')) != NULL))
-			return g_strndup(basename, (last_period - basename));
-
-	return g_strdup(basename);
-}
-
-static gboolean
-loader_supports_file(PurplePlugin *loader, const char *filename)
-{
-	GList *exts;
-
-	for (exts = PURPLE_PLUGIN_LOADER_INFO(loader)->exts; exts != NULL; exts = exts->next) {
-		if (has_file_extension(filename, (char *)exts->data)) {
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-static PurplePlugin *
-find_loader_for_plugin(const PurplePlugin *plugin)
-{
-	PurplePlugin *loader;
-	GList *l;
-
-	if (plugin->path == NULL)
-		return NULL;
-
-	for (l = purple_plugins_get_loaded(); l != NULL; l = l->next) {
-		loader = l->data;
-
-		if (loader->info->type == PURPLE_PLUGIN_LOADER &&
-			loader_supports_file(loader, plugin->path)) {
-
-			return loader;
-		}
-
-		loader = NULL;
-	}
-
-	return NULL;
-}
-
-#endif /* PURPLE_PLUGINS */
-
-/**
- * Negative if a before b, 0 if equal, positive if a after b.
- */
-static gint
-compare_prpl(PurplePlugin *a, PurplePlugin *b)
-{
-	if(PURPLE_IS_PROTOCOL_PLUGIN(a)) {
-		if(PURPLE_IS_PROTOCOL_PLUGIN(b))
-			return strcmp(a->info->name, b->info->name);
-		else
-			return -1;
-	} else {
-		if(PURPLE_IS_PROTOCOL_PLUGIN(b))
-			return 1;
-		else
-			return 0;
-	}
-}
-
-PurplePlugin *
-purple_plugin_new(gboolean native, const char *path)
-{
-	PurplePlugin *plugin;
-
-	plugin = g_new0(PurplePlugin, 1);
-
-	plugin->native_plugin = native;
-	plugin->path = g_strdup(path);
-
-	PURPLE_DBUS_REGISTER_POINTER(plugin, PurplePlugin);
-
-	return plugin;
-}
-
-PurplePlugin *
-purple_plugin_probe(const char *filename)
-{
-#ifdef PURPLE_PLUGINS
-	PurplePlugin *plugin = NULL;
-	PurplePlugin *loader;
-	gpointer unpunned;
-	gchar *basename = NULL;
-	gboolean (*purple_init_plugin)(PurplePlugin *);
-
-	purple_debug_misc("plugins", "probing %s\n", filename);
-	g_return_val_if_fail(filename != NULL, NULL);
-
-	if (!g_file_test(filename, G_FILE_TEST_EXISTS))
-		return NULL;
-
-	/* If this plugin has already been probed then exit */
-	basename = purple_plugin_get_basename(filename);
-	plugin = purple_plugins_find_with_basename(basename);
-	g_free(basename);
-	if (plugin != NULL)
-	{
-		if (purple_strequal(filename, plugin->path))
-			return plugin;
-		else if (!purple_plugin_is_unloadable(plugin))
-		{
-			purple_debug_warning("plugins", "Not loading %s. "
-							"Another plugin with the same name (%s) has already been loaded.\n",
-							filename, plugin->path);
-			return plugin;
-		}
-		else
-		{
-			/* The old plugin was a different file and it was unloadable.
-			 * There's no guarantee that this new file with the same name
-			 * will be loadable, but unless it fails in one of the silent
-			 * ways and the first one didn't, it's not any worse.  The user
-			 * will still see a greyed-out plugin, which is what we want. */
-			purple_plugin_destroy(plugin);
-		}
-	}
-
-	plugin = purple_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename);
-
-	if (plugin->native_plugin) {
-		const char *error;
-#ifdef _WIN32
-		/* Suppress error popups for failing to load plugins */
-		UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
-#endif
-
-		/*
-		 * We pass G_MODULE_BIND_LOCAL here to prevent symbols from
-		 * plugins being added to the global name space.
-		 *
-		 * G_MODULE_BIND_LOCAL was added in glib 2.3.3.
-		 */
-		plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL);
-
-		if (plugin->handle == NULL)
-		{
-			const char *error = g_module_error();
-			if (error != NULL && purple_str_has_prefix(error, filename))
-			{
-				error = error + strlen(filename);
-
-				/* These are just so we don't crash.  If we
-				 * got this far, they should always be true. */
-				if (*error == ':')
-					error++;
-				if (*error == ' ')
-					error++;
-			}
-
-			if (error == NULL || !*error)
-			{
-				plugin->error = g_strdup(_("Unknown error"));
-				purple_debug_error("plugins", "%s is not loadable: Unknown error\n",
-						 plugin->path);
-			}
-			else
-			{
-				plugin->error = g_strdup(error);
-				purple_debug_error("plugins", "%s is not loadable: %s\n",
-						 plugin->path, plugin->error);
-			}
-			plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
-
-			if (plugin->handle == NULL)
-			{
-#ifdef _WIN32
-				/* Restore the original error mode */
-				SetErrorMode(old_error_mode);
-#endif
-				purple_plugin_destroy(plugin);
-				return NULL;
-			}
-			else
-			{
-				/* We were able to load the plugin with lazy symbol binding.
-				 * This means we're missing some symbol.  Mark it as
-				 * unloadable and keep going so we get the info to display
-				 * to the user so they know to rebuild this plugin. */
-				plugin->unloadable = TRUE;
-			}
-		}
-
-		if (!g_module_symbol(plugin->handle, "purple_init_plugin",
-							 &unpunned))
-		{
-			purple_debug_error("plugins", "%s is not usable because the "
-							 "'purple_init_plugin' symbol could not be "
-							 "found.  Does the plugin call the "
-							 "PURPLE_INIT_PLUGIN() macro?\n", plugin->path);
-
-			g_module_close(plugin->handle);
-			error = g_module_error();
-			if (error != NULL)
-				purple_debug_error("plugins", "Error closing module %s: %s\n",
-								 plugin->path, error);
-			plugin->handle = NULL;
-
-#ifdef _WIN32
-			/* Restore the original error mode */
-			SetErrorMode(old_error_mode);
-#endif
-			purple_plugin_destroy(plugin);
-			return NULL;
-		}
-		purple_init_plugin = unpunned;
-
-#ifdef _WIN32
-		/* Restore the original error mode */
-		SetErrorMode(old_error_mode);
-#endif
-	}
-	else {
-		loader = find_loader_for_plugin(plugin);
-
-		if (loader == NULL) {
-			purple_plugin_destroy(plugin);
-			return NULL;
-		}
-
-		purple_init_plugin = PURPLE_PLUGIN_LOADER_INFO(loader)->probe;
-	}
-
-	if (!purple_init_plugin(plugin) || plugin->info == NULL)
-	{
-		purple_plugin_destroy(plugin);
-		return NULL;
-	}
-	else if (plugin->info->ui_requirement &&
-			!purple_strequal(plugin->info->ui_requirement, purple_core_get_ui()))
-	{
-		plugin->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."),
-					purple_core_get_ui(), plugin->info->ui_requirement);
-		purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n", plugin->path, plugin->error);
-		plugin->unloadable = TRUE;
-		return plugin;
-	}
-
-	/*
-	 * Check to make sure a plugin has defined an id.
-	 * Not having this check caused purple_plugin_unload to
-	 * enter an infinite loop in certain situations by passing
-	 * purple_find_plugin_by_id a NULL value. -- ecoffey
-	 */
-	if (plugin->info->id == NULL || *plugin->info->id == '\0')
-	{
-		plugin->error = g_strdup(_("This plugin has not defined an ID."));
-		purple_debug_error("plugins", "%s is not loadable: info->id is not defined.\n", plugin->path);
-		plugin->unloadable = TRUE;
-		return plugin;
-	}
-
-	/* Really old plugins. */
-	if (plugin->info->magic != PURPLE_PLUGIN_MAGIC)
-	{
-		if (plugin->info->magic >= 2 && plugin->info->magic <= 4)
-		{
-			struct _PurplePluginInfo2
-			{
-				unsigned int api_version;
-				PurplePluginType type;
-				char *ui_requirement;
-				unsigned long flags;
-				GList *dependencies;
-				PurplePluginPriority priority;
-
-				char *id;
-				char *name;
-				char *version;
-				char *summary;
-				char *description;
-				char *author;
-				char *homepage;
-
-				gboolean (*load)(PurplePlugin *plugin);
-				gboolean (*unload)(PurplePlugin *plugin);
-				void (*destroy)(PurplePlugin *plugin);
-
-				void *ui_info;
-				void *extra_info;
-				PurplePluginUiInfo *prefs_info;
-				GList *(*actions)(PurplePlugin *plugin, gpointer context);
-			} *info2 = (struct _PurplePluginInfo2 *)plugin->info;
-
-			/* This leaks... but only for ancient plugins, so deal with it. */
-			plugin->info = g_new0(PurplePluginInfo, 1);
-
-			/* We don't really need all these to display the plugin info, but
-			 * I'm copying them all for good measure. */
-			plugin->info->magic          = info2->api_version;
-			plugin->info->type           = info2->type;
-			plugin->info->ui_requirement = info2->ui_requirement;
-			plugin->info->flags          = info2->flags;
-			plugin->info->dependencies   = info2->dependencies;
-			plugin->info->id             = info2->id;
-			plugin->info->name           = info2->name;
-			plugin->info->version        = info2->version;
-			plugin->info->summary        = info2->summary;
-			plugin->info->description    = info2->description;
-			plugin->info->author         = info2->author;
-			plugin->info->homepage       = info2->homepage;
-			plugin->info->load           = info2->load;
-			plugin->info->unload         = info2->unload;
-			plugin->info->destroy        = info2->destroy;
-			plugin->info->ui_info        = info2->ui_info;
-			plugin->info->extra_info     = info2->extra_info;
-
-			if (info2->api_version >= 3)
-				plugin->info->prefs_info = info2->prefs_info;
-
-			if (info2->api_version >= 4)
-				plugin->info->actions    = info2->actions;
-
-
-			plugin->error = g_strdup_printf(_("Plugin magic mismatch %d (need %d)"),
-							 plugin->info->magic, PURPLE_PLUGIN_MAGIC);
-			purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n",
-					  plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC);
-			plugin->unloadable = TRUE;
-			return plugin;
-		}
-
-		purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n",
-				 plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC);
-		purple_plugin_destroy(plugin);
-		return NULL;
-	}
-
-	if (plugin->info->major_version != PURPLE_MAJOR_VERSION ||
-			plugin->info->minor_version > PURPLE_MINOR_VERSION)
-	{
-		plugin->error = g_strdup_printf(_("ABI version mismatch %d.%d.x (need %d.%d.x)"),
-						 plugin->info->major_version, plugin->info->minor_version,
-						 PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION);
-		purple_debug_error("plugins", "%s is not loadable: ABI version mismatch %d.%d.x (need %d.%d.x)\n",
-				 plugin->path, plugin->info->major_version, plugin->info->minor_version,
-				 PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION);
-		plugin->unloadable = TRUE;
-		return plugin;
-	}
-
-	if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
-	{
-		/* If plugin is a PRPL, make sure it implements the required functions */
-		if ((PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) ||
-		    (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) ||
-		    (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL))
-		{
-			plugin->error = g_strdup(_("Plugin does not implement all required functions (list_icon, login and close)"));
-			purple_debug_error("plugins", "%s is not loadable: %s\n",
-					 plugin->path, plugin->error);
-			plugin->unloadable = TRUE;
-			return plugin;
-		}
-
-		/* For debugging, let's warn about prpl prefs. */
-		if (plugin->info->prefs_info != NULL)
-		{
-			purple_debug_error("plugins", "%s has a prefs_info, but is a prpl. This is no longer supported.\n",
-			                 plugin->path);
-		}
-	}
-
-	return plugin;
-#else
-	return NULL;
-#endif /* !PURPLE_PLUGINS */
-}
-
-#ifdef PURPLE_PLUGINS
-static gint
-compare_plugins(gconstpointer a, gconstpointer b)
-{
-	const PurplePlugin *plugina = a;
-	const PurplePlugin *pluginb = b;
-
-	return strcmp(plugina->info->name, pluginb->info->name);
-}
-#endif /* PURPLE_PLUGINS */
-
-gboolean
-purple_plugin_load(PurplePlugin *plugin)
-{
-#ifdef PURPLE_PLUGINS
-	GList *dep_list = NULL;
-	GList *l;
-
-	g_return_val_if_fail(plugin != NULL, FALSE);
-
-	if (purple_plugin_is_loaded(plugin))
-		return TRUE;
-
-	if (purple_plugin_is_unloadable(plugin))
-		return FALSE;
-
-	g_return_val_if_fail(plugin->error == NULL, FALSE);
-
-	/*
-	 * Go through the list of the plugin's dependencies.
-	 *
-	 * First pass: Make sure all the plugins needed are probed.
-	 */
-	for (l = plugin->info->dependencies; l != NULL; l = l->next)
-	{
-		const char *dep_name = (const char *)l->data;
-		PurplePlugin *dep_plugin;
-
-		dep_plugin = purple_plugins_find_with_id(dep_name);
-
-		if (dep_plugin == NULL)
-		{
-			char *tmp;
-
-			tmp = g_strdup_printf(_("The required plugin %s was not found. "
-			                        "Please install this plugin and try again."),
-			                      dep_name);
-
-			purple_notify_error(NULL, NULL,
-			                  _("Unable to load the plugin"), tmp);
-			g_free(tmp);
-
-			g_list_free(dep_list);
-
-			return FALSE;
-		}
-
-		dep_list = g_list_append(dep_list, dep_plugin);
-	}
-
-	/* Second pass: load all the required plugins. */
-	for (l = dep_list; l != NULL; l = l->next)
-	{
-		PurplePlugin *dep_plugin = (PurplePlugin *)l->data;
-
-		if (!purple_plugin_is_loaded(dep_plugin))
-		{
-			if (!purple_plugin_load(dep_plugin))
-			{
-				char *tmp;
-
-				tmp = g_strdup_printf(_("The required plugin %s was unable to load."),
-				                      plugin->info->name);
-
-				purple_notify_error(NULL, NULL,
-				                 _("Unable to load your plugin."), tmp);
-				g_free(tmp);
-
-				g_list_free(dep_list);
-
-				return FALSE;
-			}
-		}
-	}
-
-	/* Third pass: note that other plugins are dependencies of this plugin.
-	 * This is done separately in case we had to bail out earlier. */
-	for (l = dep_list; l != NULL; l = l->next)
-	{
-		PurplePlugin *dep_plugin = (PurplePlugin *)l->data;
-		dep_plugin->dependent_plugins = g_list_prepend(dep_plugin->dependent_plugins, (gpointer)plugin->info->id);
-	}
-
-	g_list_free(dep_list);
-
-	if (plugin->native_plugin)
-	{
-		if (plugin->info->load != NULL && !plugin->info->load(plugin))
-			return FALSE;
-	}
-	else {
-		PurplePlugin *loader;
-		PurplePluginLoaderInfo *loader_info;
-
-		loader = find_loader_for_plugin(plugin);
-
-		if (loader == NULL)
-			return FALSE;
-
-		loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);
-
-		if (loader_info->load != NULL)
-		{
-			if (!loader_info->load(plugin))
-				return FALSE;
-		}
-	}
-
-	loaded_plugins = g_list_insert_sorted(loaded_plugins, plugin, compare_plugins);
-
-	plugin->loaded = TRUE;
-
-	purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
-
-	return TRUE;
-
-#else
-	return TRUE;
-#endif /* !PURPLE_PLUGINS */
-}
-
-gboolean
-purple_plugin_unload(PurplePlugin *plugin)
-{
-#ifdef PURPLE_PLUGINS
-	GList *l;
-	GList *ll;
-
-	g_return_val_if_fail(plugin != NULL, FALSE);
-	g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE);
-
-	purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name);
-
-	/* Unload all plugins that depend on this plugin. */
-	for (l = plugin->dependent_plugins; l != NULL; l = ll) {
-		const char * dep_name = (const char *)l->data;
-		PurplePlugin *dep_plugin;
-
-		/* Store a pointer to the next element in the list.
-		 * This is because we'll be modifying this list in the loop. */
-		ll = l->next;
-
-		dep_plugin = purple_plugins_find_with_id(dep_name);
-
-		if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin))
-		{
-			if (!purple_plugin_unload(dep_plugin))
-			{
-				g_free(plugin->error);
-				plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."),
-				                                _(plugin->info->name),
-				                                _(dep_plugin->info->name));
-				return FALSE;
-			}
-			else
-			{
-#if 0
-				/* This isn't necessary. This has already been done when unloading dep_plugin. */
-				plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l);
-#endif
-			}
-		}
-	}
-
-	/* Remove this plugin from each dependency's dependent_plugins list. */
-	for (l = plugin->info->dependencies; l != NULL; l = l->next)
-	{
-		const char *dep_name = (const char *)l->data;
-		PurplePlugin *dependency;
-
-		dependency = purple_plugins_find_with_id(dep_name);
-
-		if (dependency != NULL)
-			dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id);
-		else
-			purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name);
-	}
-
-	if (plugin->native_plugin) {
-		if (plugin->info->unload && !plugin->info->unload(plugin))
-			return FALSE;
-
-		if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) {
-			PurplePluginProtocolInfo *prpl_info;
-			GList *l;
-
-			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
-			for (l = prpl_info->user_splits; l != NULL; l = l->next)
-				purple_account_user_split_destroy(l->data);
-
-			for (l = prpl_info->protocol_options; l != NULL; l = l->next)
-				purple_account_option_destroy(l->data);
-
-			if (prpl_info->user_splits != NULL) {
-				g_list_free(prpl_info->user_splits);
-				prpl_info->user_splits = NULL;
-			}
-
-			if (prpl_info->protocol_options != NULL) {
-				g_list_free(prpl_info->protocol_options);
-				prpl_info->protocol_options = NULL;
-			}
-		}
-	} else {
-		PurplePlugin *loader;
-		PurplePluginLoaderInfo *loader_info;
-
-		loader = find_loader_for_plugin(plugin);
-
-		if (loader == NULL)
-			return FALSE;
-
-		loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);
-
-		if (loader_info->unload && !loader_info->unload(plugin))
-			return FALSE;
-	}
-
-	/* cancel any pending dialogs the plugin has */
-	purple_request_close_with_handle(plugin);
-	purple_notify_close_with_handle(plugin);
-
-	purple_signals_disconnect_by_handle(plugin);
-	purple_plugin_ipc_unregister_all(plugin);
-
-	loaded_plugins = g_list_remove(loaded_plugins, plugin);
-	if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin))
-		protocol_plugins = g_list_remove(protocol_plugins, plugin);
-	plugins_to_disable = g_list_remove(plugins_to_disable, plugin);
-	plugin->loaded = FALSE;
-
-	/* We wouldn't be anywhere near here if the plugin wasn't loaded, so
-	 * if plugin->error is set at all, it had to be from a previous
-	 * unload failure.  It's obviously okay now.
-	 */
-	g_free(plugin->error);
-	plugin->error = NULL;
-
-	purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin);
-
-	purple_prefs_disconnect_by_handle(plugin);
-
-	return TRUE;
-#else
-	return TRUE;
-#endif /* PURPLE_PLUGINS */
-}
-
-void
-purple_plugin_disable(PurplePlugin *plugin)
-{
-#ifdef PURPLE_PLUGINS
-	g_return_if_fail(plugin != NULL);
-
-	if (!g_list_find(plugins_to_disable, plugin))
-		plugins_to_disable = g_list_prepend(plugins_to_disable, plugin);
-#endif
-}
-
-gboolean
-purple_plugin_reload(PurplePlugin *plugin)
-{
-#ifdef PURPLE_PLUGINS
-	g_return_val_if_fail(plugin != NULL, FALSE);
-	g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE);
-
-	if (!purple_plugin_unload(plugin))
-		return FALSE;
-
-	if (!purple_plugin_load(plugin))
-		return FALSE;
-
-	return TRUE;
-#else
-	return TRUE;
-#endif /* !PURPLE_PLUGINS */
-}
-
-void
-purple_plugin_destroy(PurplePlugin *plugin)
-{
-#ifdef PURPLE_PLUGINS
-	g_return_if_fail(plugin != NULL);
-
-	if (purple_plugin_is_loaded(plugin))
-		purple_plugin_unload(plugin);
-
-	plugins = g_list_remove(plugins, plugin);
-
-	if (load_queue != NULL)
-		load_queue = g_list_remove(load_queue, plugin);
-
-	/* true, this may leak a little memory if there is a major version
-	 * mismatch, but it's a lot better than trying to free something
-	 * we shouldn't, and crashing while trying to load an old plugin */
-	if(plugin->info == NULL || plugin->info->magic != PURPLE_PLUGIN_MAGIC ||
-			plugin->info->major_version != PURPLE_MAJOR_VERSION)
-	{
-		if(plugin->handle)
-			g_module_close(plugin->handle);
-
-		g_free(plugin->path);
-		g_free(plugin->error);
-
-		PURPLE_DBUS_UNREGISTER_POINTER(plugin);
-
-		g_free(plugin);
-		return;
-	}
-
-	if (plugin->info != NULL)
-		g_list_free(plugin->info->dependencies);
-
-	if (plugin->native_plugin)
-	{
-		if (plugin->info != NULL && plugin->info->type == PURPLE_PLUGIN_LOADER)
-		{
-			PurplePluginLoaderInfo *loader_info;
-			GList *exts, *l, *next_l;
-			PurplePlugin *p2;
-
-			loader_info = PURPLE_PLUGIN_LOADER_INFO(plugin);
-
-			if (loader_info != NULL && loader_info->exts != NULL)
-			{
-				for (exts = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts;
-					 exts != NULL;
-					 exts = exts->next) {
-
-					for (l = purple_plugins_get_all(); l != NULL; l = next_l)
-					{
-						next_l = l->next;
-
-						p2 = l->data;
-
-						if (p2->path != NULL &&
-							has_file_extension(p2->path, exts->data))
-						{
-							purple_plugin_destroy(p2);
-						}
-					}
-				}
-
-				g_list_free(loader_info->exts);
-				loader_info->exts = NULL;
-			}
-
-			plugin_loaders = g_list_remove(plugin_loaders, plugin);
-		}
-
-		if (plugin->info != NULL && plugin->info->destroy != NULL)
-			plugin->info->destroy(plugin);
-
-		/*
-		 * I find it extremely useful to do this when using valgrind, as
-		 * it keeps all the plugins open, meaning that valgrind is able to
-		 * resolve symbol names in leak traces from plugins.
-		 */
-		if (!g_getenv("PURPLE_LEAKCHECK_HELP") && !RUNNING_ON_VALGRIND)
-		{
-			if (plugin->handle != NULL)
-				g_module_close(plugin->handle);
-		}
-	}
-	else
-	{
-		PurplePlugin *loader;
-		PurplePluginLoaderInfo *loader_info;
-
-		loader = find_loader_for_plugin(plugin);
-
-		if (loader != NULL)
-		{
-			loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);
-
-			if (loader_info->destroy != NULL)
-				loader_info->destroy(plugin);
-		}
-	}
-
-	g_free(plugin->path);
-	g_free(plugin->error);
-
-	PURPLE_DBUS_UNREGISTER_POINTER(plugin);
-
-	g_free(plugin);
-#endif /* !PURPLE_PLUGINS */
-}
-
-gboolean
-purple_plugin_is_loaded(const PurplePlugin *plugin)
-{
-	g_return_val_if_fail(plugin != NULL, FALSE);
-
-	return plugin->loaded;
-}
-
-gboolean
-purple_plugin_is_unloadable(const PurplePlugin *plugin)
-{
-	g_return_val_if_fail(plugin != NULL, FALSE);
-
-	return plugin->unloadable;
-}
-
-const gchar *
-purple_plugin_get_id(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return plugin->info->id;
-}
-
-const gchar *
-purple_plugin_get_name(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return _(plugin->info->name);
-}
-
-const gchar *
-purple_plugin_get_version(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return plugin->info->version;
-}
-
-const gchar *
-purple_plugin_get_summary(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return _(plugin->info->summary);
-}
-
-const gchar *
-purple_plugin_get_description(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return _(plugin->info->description);
-}
-
-const gchar *
-purple_plugin_get_author(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return _(plugin->info->author);
-}
-
-const gchar *
-purple_plugin_get_homepage(const PurplePlugin *plugin) {
-	g_return_val_if_fail(plugin, NULL);
-	g_return_val_if_fail(plugin->info, NULL);
-
-	return plugin->info->homepage;
-}
-
-/**************************************************************************
- * Plugin IPC
- **************************************************************************/
-static void
-destroy_ipc_info(void *data)
-{
-	PurplePluginIpcCommand *ipc_command = (PurplePluginIpcCommand *)data;
-
-	g_free(ipc_command->param_types);
-	g_free(ipc_command);
-}
-
-gboolean
-purple_plugin_ipc_register(PurplePlugin *plugin, const char *command,
-						 PurpleCallback func, PurpleSignalMarshalFunc marshal,
-						 GType ret_type, int num_params, ...)
-{
-	PurplePluginIpcInfo *ipc_info;
-	PurplePluginIpcCommand *ipc_command;
-
-	g_return_val_if_fail(plugin  != NULL, FALSE);
-	g_return_val_if_fail(command != NULL, FALSE);
-	g_return_val_if_fail(func    != NULL, FALSE);
-	g_return_val_if_fail(marshal != NULL, FALSE);
-
-	if (plugin->ipc_data == NULL)
-	{
-		ipc_info = plugin->ipc_data = g_new0(PurplePluginIpcInfo, 1);
-		ipc_info->commands = g_hash_table_new_full(g_str_hash, g_str_equal,
-												   g_free, destroy_ipc_info);
-	}
-	else
-		ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data;
-
-	ipc_command = g_new0(PurplePluginIpcCommand, 1);
-	ipc_command->func       = func;
-	ipc_command->marshal    = marshal;
-	ipc_command->num_params = num_params;
-	ipc_command->ret_type   = ret_type;
-
-	if (num_params > 0)
-	{
-		va_list args;
-		int i;
-
-		ipc_command->param_types = g_new0(GType, num_params);
-
-		va_start(args, num_params);
-
-		for (i = 0; i < num_params; i++)
-			ipc_command->param_types[i] = va_arg(args, GType);
-
-		va_end(args);
-	}
-
-	g_hash_table_replace(ipc_info->commands, g_strdup(command), ipc_command);
-
-	ipc_info->command_count++;
-
-	return TRUE;
-}
-
-void
-purple_plugin_ipc_unregister(PurplePlugin *plugin, const char *command)
-{
-	PurplePluginIpcInfo *ipc_info;
-
-	g_return_if_fail(plugin  != NULL);
-	g_return_if_fail(command != NULL);
-
-	ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data;
-
-	if (ipc_info == NULL ||
-		g_hash_table_lookup(ipc_info->commands, command) == NULL)
-	{
-		purple_debug_error("plugins",
-						 "IPC command '%s' was not registered for plugin %s\n",
-						 command, plugin->info->name);
-		return;
-	}
-
-	g_hash_table_remove(ipc_info->commands, command);
-
-	ipc_info->command_count--;
-
-	if (ipc_info->command_count == 0)
-	{
-		g_hash_table_destroy(ipc_info->commands);
-		g_free(ipc_info);
-
-		plugin->ipc_data = NULL;
-	}
-}
-
-void
-purple_plugin_ipc_unregister_all(PurplePlugin *plugin)
-{
-	PurplePluginIpcInfo *ipc_info;
-
-	g_return_if_fail(plugin != NULL);
-
-	if (plugin->ipc_data == NULL)
-		return; /* Silently ignore it. */
-
-	ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data;
-
-	g_hash_table_destroy(ipc_info->commands);
-	g_free(ipc_info);
-
-	plugin->ipc_data = NULL;
-}
-
-gboolean
-purple_plugin_ipc_get_types(PurplePlugin *plugin, const char *command,
-						   GType *ret_type, int *num_params,
-						   GType **param_types)
-{
-	PurplePluginIpcInfo *ipc_info;
-	PurplePluginIpcCommand *ipc_command;
-
-	g_return_val_if_fail(plugin  != NULL, FALSE);
-	g_return_val_if_fail(command != NULL, FALSE);
-
-	ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data;
-
-	if (ipc_info == NULL ||
-		(ipc_command = g_hash_table_lookup(ipc_info->commands,
-										   command)) == NULL)
-	{
-		purple_debug_error("plugins",
-						 "IPC command '%s' was not registered for plugin %s\n",
-						 command, plugin->info->name);
-
-		return FALSE;
-	}
-
-	if (num_params != NULL)
-		*num_params = ipc_command->num_params;
-
-	if (param_types != NULL)
-		*param_types = ipc_command->param_types;
-
-	if (ret_type != NULL)
-		*ret_type = ipc_command->ret_type;
-
-	return TRUE;
-}
-
-void *
-purple_plugin_ipc_call(PurplePlugin *plugin, const char *command,
-					 gboolean *ok, ...)
-{
-	PurplePluginIpcInfo *ipc_info;
-	PurplePluginIpcCommand *ipc_command;
-	va_list args;
-	void *ret_value;
-
-	if (ok != NULL)
-		*ok = FALSE;
-
-	g_return_val_if_fail(plugin  != NULL, NULL);
-	g_return_val_if_fail(command != NULL, NULL);
-
-	ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data;
-
-	if (ipc_info == NULL ||
-		(ipc_command = g_hash_table_lookup(ipc_info->commands,
-										   command)) == NULL)
-	{
-		purple_debug_error("plugins",
-						 "IPC command '%s' was not registered for plugin %s\n",
-						 command, plugin->info->name);
-
-		return NULL;
-	}
-
-	va_start(args, ok);
-	ipc_command->marshal(ipc_command->func, args, NULL, &ret_value);
-	va_end(args);
-
-	if (ok != NULL)
-		*ok = TRUE;
-
-	return ret_value;
-}
-
-/**************************************************************************
- * Plugins subsystem
- **************************************************************************/
-void *
-purple_plugins_get_handle(void) {
-	static int handle;
-
-	return &handle;
-}
-
-void
-purple_plugins_init(void) {
-	void *handle = purple_plugins_get_handle();
-
-	purple_plugins_add_search_path(LIBDIR);
-
-	purple_signal_register(handle, "plugin-load",
-						 purple_marshal_VOID__POINTER,
-						 G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN);
-	purple_signal_register(handle, "plugin-unload",
-						 purple_marshal_VOID__POINTER,
-						 G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN);
-}
-
-void
-purple_plugins_uninit(void)
-{
-	void *handle = purple_plugins_get_handle();
-
-	purple_signals_disconnect_by_handle(handle);
-	purple_signals_unregister_by_instance(handle);
-
-	while (search_paths) {
-		g_free(search_paths->data);
-		search_paths = g_list_delete_link(search_paths, search_paths);
-	}
-}
-
-/**************************************************************************
- * Plugins API
- **************************************************************************/
-void
-purple_plugins_add_search_path(const char *path)
-{
-	g_return_if_fail(path != NULL);
-
-	if (g_list_find_custom(search_paths, path, (GCompareFunc)strcmp))
-		return;
-
-	search_paths = g_list_append(search_paths, g_strdup(path));
-}
-
-GList *
-purple_plugins_get_search_paths()
-{
-	return search_paths;
-}
-
-void
-purple_plugins_unload_all(void)
-{
-#ifdef PURPLE_PLUGINS
-
-	while (loaded_plugins != NULL)
-		purple_plugin_unload(loaded_plugins->data);
-
-#endif /* PURPLE_PLUGINS */
-}
-
-void
-purple_plugins_unload(PurplePluginType type)
-{
-#ifdef PURPLE_PLUGINS
-	GList *l;
-
-	for (l = plugins; l; l = l->next) {
-		PurplePlugin *plugin = l->data;
-		if (plugin->info->type == type && purple_plugin_is_loaded(plugin))
-			purple_plugin_unload(plugin);
-	}
-
-#endif /* PURPLE_PLUGINS */
-}
-
-void
-purple_plugins_destroy_all(void)
-{
-#ifdef PURPLE_PLUGINS
-
-	while (plugins != NULL)
-		purple_plugin_destroy(plugins->data);
-
-#endif /* PURPLE_PLUGINS */
-}
-
-void
-purple_plugins_save_loaded(const char *key)
-{
-#ifdef PURPLE_PLUGINS
-	GList *pl;
-	GList *files = NULL;
-
-	for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) {
-		PurplePlugin *plugin = pl->data;
-
-		if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL &&
-		    plugin->info->type != PURPLE_PLUGIN_LOADER &&
-		    !g_list_find(plugins_to_disable, plugin)) {
-			files = g_list_append(files, plugin->path);
-		}
-	}
-
-	purple_prefs_set_path_list(key, files);
-	g_list_free(files);
-#endif
-}
-
-void
-purple_plugins_load_saved(const char *key)
-{
-#ifdef PURPLE_PLUGINS
-	GList *f, *files;
-
-	g_return_if_fail(key != NULL);
-
-	files = purple_prefs_get_path_list(key);
-
-	for (f = files; f; f = f->next)
-	{
-		char *filename;
-		char *basename;
-		PurplePlugin *plugin;
-
-		if (f->data == NULL)
-			continue;
-
-		filename = f->data;
-
-		/*
-		 * We don't know if the filename uses Windows or Unix path
-		 * separators (because people might be sharing a prefs.xml
-		 * file across systems), so we find the last occurrence
-		 * of either.
-		 */
-		basename = strrchr(filename, '/');
-		if ((basename == NULL) || (basename < strrchr(filename, '\\')))
-			basename = strrchr(filename, '\\');
-		if (basename != NULL)
-			basename++;
-
-		/* Strip the extension */
-		if (basename)
-			basename = purple_plugin_get_basename(basename);
-
-		if (((plugin = purple_plugins_find_with_filename(filename)) != NULL) ||
-				(basename && (plugin = purple_plugins_find_with_basename(basename)) != NULL) ||
-				((plugin = purple_plugin_probe(filename)) != NULL))
-		{
-			purple_debug_info("plugins", "Loading saved plugin %s\n",
-							plugin->path);
-			purple_plugin_load(plugin);
-		}
-		else
-		{
-			purple_debug_error("plugins", "Unable to find saved plugin %s\n",
-							 filename);
-		}
-
-		g_free(basename);
-
-		g_free(f->data);
-	}
-
-	g_list_free(files);
-#endif /* PURPLE_PLUGINS */
-}
-
-
-void
-purple_plugins_probe(const char *ext)
-{
-#ifdef PURPLE_PLUGINS
-	GDir *dir;
-	const gchar *file;
-	gchar *path;
-	PurplePlugin *plugin;
-	GList *cur;
-	const char *search_path;
-
-	if (!g_module_supported())
-		return;
-
-	/* Probe plugins */
-	for (cur = search_paths; cur != NULL; cur = cur->next)
-	{
-		search_path = cur->data;
-
-		dir = g_dir_open(search_path, 0, NULL);
-
-		if (dir != NULL)
-		{
-			while ((file = g_dir_read_name(dir)) != NULL)
-			{
-				path = g_build_filename(search_path, file, NULL);
-
-				if (ext == NULL || has_file_extension(file, ext))
-					purple_plugin_probe(path);
-
-				g_free(path);
-			}
-
-			g_dir_close(dir);
-		}
-	}
-
-	/* See if we have any plugins waiting to load */
-	while (load_queue != NULL)
-	{
-		plugin = (PurplePlugin *)load_queue->data;
-
-		load_queue = g_list_remove(load_queue, plugin);
-
-		if (plugin == NULL || plugin->info == NULL)
-			continue;
-
-		if (plugin->info->type == PURPLE_PLUGIN_LOADER)
-		{
-			/* We'll just load this right now. */
-			if (!purple_plugin_load(plugin))
-			{
-				purple_plugin_destroy(plugin);
-
-				continue;
-			}
-
-			plugin_loaders = g_list_append(plugin_loaders, plugin);
-
-			for (cur = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts;
-				 cur != NULL;
-				 cur = cur->next)
-			{
-				purple_plugins_probe(cur->data);
-			}
-		}
-		else if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
-		{
-			/* We'll just load this right now. */
-			if (!purple_plugin_load(plugin))
-			{
-				purple_plugin_destroy(plugin);
-
-				continue;
-			}
-
-			/* Make sure we don't load two PRPLs with the same name? */
-			if (purple_find_prpl(plugin->info->id))
-			{
-				/* Nothing to see here--move along, move along */
-				purple_plugin_destroy(plugin);
-
-				continue;
-			}
-
-			protocol_plugins = g_list_insert_sorted(protocol_plugins, plugin,
-													(GCompareFunc)compare_prpl);
-		}
-	}
-#endif /* PURPLE_PLUGINS */
-}
-
-gboolean
-purple_plugin_register(PurplePlugin *plugin)
-{
-	g_return_val_if_fail(plugin != NULL, FALSE);
-
-	/* If this plugin has been registered already then exit */
-	if (g_list_find(plugins, plugin))
-		return TRUE;
-
-	/* Ensure the plugin has the requisite information */
-	if (plugin->info->type == PURPLE_PLUGIN_LOADER)
-	{
-		PurplePluginLoaderInfo *loader_info;
-
-		loader_info = PURPLE_PLUGIN_LOADER_INFO(plugin);
-
-		if (loader_info == NULL)
-		{
-			purple_debug_error("plugins", "%s is not loadable, loader plugin missing loader_info\n",
-							   plugin->path);
-			return FALSE;
-		}
-	}
-	else if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
-	{
-		PurplePluginProtocolInfo *prpl_info;
-
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
-		if (prpl_info == NULL)
-		{
-			purple_debug_error("plugins", "%s is not loadable, protocol plugin missing prpl_info\n",
-							   plugin->path);
-			return FALSE;
-		}
-	}
-
-#ifdef PURPLE_PLUGINS
-	/* This plugin should be probed and maybe loaded--add it to the queue */
-	load_queue = g_list_append(load_queue, plugin);
-#else
-	if (plugin->info != NULL)
-	{
-		if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
-			protocol_plugins = g_list_insert_sorted(protocol_plugins, plugin,
-													(GCompareFunc)compare_prpl);
-		if (plugin->info->load != NULL)
-			if (!plugin->info->load(plugin))
-				return FALSE;
-	}
-#endif
-
-	plugins = g_list_append(plugins, plugin);
-
-	return TRUE;
-}
-
-gboolean
-purple_plugins_enabled(void)
-{
-#ifdef PURPLE_PLUGINS
-	return TRUE;
-#else
-	return FALSE;
-#endif
-}
-
-PurplePlugin *
-purple_plugins_find_with_name(const char *name)
-{
-	PurplePlugin *plugin;
-	GList *l;
-
-	for (l = plugins; l != NULL; l = l->next) {
-		plugin = l->data;
-
-		if (purple_strequal(plugin->info->name, name))
-			return plugin;
-	}
-
-	return NULL;
-}
-
-PurplePlugin *
-purple_plugins_find_with_filename(const char *filename)
-{
-	PurplePlugin *plugin;
-	GList *l;
-
-	for (l = plugins; l != NULL; l = l->next) {
-		plugin = l->data;
-
-		if (purple_strequal(plugin->path, filename))
-			return plugin;
-	}
-
-	return NULL;
-}
-
-PurplePlugin *
-purple_plugins_find_with_basename(const char *basename)
-{
-#ifdef PURPLE_PLUGINS
-	PurplePlugin *plugin;
-	GList *l;
-	char *tmp;
-
-	g_return_val_if_fail(basename != NULL, NULL);
-
-	for (l = plugins; l != NULL; l = l->next)
-	{
-		plugin = (PurplePlugin *)l->data;
-
-		if (plugin->path != NULL) {
-			tmp = purple_plugin_get_basename(plugin->path);
-			if (purple_strequal(tmp, basename))
-			{
-				g_free(tmp);
-				return plugin;
-			}
-			g_free(tmp);
-		}
-	}
-
-#endif /* PURPLE_PLUGINS */
-
-	return NULL;
-}
-
-PurplePlugin *
-purple_plugins_find_with_id(const char *id)
-{
-	PurplePlugin *plugin;
-	GList *l;
-
-	g_return_val_if_fail(id != NULL, NULL);
-
-	for (l = plugins; l != NULL; l = l->next)
-	{
-		plugin = l->data;
-
-		if (purple_strequal(plugin->info->id, id))
-			return plugin;
-	}
-
-	return NULL;
-}
-
-GList *
-purple_plugins_get_loaded(void)
-{
-	return loaded_plugins;
-}
-
-GList *
-purple_plugins_get_protocols(void)
-{
-	return protocol_plugins;
-}
-
-GList *
-purple_plugins_get_all(void)
-{
-	return plugins;
-}
-
-
-PurplePluginAction *
-purple_plugin_action_new(const char* label, void (*callback)(PurplePluginAction *))
-{
-	PurplePluginAction *act = g_new0(PurplePluginAction, 1);
-
-	act->label = g_strdup(label);
-	act->callback = callback;
-
-	return act;
-}
-
-void
-purple_plugin_action_free(PurplePluginAction *action)
-{
-	g_return_if_fail(action != NULL);
-
-	g_free(action->label);
-	g_free(action);
-}
-
-static PurplePlugin *
-purple_plugin_copy(PurplePlugin *plugin)
-{
-	PurplePlugin *plugin_copy;
-
-	g_return_val_if_fail(plugin != NULL, NULL);
-
-	plugin_copy = g_new(PurplePlugin, 1);
-	*plugin_copy = *plugin;
-
-	return plugin_copy;
-}
-
-GType
-purple_plugin_get_type(void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurplePlugin",
-				(GBoxedCopyFunc)purple_plugin_copy,
-				(GBoxedFreeFunc)g_free);
-	}
-
-	return type;
-}
--- a/libpurple/plugin.h	Sun Aug 18 01:52:32 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,675 +0,0 @@
-/**
- * @file plugin.h Plugin API
- * @ingroup core
- * @see @ref plugin-signals
- * @see @ref plugin-ids
- * @see @ref plugin-i18n
- */
-
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-#ifndef _PURPLE_PLUGIN_H_
-#define _PURPLE_PLUGIN_H_
-
-#include <glib.h>
-#include <gmodule.h>
-#include "signals.h"
-
-/** Returns the GType for the PurplePlugin boxed structure */
-#define PURPLE_TYPE_PLUGIN  (purple_plugin_get_type())
-
-/** @copydoc _PurplePlugin */
-typedef struct _PurplePlugin           PurplePlugin;
-/** @copydoc _PurplePluginInfo */
-typedef struct _PurplePluginInfo       PurplePluginInfo;
-/** @copydoc _PurplePluginUiInfo */
-typedef struct _PurplePluginUiInfo     PurplePluginUiInfo;
-/** @copydoc _PurplePluginLoaderInfo */
-typedef struct _PurplePluginLoaderInfo PurplePluginLoaderInfo;
-
-/** @copydoc _PurplePluginAction */
-typedef struct _PurplePluginAction     PurplePluginAction;
-
-typedef int PurplePluginPriority; /**< Plugin priority. */
-
-#include "pluginpref.h"
-
-/**
- * Plugin types.
- */
-typedef enum
-{
-	PURPLE_PLUGIN_UNKNOWN  = -1,  /**< Unknown type.    */
-	PURPLE_PLUGIN_STANDARD = 0,   /**< Standard plugin. */
-	PURPLE_PLUGIN_LOADER,         /**< Loader plugin.   */
-	PURPLE_PLUGIN_PROTOCOL        /**< Protocol plugin. */
-
-} PurplePluginType;
-
-#define PURPLE_PRIORITY_DEFAULT     0
-#define PURPLE_PRIORITY_HIGHEST  9999
-#define PURPLE_PRIORITY_LOWEST  -9999
-
-#define PURPLE_PLUGIN_FLAG_INVISIBLE 0x01
-
-#define PURPLE_PLUGIN_MAGIC 5 /* once we hit 6.0.0 I think we can remove this */
-
-/**
- * Detailed information about a plugin.
- *
- * This is used in the version 2.0 API and up.
- */
-struct _PurplePluginInfo
-{
-	unsigned int magic;
-	unsigned int major_version;
-	unsigned int minor_version;
-	PurplePluginType type;
-	char *ui_requirement;
-	unsigned long flags;
-	GList *dependencies;
-	PurplePluginPriority priority;
-
-	const char *id;
-	const char *name;
-	const char *version;
-	const char *summary;
-	const char *description;
-	const char *author;
-	const char *homepage;
-
-	/**
-	 * If a plugin defines a 'load' function, and it returns FALSE,
-	 * then the plugin will not be loaded.
-	 */
-	gboolean (*load)(PurplePlugin *plugin);
-	gboolean (*unload)(PurplePlugin *plugin);
-	void (*destroy)(PurplePlugin *plugin);
-
-	void *ui_info; /**< Used only by UI-specific plugins to build a preference screen with a custom UI */
-	void *extra_info;
-	PurplePluginUiInfo *prefs_info; /**< Used by any plugin to display preferences.  If #ui_info has been specified, this will be ignored. */
-
-	/**
-	 * This callback has a different use depending on whether this
-	 * plugin type is PURPLE_PLUGIN_STANDARD or PURPLE_PLUGIN_PROTOCOL.
-	 *
-	 * If PURPLE_PLUGIN_STANDARD then the list of actions will show up
-	 * in the Tools menu, under a submenu with the name of the plugin.
-	 * context will be NULL.
-	 *
-	 * If PURPLE_PLUGIN_PROTOCOL then the list of actions will show up
-	 * in the Accounts menu, under a submenu with the name of the
-	 * account.  context will be set to the PurpleConnection for that
-	 * account.  This callback will only be called for online accounts.
-	 */
-	GList *(*actions)(PurplePlugin *plugin, gpointer context);
-
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-/**
- * Extra information for loader plugins.
- */
-struct _PurplePluginLoaderInfo
-{
-	GList *exts;
-
-	gboolean (*probe)(PurplePlugin *plugin);
-	gboolean (*load)(PurplePlugin *plugin);
-	gboolean (*unload)(PurplePlugin *plugin);
-	void     (*destroy)(PurplePlugin *plugin);
-
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-/**
- * A plugin handle.
- */
-struct _PurplePlugin
-{
-	gboolean native_plugin;                /**< Native C plugin.          */
-	gboolean loaded;                       /**< The loaded state.         */
-	void *handle;                          /**< The module handle.        */
-	char *path;                            /**< The path to the plugin.   */
-	PurplePluginInfo *info;                  /**< The plugin information.   */
-	char *error;
-	void *ipc_data;                        /**< IPC data.                 */
-	void *extra;                           /**< Plugin-specific data.     */
-	gboolean unloadable;                   /**< Unloadable                */
-	GList *dependent_plugins;              /**< Plugins depending on this */
-
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-#define PURPLE_PLUGIN_LOADER_INFO(plugin) \
-	((PurplePluginLoaderInfo *)(plugin)->info->extra_info)
-
-struct _PurplePluginUiInfo {
-	PurplePluginPrefFrame *(*get_plugin_pref_frame)(PurplePlugin *plugin);
-
-	int page_num;                                         /**< Reserved */
-	PurplePluginPrefFrame *frame;                           /**< Reserved */
-
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-#define PURPLE_PLUGIN_HAS_PREF_FRAME(plugin) \
-	((plugin)->info != NULL && (plugin)->info->prefs_info != NULL)
-
-#define PURPLE_PLUGIN_UI_INFO(plugin) \
-	((PurplePluginUiInfo*)(plugin)->info->prefs_info)
-
-
-/**
- * The structure used in the actions member of PurplePluginInfo
- */
-struct _PurplePluginAction {
-	char *label;
-	void (*callback)(PurplePluginAction *);
-
-	/** set to the owning plugin */
-	PurplePlugin *plugin;
-
-	/** NULL for plugin actions menu, set to the PurpleConnection for
-	    account actions menu */
-	gpointer context;
-
-	gpointer user_data;
-};
-
-#define PURPLE_PLUGIN_HAS_ACTIONS(plugin) \
-	((plugin)->info != NULL && (plugin)->info->actions != NULL)
-
-#define PURPLE_PLUGIN_ACTIONS(plugin, context) \
-	(PURPLE_PLUGIN_HAS_ACTIONS(plugin)? \
-	(plugin)->info->actions(plugin, context): NULL)
-
-
-/**
- * Handles the initialization of modules.
- */
-#if !defined(PURPLE_PLUGINS) || defined(PURPLE_STATIC_PRPL)
-# define _FUNC_NAME(x) purple_init_##x##_plugin
-# define PURPLE_INIT_PLUGIN(pluginname, initfunc, plugininfo) \
-	gboolean _FUNC_NAME(pluginname)(void);\
-	gboolean _FUNC_NAME(pluginname)(void) { \
-		PurplePlugin *plugin = purple_plugin_new(TRUE, NULL); \
-		plugin->info = &(plugininfo); \
-		initfunc((plugin)); \
-		purple_plugin_load((plugin)); \
-		return purple_plugin_register(plugin); \
-	}
-#else /* PURPLE_PLUGINS  && !PURPLE_STATIC_PRPL */
-# define PURPLE_INIT_PLUGIN(pluginname, initfunc, plugininfo) \
-	G_MODULE_EXPORT gboolean purple_init_plugin(PurplePlugin *plugin); \
-	G_MODULE_EXPORT gboolean purple_init_plugin(PurplePlugin *plugin) { \
-		plugin->info = &(plugininfo); \
-		initfunc((plugin)); \
-		return purple_plugin_register(plugin); \
-	}
-#endif
-
-
-G_BEGIN_DECLS
-
-/**************************************************************************/
-/** @name Plugin API                                                      */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Returns the GType for the PurplePlugin boxed structure.
- * TODO Boxing of PurplePlugin is a temporary solution to having a GType for
- *      plugins. This should rather be a GObject instead of a GBoxed.
- */
-GType purple_plugin_get_type(void);
-
-/**
- * Creates a new plugin structure.
- *
- * @param native Whether or not the plugin is native.
- * @param path   The path to the plugin, or @c NULL if statically compiled.
- *
- * @return A new PurplePlugin structure.
- */
-PurplePlugin *purple_plugin_new(gboolean native, const char *path);
-
-/**
- * Probes a plugin, retrieving the information on it and adding it to the
- * list of available plugins.
- *
- * @param filename The plugin's filename.
- *
- * @return The plugin handle.
- *
- * @see purple_plugin_load()
- * @see purple_plugin_destroy()
- */
-PurplePlugin *purple_plugin_probe(const char *filename);
-
-/**
- * Registers a plugin and prepares it for loading.
- *
- * This shouldn't be called by anything but the internal module code.
- * Plugins should use the PURPLE_INIT_PLUGIN() macro to register themselves
- * with the core.
- *
- * @param plugin The plugin to register.
- *
- * @return @c TRUE if the plugin was registered successfully.  Otherwise
- *         @c FALSE is returned (this happens if the plugin does not contain
- *         the necessary information).
- */
-gboolean purple_plugin_register(PurplePlugin *plugin);
-
-/**
- * Attempts to load a previously probed plugin.
- *
- * @param plugin The plugin to load.
- *
- * @return @c TRUE if successful, or @c FALSE otherwise.
- *
- * @see purple_plugin_reload()
- * @see purple_plugin_unload()
- */
-gboolean purple_plugin_load(PurplePlugin *plugin);
-
-/**
- * Unloads the specified plugin.
- *
- * @param plugin The plugin handle.
- *
- * @return @c TRUE if successful, or @c FALSE otherwise.
- *
- * @see purple_plugin_load()
- * @see purple_plugin_reload()
- */
-gboolean purple_plugin_unload(PurplePlugin *plugin);
-
-/**
- * Disable a plugin.
- *
- * This function adds the plugin to a list of plugins to "disable at the next
- * 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.
- */
-void purple_plugin_disable(PurplePlugin *plugin);
-
-/**
- * Reloads a plugin.
- *
- * @param plugin The old plugin handle.
- *
- * @return @c TRUE if successful, or @c FALSE otherwise.
- *
- * @see purple_plugin_load()
- * @see purple_plugin_unload()
- */
-gboolean purple_plugin_reload(PurplePlugin *plugin);
-
-/**
- * Unloads a plugin and destroys the structure from memory.
- *
- * @param plugin The plugin handle.
- */
-void purple_plugin_destroy(PurplePlugin *plugin);
-
-/**
- * Returns whether or not a plugin is currently loaded.
- *
- * @param plugin The plugin.
- *
- * @return @c TRUE if loaded, or @c FALSE otherwise.
- */
-gboolean purple_plugin_is_loaded(const PurplePlugin *plugin);
-
-/**
- * Returns whether or not a plugin is unloadable.
- *
- * If this returns @c TRUE, the plugin is guaranteed to not
- * be loadable. However, a return value of @c FALSE does not
- * guarantee the plugin is loadable.
- *
- * @param plugin The plugin.
- *
- * @return @c TRUE if the plugin is known to be unloadable,\
- *         @c FALSE otherwise
- */
-gboolean purple_plugin_is_unloadable(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's id.
- *
- * @param plugin The plugin.
- *
- * @return The plugin's id.
- */
-const gchar *purple_plugin_get_id(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's name.
- *
- * @param plugin The plugin.
- *
- * @return THe name of the plugin, or @c NULL.
- */
-const gchar *purple_plugin_get_name(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's version.
- *
- * @param plugin The plugin.
- *
- * @return The plugin's version or @c NULL.
- */
-const gchar *purple_plugin_get_version(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's summary.
- *
- * @param plugin The plugin.
- *
- * @return The plugin's summary.
- */
-const gchar *purple_plugin_get_summary(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's description.
- *
- * @param plugin The plugin.
- *
- * @return The plugin's description.
- */
-const gchar *purple_plugin_get_description(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's author.
- *
- * @param plugin The plugin.
- *
- * @return The plugin's author.
- */
-const gchar *purple_plugin_get_author(const PurplePlugin *plugin);
-
-/**
- * Returns a plugin's homepage.
- *
- * @param plugin The plugin.
- *
- * @return The plugin's homepage.
- */
-const gchar *purple_plugin_get_homepage(const PurplePlugin *plugin);
-
-/*@}*/
-
-/**************************************************************************/
-/** @name Plugin IPC API                                                  */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Registers an IPC command in a plugin.
- *
- * @param plugin     The plugin to register the command with.
- * @param command    The name of the command.
- * @param func       The function to execute.
- * @param marshal    The marshalling function.
- * @param ret_type   The return type.
- * @param num_params The number of parameters.
- * @param ...        The parameter types.
- *
- * @return TRUE if the function was registered successfully, or
- *         FALSE otherwise.
- */
-gboolean purple_plugin_ipc_register(PurplePlugin *plugin, const char *command,
-								  PurpleCallback func,
-								  PurpleSignalMarshalFunc marshal,
-								  GType ret_type, int num_params, ...);
-
-/**
- * Unregisters an IPC command in a plugin.
- *
- * @param plugin  The plugin to unregister the command from.
- * @param command The name of the command.
- */
-void purple_plugin_ipc_unregister(PurplePlugin *plugin, const char *command);
-
-/**
- * Unregisters all IPC commands in a plugin.
- *
- * @param plugin The plugin to unregister the commands from.
- */
-void purple_plugin_ipc_unregister_all(PurplePlugin *plugin);
-
-/**
- * Returns a list of value types used for an IPC command.
- *
- * @param plugin      The plugin.
- * @param command     The name of the command.
- * @param ret_type    The returned return type.
- * @param num_params  The returned number of parameters.
- * @param param_types The returned list of parameter types.
- *
- * @return TRUE if the command was found, or FALSE otherwise.
- */
-gboolean purple_plugin_ipc_get_types(PurplePlugin *plugin, const char *command,
-									GType *ret_type, int *num_params,
-									GType **param_types);
-
-/**
- * Executes an IPC command.
- *
- * @param plugin  The plugin to execute the command on.
- * @param command The name of the command.
- * @param ok      TRUE if the call was successful, or FALSE otherwise.
- * @param ...     The parameters to pass.
- *
- * @return The return value, which will be NULL if the command doesn't
- *         return a value.
- */
-void *purple_plugin_ipc_call(PurplePlugin *plugin, const char *command,
-						   gboolean *ok, ...);
-
-/*@}*/
-
-/**************************************************************************/
-/** @name Plugins API                                                     */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Add a new directory to search for plugins
- *
- * @param path The new search path.
- */
-void purple_plugins_add_search_path(const char *path);
-
-/**
- * Returns a list of plugin search paths.
- *
- * @constreturn A list of searched paths.
- */
-GList *purple_plugins_get_search_paths(void);
-
-/**
- * Unloads all loaded plugins.
- */
-void purple_plugins_unload_all(void);
-
-/**
- * Unloads all plugins of a specific type.
- */
-void purple_plugins_unload(PurplePluginType type);
-
-/**
- * Destroys all registered plugins.
- */
-void purple_plugins_destroy_all(void);
-
-/**
- * Saves the list of loaded plugins to the specified preference key
- *
- * @param key The preference key to save the list of plugins to.
- */
-void purple_plugins_save_loaded(const char *key);
-
-/**
- * Attempts to load all the plugins in the specified preference key
- * that were loaded when purple last quit.
- *
- * @param key The preference key containing the list of plugins.
- */
-void purple_plugins_load_saved(const char *key);
-
-/**
- * Probes for plugins in the registered module paths.
- *
- * @param ext The extension type to probe for, or @c NULL for all.
- *
- * @see purple_plugin_set_probe_path()
- */
-void purple_plugins_probe(const char *ext);
-
-/**
- * Returns whether or not plugin support is enabled.
- *
- * @return TRUE if plugin support is enabled, or FALSE otherwise.
- */
-gboolean purple_plugins_enabled(void);
-
-/**
- * Finds a plugin with the specified name.
- *
- * @param name The plugin name.
- *
- * @return The plugin if found, or @c NULL if not found.
- */
-PurplePlugin *purple_plugins_find_with_name(const char *name);
-
-/**
- * Finds a plugin with the specified filename (filename with a path).
- *
- * @param filename The plugin filename.
- *
- * @return The plugin if found, or @c NULL if not found.
- */
-PurplePlugin *purple_plugins_find_with_filename(const char *filename);
-
-/**
- * Finds a plugin with the specified basename (filename without a path).
- *
- * @param basename The plugin basename.
- *
- * @return The plugin if found, or @c NULL if not found.
- */
-PurplePlugin *purple_plugins_find_with_basename(const char *basename);
-
-/**
- * Finds a plugin with the specified plugin ID.
- *
- * @param id The plugin ID.
- *
- * @return The plugin if found, or @c NULL if not found.
- */
-PurplePlugin *purple_plugins_find_with_id(const char *id);
-
-/**
- * Returns a list of all loaded plugins.
- *
- * @constreturn A list of all loaded plugins.
- */
-GList *purple_plugins_get_loaded(void);
-
-/**
- * Returns a list of all valid protocol plugins.  A protocol
- * plugin is considered invalid if it does not contain the call
- * to the PURPLE_INIT_PLUGIN() macro, or if it was compiled
- * against an incompatable API version.
- *
- * @constreturn A list of all protocol plugins.
- */
-GList *purple_plugins_get_protocols(void);
-
-/**
- * Returns a list of all plugins, whether loaded or not.
- *
- * @constreturn A list of all plugins.
- */
-GList *purple_plugins_get_all(void);
-
-/*@}*/
-
-/**************************************************************************/
-/** @name Plugins SubSytem API                                            */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Returns the plugin subsystem handle.
- *
- * @return The plugin sybsystem handle.
- */
-void *purple_plugins_get_handle(void);
-
-/**
- * Initializes the plugin subsystem
- */
-void purple_plugins_init(void);
-
-/**
- * Uninitializes the plugin subsystem
- */
-void purple_plugins_uninit(void);
-
-/*@}*/
-
-/**
- * Allocates and returns a new PurplePluginAction.
- *
- * @param label    The description of the action to show to the user.
- * @param callback The callback to call when the user selects this action.
- */
-PurplePluginAction *purple_plugin_action_new(const char* label, void (*callback)(PurplePluginAction *));
-
-/**
- * Frees a PurplePluginAction
- *
- * @param action The PurplePluginAction to free.
- */
-void purple_plugin_action_free(PurplePluginAction *action);
-
-G_END_DECLS
-
-#endif /* _PURPLE_PLUGIN_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins.c	Sun Aug 18 01:53:00 2013 +0530
@@ -0,0 +1,962 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#include "internal.h"
+
+#include "core.h"
+#include "debug.h"
+#include "plugins.h"
+
+#define PURPLE_PLUGIN_INFO_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfoPrivate))
+
+/** @copydoc _PurplePluginInfoPrivate */
+typedef struct _PurplePluginInfoPrivate  PurplePluginInfoPrivate;
+
+/**************************************************************************
+ * Plugin info private data
+ **************************************************************************/
+struct _PurplePluginInfoPrivate {
+	char *ui_requirement;  /**< ID of UI that is required to load the plugin */
+	char *error;           /**< Why a plugin is not loadable                 */
+
+	/** Callback that returns a list of actions the plugin can perform */
+	PurplePluginGetActionsCallback get_actions;
+
+	/** Callback that returns a preferences frame for a plugin */
+	PurplePluginPrefFrameCallback get_pref_frame;
+
+	/** TRUE if a plugin has been unloaded at least once. Load-on-query
+	 *  plugins that have been unloaded once will not be auto-loaded again. */
+	gboolean unloaded;
+};
+
+enum
+{
+	PROP_0,
+	PROP_UI_REQUIREMENT,
+	PROP_GET_ACTIONS,
+	PROP_PREFERENCES_FRAME,
+	PROP_LAST
+};
+
+static GObjectClass *parent_class;
+
+/**************************************************************************
+ * Globals
+ **************************************************************************/
+#ifdef PURPLE_PLUGINS
+static GList *loaded_plugins     = NULL;
+static GList *plugins_to_disable = NULL;
+#endif
+
+/**************************************************************************
+ * Plugin API
+ **************************************************************************/
+gboolean
+purple_plugin_load(PurplePlugin *plugin, GError **error)
+{
+#ifdef PURPLE_PLUGINS
+	GError *err = NULL;
+	PurplePluginInfoPrivate *priv;
+
+	g_return_val_if_fail(plugin != NULL, FALSE);
+
+	if (purple_plugin_is_loaded(plugin))
+		return TRUE;
+
+	priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(purple_plugin_get_info(plugin));
+
+	if (priv->error) {
+		purple_debug_error("plugins", "Failed to load plugin %s: %s",
+		                   purple_plugin_get_filename(plugin), priv->error);
+
+		g_set_error(error, PURPLE_PLUGINS_DOMAIN, 0,
+		            "Plugin is not loadable: %s", priv->error);
+
+		return FALSE;
+	}
+
+	if (!gplugin_plugin_manager_load_plugin(plugin, &err)) {
+		purple_debug_error("plugins", "Failed to load plugin %s: %s",
+				purple_plugin_get_filename(plugin), err->message);
+
+		if (error)
+			*error = g_error_copy(err);
+		g_error_free(err);
+
+		return FALSE;
+	}
+
+	loaded_plugins = g_list_append(loaded_plugins, plugin);
+
+	purple_debug_info("plugins", "Loaded plugin %s\n",
+	                  purple_plugin_get_filename(plugin));
+
+	purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
+
+	return TRUE;
+
+#else
+	g_set_error(error, PURPLE_PLUGINS_DOMAIN, 0, "Plugin support is disabled.");
+	return FALSE;
+#endif /* PURPLE_PLUGINS */
+}
+
+gboolean
+purple_plugin_unload(PurplePlugin *plugin, GError **error)
+{
+#ifdef PURPLE_PLUGINS
+	GError *err = NULL;
+	PurplePluginInfoPrivate *priv;
+
+	g_return_val_if_fail(plugin != NULL, FALSE);
+
+	if (!purple_plugin_is_loaded(plugin))
+		return TRUE;
+
+	priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(purple_plugin_get_info(plugin));
+
+	g_return_val_if_fail(priv != NULL, FALSE);
+
+	purple_debug_info("plugins", "Unloading plugin %s\n",
+			purple_plugin_get_filename(plugin));
+
+	if (!gplugin_plugin_manager_unload_plugin(plugin, &err)) {
+		purple_debug_error("plugins", "Failed to unload plugin %s: %s",
+				purple_plugin_get_filename(plugin), err->message);
+
+		if (error)
+			*error = g_error_copy(err);
+		g_error_free(err);
+
+		return FALSE;
+	}
+
+	/* cancel any pending dialogs the plugin has */
+	purple_request_close_with_handle(plugin);
+	purple_notify_close_with_handle(plugin);
+
+	purple_signals_disconnect_by_handle(plugin);
+	purple_signals_unregister_by_instance(plugin);
+
+	priv->unloaded = TRUE;
+
+	loaded_plugins     = g_list_remove(loaded_plugins, plugin);
+	plugins_to_disable = g_list_remove(plugins_to_disable, plugin);
+
+	purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin);
+
+	purple_prefs_disconnect_by_handle(plugin);
+
+	return TRUE;
+
+#else
+	g_set_error(error, PURPLE_PLUGINS_DOMAIN, 0, "Plugin support is disabled.");
+	return FALSE;
+#endif /* PURPLE_PLUGINS */
+}
+
+gboolean
+purple_plugin_is_loaded(const PurplePlugin *plugin)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(plugin != NULL, FALSE);
+
+	return (gplugin_plugin_get_state(plugin) == GPLUGIN_PLUGIN_STATE_LOADED);
+
+#else
+	return FALSE;
+#endif
+}
+
+const gchar *
+purple_plugin_get_filename(const PurplePlugin *plugin)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(plugin != NULL, NULL);
+
+	return gplugin_plugin_get_filename(plugin);
+
+#else
+	return NULL;
+#endif
+}
+
+PurplePluginInfo *
+purple_plugin_get_info(const PurplePlugin *plugin)
+{
+#ifdef PURPLE_PLUGINS
+	GPluginPluginInfo *info;
+
+	g_return_val_if_fail(plugin != NULL, NULL);
+
+	info = gplugin_plugin_get_info(plugin);
+	g_object_unref(info);
+
+	return PURPLE_PLUGIN_INFO(info);
+
+#else
+	return NULL;
+#endif
+}
+
+void
+purple_plugin_disable(PurplePlugin *plugin)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_if_fail(plugin != NULL);
+
+	if (!g_list_find(plugins_to_disable, plugin))
+		plugins_to_disable = g_list_prepend(plugins_to_disable, plugin);
+#endif
+}
+
+GType
+purple_plugin_register_type(PurplePlugin *plugin, GType parent,
+                            const gchar *name, const GTypeInfo *info,
+                            GTypeFlags flags)
+{
+#ifdef PURPLE_PLUGINS
+	return gplugin_native_plugin_register_type(GPLUGIN_NATIVE_PLUGIN(plugin),
+	                                           parent, name, info, flags);
+
+#else
+	return G_TYPE_INVALID;
+#endif
+}
+
+void
+purple_plugin_add_interface(PurplePlugin *plugin, GType instance_type,
+                            GType interface_type,
+                            const GInterfaceInfo *interface_info)
+{
+#ifdef PURPLE_PLUGINS
+	gplugin_native_plugin_add_interface(GPLUGIN_NATIVE_PLUGIN(plugin),
+	                                    instance_type, interface_type,
+	                                    interface_info);
+#endif
+}
+
+gboolean
+purple_plugin_is_internal(const PurplePlugin *plugin)
+{
+#ifdef PURPLE_PLUGINS
+	GPluginPluginInfo *info;
+
+	g_return_val_if_fail(plugin != NULL, FALSE);
+
+	info = GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin));
+
+	g_return_val_if_fail(info != NULL, FALSE);
+
+	return (gplugin_plugin_info_get_flags(info) &
+	        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL);
+
+#else
+	return FALSE;
+#endif
+}
+
+GSList *
+purple_plugin_get_dependent_plugins(const PurplePlugin *plugin)
+{
+#ifdef PURPLE_PLUGINS
+#warning TODO: Implement this when GPlugin can return dependent plugins.
+	return NULL;
+
+#else
+	return NULL;
+#endif
+}
+
+/**************************************************************************
+ * GObject code for PurplePluginInfo
+ **************************************************************************/
+/* GObject Property names */
+#define PROP_UI_REQUIREMENT_S     "ui-requirement"
+#define PROP_GET_ACTIONS_S        "get-actions"
+#define PROP_PREFERENCES_FRAME_S  "preferences-frame"
+
+/* Set method for GObject properties */
+static void
+purple_plugin_info_set_property(GObject *obj, guint param_id, const GValue *value,
+		GParamSpec *pspec)
+{
+	PurplePluginInfo *info = PURPLE_PLUGIN_INFO(obj);
+	PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info);
+
+	switch (param_id) {
+		case PROP_UI_REQUIREMENT:
+			priv->ui_requirement = g_strdup(g_value_get_string(value));
+			break;
+		case PROP_GET_ACTIONS:
+			priv->get_actions = g_value_get_pointer(value);
+			break;
+		case PROP_PREFERENCES_FRAME:
+			priv->get_pref_frame = g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+/* Get method for GObject properties */
+static void
+purple_plugin_info_get_property(GObject *obj, guint param_id, GValue *value,
+		GParamSpec *pspec)
+{
+	PurplePluginInfo *info = PURPLE_PLUGIN_INFO(obj);
+
+	switch (param_id) {
+		case PROP_GET_ACTIONS:
+			g_value_set_pointer(value,
+					purple_plugin_info_get_actions_callback(info));
+			break;
+		case PROP_PREFERENCES_FRAME:
+			g_value_set_pointer(value,
+					purple_plugin_info_get_pref_frame_callback(info));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+/* Called when done constructing */
+static void
+purple_plugin_info_constructed(GObject *object)
+{
+	PurplePluginInfo *info = PURPLE_PLUGIN_INFO(object);
+	PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info);
+	const char *id = purple_plugin_info_get_id(info);
+	guint32 version;
+
+	parent_class->constructed(object);
+
+	if (id == NULL || *id == '\0')
+		priv->error = g_strdup(_("This plugin has not defined an ID."));
+
+	if (priv->ui_requirement && !purple_strequal(priv->ui_requirement, purple_core_get_ui()))
+	{
+		priv->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."),
+				purple_core_get_ui(), priv->ui_requirement);
+		purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n",
+				id, priv->error);
+	}
+
+	version = purple_plugin_info_get_abi_version(info);
+	if (PURPLE_PLUGIN_ABI_MAJOR_VERSION(version) != PURPLE_MAJOR_VERSION ||
+		PURPLE_PLUGIN_ABI_MINOR_VERSION(version) > PURPLE_MINOR_VERSION)
+	{
+		priv->error = g_strdup_printf(_("Your libpurple version is %d.%d.x (need %d.%d.x)"),
+				PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION,
+				PURPLE_PLUGIN_ABI_MAJOR_VERSION(version),
+				PURPLE_PLUGIN_ABI_MINOR_VERSION(version));
+		purple_debug_error("plugins", "%s is not loadable: libpurple version is %d.%d.x (need %d.%d.x)\n",
+				id, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION,
+				PURPLE_PLUGIN_ABI_MAJOR_VERSION(version),
+				PURPLE_PLUGIN_ABI_MINOR_VERSION(version));
+	}
+}
+
+/* GObject finalize function */
+static void
+purple_plugin_info_finalize(GObject *object)
+{
+	PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(object);
+
+	g_free(priv->ui_requirement);
+	g_free(priv->error);
+
+	parent_class->finalize(object);
+}
+
+/* Class initializer function */
+static void purple_plugin_info_class_init(PurplePluginInfoClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	g_type_class_add_private(klass, sizeof(PurplePluginInfoPrivate));
+
+	obj_class->constructed = purple_plugin_info_constructed;
+	obj_class->finalize = purple_plugin_info_finalize;
+
+	/* Setup properties */
+	obj_class->get_property = purple_plugin_info_get_property;
+	obj_class->set_property = purple_plugin_info_set_property;
+
+	g_object_class_install_property(obj_class, PROP_UI_REQUIREMENT,
+		g_param_spec_string(PROP_UI_REQUIREMENT_S,
+		                  "UI Requirement",
+		                  "ID of UI that is required by this plugin", NULL,
+		                  G_PARAM_WRITABLE));
+
+	g_object_class_install_property(obj_class, PROP_GET_ACTIONS,
+		g_param_spec_pointer(PROP_GET_ACTIONS_S,
+		                  "Plugin actions",
+		                  "Callback that returns list of the plugin's actions",
+		                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property(obj_class, PROP_PREFERENCES_FRAME,
+		g_param_spec_pointer(PROP_PREFERENCES_FRAME_S,
+		                  "Preferences frame callback",
+		                  "The callback that returns the preferences frame",
+		                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/**************************************************************************
+ * PluginInfo API
+ **************************************************************************/
+GType
+purple_plugin_info_get_type(void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY(type == 0)) {
+		static const GTypeInfo info = {
+			.class_size = sizeof(PurplePluginInfoClass),
+			.class_init = (GClassInitFunc)purple_plugin_info_class_init,
+			.instance_size = sizeof(PurplePluginInfo),
+		};
+
+		type = g_type_register_static(
+#ifdef PURPLE_PLUGINS
+		                              GPLUGIN_TYPE_PLUGIN_INFO,
+#else
+		                              G_TYPE_OBJECT,
+#endif
+		                              "PurplePluginInfo", &info, 0);
+	}
+
+	return type;
+}
+
+PurplePluginInfo *
+purple_plugin_info_new(const char *first_property, ...)
+{
+	GObject *info;
+	va_list var_args;
+
+	/* at least ID is required */
+	if (!first_property)
+		return NULL;
+
+	va_start(var_args, first_property);
+	info = g_object_new_valist(PURPLE_TYPE_PLUGIN_INFO, first_property,
+	                           var_args);
+	va_end(var_args);
+
+	return PURPLE_PLUGIN_INFO(info);
+}
+
+const gchar *
+purple_plugin_info_get_id(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_id(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_name(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_name(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_version(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_version(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_category(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_category(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_summary(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_summary(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_description(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_description(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_author(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_author(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_website(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_website(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_icon(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_icon(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_license(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_license(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_license_text(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_license_text(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+const gchar *
+purple_plugin_info_get_license_url(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, NULL);
+
+	return gplugin_plugin_info_get_license_url(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return NULL;
+#endif
+}
+
+guint32
+purple_plugin_info_get_abi_version(const PurplePluginInfo *info)
+{
+#ifdef PURPLE_PLUGINS
+	g_return_val_if_fail(info != NULL, 0);
+
+	return gplugin_plugin_info_get_abi_version(GPLUGIN_PLUGIN_INFO(info));
+
+#else
+	return 0;
+#endif
+}
+
+PurplePluginGetActionsCallback
+purple_plugin_info_get_actions_callback(const PurplePluginInfo *info)
+{
+	PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info);
+
+	g_return_val_if_fail(priv != NULL, NULL);
+
+	return priv->get_actions;
+}
+
+PurplePluginPrefFrameCallback
+purple_plugin_info_get_pref_frame_callback(const PurplePluginInfo *info)
+{
+	PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info);
+
+	g_return_val_if_fail(priv != NULL, NULL);
+
+	return priv->get_pref_frame;
+}
+
+const gchar *
+purple_plugin_info_get_error(const PurplePluginInfo *info)
+{
+	PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info);
+
+	g_return_val_if_fail(priv != NULL, NULL);
+
+	return priv->error;
+}
+
+/**************************************************************************
+ * PluginAction API
+ **************************************************************************/
+PurplePluginAction *
+purple_plugin_action_new(const char* label, PurplePluginActionCallback callback)
+{
+	PurplePluginAction *action;
+
+	g_return_val_if_fail(label != NULL && callback != NULL, NULL);
+
+	action = g_new0(PurplePluginAction, 1);
+
+	action->label    = g_strdup(label);
+	action->callback = callback;
+
+	return action;
+}
+
+void
+purple_plugin_action_free(PurplePluginAction *action)
+{
+	g_return_if_fail(action != NULL);
+
+	g_free(action->label);
+	g_free(action);
+}
+
+static PurplePluginAction *
+purple_plugin_action_copy(PurplePluginAction *action)
+{
+	PurplePluginAction *action_copy;
+
+	g_return_val_if_fail(action != NULL, NULL);
+
+	action_copy = g_new(PurplePluginAction, 1);
+	*action_copy = *action;
+
+	action_copy->label    = g_strdup(action->label);
+
+	return action_copy;
+}
+
+GType
+purple_plugin_action_get_type(void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY(type == 0)) {
+		type = g_boxed_type_register_static("PurplePluginAction",
+				(GBoxedCopyFunc)purple_plugin_action_copy,
+				(GBoxedFreeFunc)purple_plugin_action_free);
+	}
+
+	return type;
+}
+
+/**************************************************************************
+ * Plugins API
+ **************************************************************************/
+GList *
+purple_plugins_find_all(void)
+{
+#ifdef PURPLE_PLUGINS
+	GList *ret = NULL, *ids, *l;
+	GSList *plugins, *ll;
+
+	ids = gplugin_plugin_manager_list_plugins();
+
+	for (l = ids; l; l = l->next) {
+		plugins = gplugin_plugin_manager_find_plugins(l->data);
+		for (ll = plugins; ll; ll = ll->next)
+			ret = g_list_append(ret, ll->data);
+
+		gplugin_plugin_manager_free_plugin_list(plugins);
+	}
+	g_list_free(ids);
+
+	return ret;
+
+#else
+	return NULL;
+#endif
+}
+
+GList *
+purple_plugins_get_loaded(void)
+{
+#ifdef PURPLE_PLUGINS
+	return loaded_plugins;
+#else
+	return NULL;
+#endif
+}
+
+void
+purple_plugins_add_search_path(const gchar *path)
+{
+#ifdef PURPLE_PLUGINS
+	gplugin_plugin_manager_append_path(path);
+#endif
+}
+
+void
+purple_plugins_refresh(void)
+{
+#ifdef PURPLE_PLUGINS
+	GList *plugins, *l;
+
+	gplugin_plugin_manager_refresh();
+
+	plugins = purple_plugins_find_all();
+	for (l = plugins; l != NULL; l = l->next) {
+		PurplePlugin *plugin = PURPLE_PLUGIN(l->data);
+		GPluginPluginInfo *info;
+		PurplePluginInfoPrivate *priv;
+
+		if (purple_plugin_is_loaded(plugin))
+			continue;
+
+		info = GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin));
+		if (!info)
+			continue;
+
+		priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info);
+
+		if (!priv->unloaded && gplugin_plugin_info_get_flags(info) &
+				GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY) {
+			purple_debug_info("plugins", "Auto-loading plugin %s\n",
+			                  purple_plugin_get_filename(plugin));
+			purple_plugin_load(plugin, NULL);
+		}
+	}
+
+	g_list_free(plugins);
+#endif
+}
+
+PurplePlugin *
+purple_plugins_find_plugin(const gchar *id)
+{
+#ifdef PURPLE_PLUGINS
+	PurplePlugin *plugin;
+
+	g_return_val_if_fail(id != NULL && *id != '\0', NULL);
+
+	plugin = gplugin_plugin_manager_find_plugin(id);
+	g_object_unref(plugin);
+
+	return plugin;
+
+#else
+	return NULL;
+#endif
+}
+
+PurplePlugin *
+purple_plugins_find_by_filename(const char *filename)
+{
+	GList *plugins, *l;
+
+	g_return_val_if_fail(filename != NULL && *filename != '\0', NULL);
+
+	plugins = purple_plugins_find_all();
+
+	for (l = plugins; l != NULL; l = l->next) {
+		PurplePlugin *plugin = PURPLE_PLUGIN(l->data);
+
+		if (purple_strequal(purple_plugin_get_filename(plugin), filename)) {
+			g_list_free(plugins);
+			return plugin;
+		}
+	}
+	g_list_free(plugins);
+
+	return NULL;
+}
+
+void
+purple_plugins_save_loaded(const char *key)
+{
+#ifdef PURPLE_PLUGINS
+	GList *pl;
+	GList *files = NULL;
+
+	g_return_if_fail(key != NULL && *key != '\0');
+
+	for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) {
+		PurplePlugin *plugin = PURPLE_PLUGIN(pl->data);
+		GPluginPluginInfo *info =
+				GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin));
+
+		if (!info)
+			continue;
+
+		if (gplugin_plugin_info_get_flags(info) &
+				GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY)
+			continue;
+
+		if (!g_list_find(plugins_to_disable, plugin))
+			files = g_list_append(files, (gchar *)purple_plugin_get_filename(plugin));
+	}
+
+	purple_prefs_set_path_list(key, files);
+	g_list_free(files);
+#endif
+}
+
+void
+purple_plugins_load_saved(const char *key)
+{
+#ifdef PURPLE_PLUGINS
+	GList *l, *files;
+
+	g_return_if_fail(key != NULL && *key != '\0');
+
+	files = purple_prefs_get_path_list(key);
+
+	for (l = files; l; l = l->next)
+	{
+		char *file;
+		PurplePlugin *plugin;
+
+		if (l->data == NULL)
+			continue;
+
+		file = l->data;
+		plugin = purple_plugins_find_by_filename(file);
+
+		if (plugin) {
+			purple_debug_info("plugins", "Loading saved plugin %s\n", file);
+			purple_plugin_load(plugin, NULL);
+		} else {
+			purple_debug_error("plugins", "Unable to find saved plugin %s\n", file);
+		}
+
+		g_free(l->data);
+	}
+
+	g_list_free(files);
+#endif /* PURPLE_PLUGINS */
+}
+
+/**************************************************************************
+ * Plugins Subsystem API
+ **************************************************************************/
+void *
+purple_plugins_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
+}
+
+void
+purple_plugins_init(void)
+{
+	void *handle = purple_plugins_get_handle();
+
+	purple_signal_register(handle, "plugin-load",
+	                       purple_marshal_VOID__POINTER,
+	                       G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN);
+	purple_signal_register(handle, "plugin-unload",
+	                       purple_marshal_VOID__POINTER,
+	                       G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN);
+
+#ifdef PURPLE_PLUGINS
+	gplugin_init();
+	purple_plugins_add_search_path(LIBDIR);
+	purple_plugins_refresh();
+#endif
+}
+
+void
+purple_plugins_uninit(void)
+{
+	void *handle = purple_plugins_get_handle();
+
+#ifdef PURPLE_PLUGINS
+	purple_debug_info("plugins", "Unloading all plugins\n");
+	while (loaded_plugins != NULL)
+		purple_plugin_unload(loaded_plugins->data, NULL);
+#endif
+
+	purple_signals_disconnect_by_handle(handle);
+	purple_signals_unregister_by_instance(handle);
+
+#ifdef PURPLE_PLUGINS
+	gplugin_uninit();
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins.h	Sun Aug 18 01:53:00 2013 +0530
@@ -0,0 +1,664 @@
+/**
+ * @file plugins.h Plugins API
+ * @ingroup core
+ * @see @ref plugin-signals
+ * @see @ref plugin-ids
+ * @see @ref plugin-i18n
+ */
+
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef _PURPLE_PLUGINS_H_
+#define _PURPLE_PLUGINS_H_
+
+#ifdef PURPLE_PLUGINS
+#include <gplugin.h>
+#include <gplugin-native.h>
+#else
+#include <glib.h>
+#include <glib-object.h>
+#endif
+
+#include "version.h"
+
+#define PURPLE_PLUGINS_DOMAIN          (g_quark_from_static_string("plugins"))
+
+#ifdef PURPLE_PLUGINS
+
+#define PURPLE_TYPE_PLUGIN             GPLUGIN_TYPE_PLUGIN
+#define PURPLE_PLUGIN(obj)             GPLUGIN_PLUGIN(obj)
+#define PURPLE_PLUGIN_CLASS(klass)     GPLUGIN_PLUGIN_CLASS(klass)
+#define PURPLE_IS_PLUGIN(obj)          GPLUGIN_IS_PLUGIN(obj)
+#define PURPLE_IS_PLUGIN_CLASS(klass)  GPLUGIN_IS_PLUGIN_CLASS(klass)
+#define PURPLE_PLUGIN_GET_CLASS(obj)   GPLUGIN_PLUGIN_GET_CLASS(obj)
+
+/**
+ * Represents a plugin handle.
+ * This type is an alias for GPluginPlugin.
+ */
+typedef GPluginPlugin PurplePlugin;
+
+/**
+ * The base class for all #PurplePlugin's.
+ * This type is an alias for GPluginPluginClass.
+ */
+typedef GPluginPluginClass PurplePluginClass;
+
+#else /* !defined(PURPLE_PLUGINS) */
+
+#define PURPLE_TYPE_PLUGIN             G_TYPE_OBJECT
+#define PURPLE_PLUGIN(obj)             G_OBJECT(obj)
+#define PURPLE_PLUGIN_CLASS(klass)     G_OBJECT_CLASS(klass)
+#define PURPLE_IS_PLUGIN(obj)          G_IS_OBJECT(obj)
+#define PURPLE_IS_PLUGIN_CLASS(klass)  G_IS_OBJECT_CLASS(klass)
+#define PURPLE_PLUGIN_GET_CLASS(obj)   G_OBJECT_GET_CLASS(obj)
+
+#define GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY 0
+#define GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL      0
+
+typedef GObject PurplePlugin;
+typedef GObjectClass PurplePluginClass;
+
+#endif /* PURPLE_PLUGINS */
+
+#define PURPLE_TYPE_PLUGIN_INFO             (purple_plugin_info_get_type())
+#define PURPLE_PLUGIN_INFO(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfo))
+#define PURPLE_PLUGIN_INFO_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfoClass))
+#define PURPLE_IS_PLUGIN_INFO(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PLUGIN_INFO))
+#define PURPLE_IS_PLUGIN_INFO_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_PLUGIN_INFO))
+#define PURPLE_PLUGIN_INFO_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfoClass))
+
+/** @copydoc _PurplePluginInfo */
+typedef struct _PurplePluginInfo PurplePluginInfo;
+/** @copydoc _PurplePluginInfoClass */
+typedef struct _PurplePluginInfoClass PurplePluginInfoClass;
+
+#define PURPLE_TYPE_PLUGIN_ACTION  (purple_plugin_action_get_type())
+
+/** @copydoc _PurplePluginAction */
+typedef struct _PurplePluginAction PurplePluginAction;
+
+#include "pluginpref.h"
+
+typedef void (*PurplePluginActionCallback)(PurplePluginAction *);
+typedef GList *(*PurplePluginGetActionsCallback)(PurplePlugin *);
+typedef PurplePluginPrefFrame *(*PurplePluginPrefFrameCallback)(PurplePlugin *);
+
+/**
+ * Holds information about a plugin.
+ */
+struct _PurplePluginInfo {
+#ifdef PURPLE_PLUGINS
+	/*< private >*/
+	GPluginPluginInfo parent;
+#else
+	/*< private >*/
+	GObject parent;
+#endif
+};
+
+/**
+ * PurplePluginInfoClass:
+ *
+ * The base class for all #PurplePluginInfo's.
+ */
+struct _PurplePluginInfoClass {
+#ifdef PURPLE_PLUGINS
+	/*< private >*/
+	GPluginPluginInfoClass parent_class;
+#else
+	/*< private >*/
+	GObjectClass parent_class;
+#endif
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+/**
+ * Represents an action that the plugin can perform. This shows up in the Tools
+ * menu, under a submenu with the name of the plugin.
+ */
+struct _PurplePluginAction {
+	char *label;
+	PurplePluginActionCallback callback;
+	PurplePlugin *plugin;
+	gpointer user_data;
+};
+
+/** Returns an ABI version to set in plugins using major and minor versions */
+#define PURPLE_PLUGIN_ABI_VERSION(major,minor) (0x01000000 | \
+                                               ((major) << 16) | (minor))
+
+/** Returns the major version from an ABI version */
+#define PURPLE_PLUGIN_ABI_MAJOR_VERSION(abi)   ((abi >> 16) & 0xff)
+/** Returns the minor version from an ABI version */
+#define PURPLE_PLUGIN_ABI_MINOR_VERSION(abi)   (abi & 0xffff)
+
+/**
+  * A convenience‎ macro that returns an ABI version using PURPLE_MAJOR_VERSION
+  * and PURPLE_MINOR_VERSION
+  */
+#define PURPLE_ABI_VERSION PURPLE_PLUGIN_ABI_VERSION(PURPLE_MAJOR_VERSION, \
+                                                     PURPLE_MINOR_VERSION)
+
+/**
+ * Handles the initialization of modules.
+ */
+#if !defined(PURPLE_PLUGINS) || defined(PURPLE_STATIC_PROTOCOL)
+#define PURPLE_PLUGIN_INIT(pluginname,pluginquery,pluginload,pluginunload) \
+	PurplePluginInfo * pluginname##_plugin_query(void); \
+	PurplePluginInfo * pluginname##_plugin_query(void) { \
+		return pluginquery(NULL); \
+	} \
+	gboolean pluginname##_plugin_load(void); \
+	gboolean pluginname##_plugin_load(void) { \
+		GError *e = NULL; \
+		gboolean loaded = pluginload(NULL, &e); \
+		if (e) g_error_free(e); \
+		return loaded; \
+	} \
+	gboolean pluginname##_plugin_unload(void); \
+	gboolean pluginname##_plugin_unload(void) { \
+		GError *e = NULL; \
+		gboolean unloaded = pluginunload(NULL, &e); \
+		if (e) g_error_free(e); \
+		return unloaded; \
+	}
+#else /* PURPLE_PLUGINS  && !PURPLE_STATIC_PROTOCOL */
+#define PURPLE_PLUGIN_INIT(pluginname,pluginquery,pluginload,pluginunload) \
+	G_MODULE_EXPORT GPluginPluginInfo *gplugin_plugin_query(GError **e); \
+	G_MODULE_EXPORT GPluginPluginInfo *gplugin_plugin_query(GError **e) { \
+		return GPLUGIN_PLUGIN_INFO(pluginquery(e)); \
+	} \
+	G_MODULE_EXPORT gboolean gplugin_plugin_load(GPluginNativePlugin *p, GError **e); \
+	G_MODULE_EXPORT gboolean gplugin_plugin_load(GPluginNativePlugin *p, GError **e) { \
+		return pluginload(PURPLE_PLUGIN(p), e); \
+	} \
+	G_MODULE_EXPORT gboolean gplugin_plugin_unload(GPluginNativePlugin *p, GError **e); \
+	G_MODULE_EXPORT gboolean gplugin_plugin_unload(GPluginNativePlugin *p, GError **e) { \
+		return pluginunload(PURPLE_PLUGIN(p), e); \
+	}
+#endif
+
+G_BEGIN_DECLS
+
+/**************************************************************************/
+/** @name Plugin API                                                      */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Attempts to load a plugin.
+ *
+ * @param plugin The plugin to load.
+ * @param error  Return location for a #GError or @c NULL. If provided, this
+ *               will be set to the reason if the load fails.
+ *
+ * @return @c TRUE if successful or already loaded, @c FALSE otherwise.
+ *
+ * @see purple_plugin_unload()
+ */
+gboolean purple_plugin_load(PurplePlugin *plugin, GError **error);
+
+/**
+ * Unloads the specified plugin.
+ *
+ * @param plugin The plugin handle.
+ * @param error  Return location for a #GError or @c NULL. If provided, this
+ *               will be set to the reason if the unload fails.
+ *
+ * @return @c TRUE if successful or not loaded, @c FALSE otherwise.
+ *
+ * @see purple_plugin_load()
+ */
+gboolean purple_plugin_unload(PurplePlugin *plugin, GError **error);
+
+/**
+ * Returns whether or not a plugin is currently loaded.
+ *
+ * @param plugin The plugin.
+ *
+ * @return @c TRUE if loaded, or @c FALSE otherwise.
+ */
+gboolean purple_plugin_is_loaded(const PurplePlugin *plugin);
+
+/**
+ * Returns a plugin's filename, along with the path.
+ *
+ * @param info The plugin.
+ *
+ * @return The plugin's filename.
+ */
+const gchar *purple_plugin_get_filename(const PurplePlugin *plugin);
+
+/**
+ * Returns a plugin's #PurplePluginInfo instance.
+ *
+ * @param info The plugin.
+ *
+ * @return The plugin's #PurplePluginInfo instance.
+ */
+PurplePluginInfo *purple_plugin_get_info(const PurplePlugin *plugin);
+
+/**
+ * Disable a plugin.
+ *
+ * This function adds the plugin to a list of plugins to "disable at the next
+ * 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.
+ */
+void purple_plugin_disable(PurplePlugin *plugin);
+
+/**
+ * Registers a new dynamic type.
+ *
+ * @param plugin  The plugin that is registering the type.
+ * @param parent  Type from which this type will be derived.
+ * @param name    Name of the new type.
+ * @param info    Information to initialize and destroy a type's classes and
+ *                instances.
+ * @param flags   Bitwise combination of values that determines the nature
+ *                (e.g. abstract or not) of the type.
+ *
+ * @return The new GType, or @c G_TYPE_INVALID if registration failed.
+ */
+GType purple_plugin_register_type(PurplePlugin *plugin, GType parent,
+                                  const gchar *name, const GTypeInfo *info,
+                                  GTypeFlags flags);
+
+/**
+ * Adds a dynamic interface type to an instantiable type.
+ *
+ * @param plugin          The plugin that is adding the interface type.
+ * @param instance_type   The GType of the instantiable type.
+ * @param interface_type  The GType of the interface type.
+ * @param interface_info  Information used to manage the interface type.
+ */
+void purple_plugin_add_interface(PurplePlugin *plugin, GType instance_type,
+                                 GType interface_type,
+                                 const GInterfaceInfo *interface_info);
+
+/**
+ * Returns whether a plugin is an internal plugin. Internal plugins provide
+ * required additional functionality to the libpurple core. These plugins must
+ * not be shown in plugin lists. Examples of such plugins are in-tree protocol
+ * plugins, loaders etc.
+ *
+ * @param plugin The plugin.
+ *
+ * @return @c TRUE if the plugin is an internal plugin, @c FALSE otherwise.
+ */
+gboolean purple_plugin_is_internal(const PurplePlugin *plugin);
+
+/**
+ * Returns a list of plugins that depend on a particular plugin.
+ *
+ * @param plugin The plugin whose dependent plugins are returned.
+ *
+ * @constreturn The list of a plugins that depend on the specified plugin.
+ */
+GSList *purple_plugin_get_dependent_plugins(const PurplePlugin *plugin);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name PluginInfo API                                                  */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the GType for the PurplePluginInfo object.
+ */
+GType purple_plugin_info_get_type(void);
+
+/**
+ * Creates a new #PurplePluginInfo instance to be returned from
+ * gplugin_plugin_query() of a plugin, using the provided name/value pairs.
+ *
+ * All properties except "id" and "purple-abi" are optional.
+ *
+ * Valid property names are:                                                 \n
+ * "id"                 (string) The ID of the plugin.                       \n
+ * "name"               (string) The translated name of the plugin.          \n
+ * "version"            (string) Version of the plugin.                      \n
+ * "category"           (string) Primary category of the plugin.             \n
+ * "summary"            (string) Brief summary of the plugin.                \n
+ * "description"        (string) Full description of the plugin.             \n
+ * "author"             (string) Name and e-mail address of the author.
+ *                               format: First Last <user@domain.com>        \n
+ * "website"            (string) Website of the plugin.                      \n
+ * "icon"               (string) Path to a plugin's icon.                    \n
+ * "license"            (string) Short name of the plugin's license. This
+ *                               should either be an identifier of the
+ *                               license from http://spdx.org/licenses/ or
+ *                               "Other" for custom licenses.                \n
+ * "license-text"       (string) The text of the plugin's license, if
+ *                               unlisted on SPDX.                           \n
+ * "license-url"        (string) The plugin's license URL, if unlisted on
+ *                               SPDX.                                       \n
+ * "dependencies"       (string) Comma-seperated list of plugin IDs required
+ *                               by the plugin.                              \n
+ * "abi-version"        (guint32) The ABI version required by the plugin.    \n
+ * "get-actions"        (PurplePluginGetActionsCallback) Callback that
+ *                               returns a list of actions the plugin can
+ *                               perform.                                    \n
+ * "preferences-frame"  (PurplePluginPrefFrameCallback) Callback that returns
+ *                               a preferences frame for the plugin.
+ *
+ * Additionally, you can provide a "flags" property if the plugin is to be
+ * distributed with libpurple, the value for which should be a bitwise
+ * combination of:                                                           \n
+ * GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL: Internal plugin, not shown in lists.  \n
+ * GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY: Auto-load on query.              \n
+ *
+ * @param first_property  The first property name
+ * @param ...  The value of the first property, followed optionally by more
+ *             name/value pairs, followed by @c NULL
+ *
+ * @return A new #PurplePluginInfo instance.
+ *
+ * @see PURPLE_PLUGIN_ABI_VERSION
+ * @see @ref plugin-ids
+ */
+PurplePluginInfo *purple_plugin_info_new(const char *first_property, ...);
+
+/**
+ * Returns a plugin's ID.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The plugin's ID.
+ */
+const gchar *purple_plugin_info_get_id(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's translated name.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The name of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_name(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's version.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The version of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_version(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's primary category.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The primary category of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_category(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's summary.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The summary of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_summary(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's description.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The description of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_description(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's author.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The author of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_author(const PurplePluginInfo *info);
+
+/**
+ * Returns a plugin's website.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The website of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_website(const PurplePluginInfo *info);
+
+/**
+ * Returns the path to a plugin's icon.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The path to the plugin's icon, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_icon(const PurplePluginInfo *info);
+
+/**
+ * Returns a short name of the plugin's license.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The license name of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_license(const PurplePluginInfo *info);
+
+/**
+ * Returns the text of a plugin's license.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The license text of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_license_text(const PurplePluginInfo *info);
+
+/**
+ * Returns the URL of a plugin's license.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The license URL of the plugin, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_license_url(const PurplePluginInfo *info);
+
+/**
+ * Returns the required purple ABI version for a plugin.
+ *
+ * @param info The plugin's info instance.
+ *
+ * @return The required purple ABI version for the plugin.
+ */
+guint32 purple_plugin_info_get_abi_version(const PurplePluginInfo *info);
+
+/**
+ * Returns the callback that retrieves the list of actions a plugin can perform
+ * at that moment.
+ *
+ * @param info The plugin info to get the callback from.
+ *
+ * @constreturn The callback that returns a list of #PurplePluginAction
+ *              instances corresponding to the actions a plugin can perform.
+ */
+PurplePluginGetActionsCallback
+purple_plugin_info_get_actions_callback(const PurplePluginInfo *info);
+
+/**
+ * Returns the callback that retrieves the preferences frame for a plugin.
+ *
+ * @param info The plugin info to get the callback from.
+ *
+ * @return The callback that returns the preferences frame.
+ */
+PurplePluginPrefFrameCallback
+purple_plugin_info_get_pref_frame_callback(const PurplePluginInfo *info);
+
+/**
+ * Returns an error in the plugin info that would prevent the plugin from being
+ * loaded.
+ *
+ * @param info The plugin info.
+ *
+ * @return The plugin info error, or @c NULL.
+ */
+const gchar *purple_plugin_info_get_error(const PurplePluginInfo *info);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name PluginAction API                                                */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the GType for the PurplePluginAction boxed structure.
+ */
+GType purple_plugin_action_get_type(void);
+
+/**
+ * Allocates and returns a new PurplePluginAction. Use this to add actions in a
+ * list in the "get-actions" callback for your plugin.
+ *
+ * @param label    The description of the action to show to the user.
+ * @param callback The callback to call when the user selects this action.
+ */
+PurplePluginAction *purple_plugin_action_new(const char* label,
+		PurplePluginActionCallback callback);
+
+/**
+ * Frees a PurplePluginAction
+ *
+ * @param action The PurplePluginAction to free.
+ */
+void purple_plugin_action_free(PurplePluginAction *action);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name Plugins API                                                     */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns a list of all plugins, whether loaded or not.
+ *
+ * @return A list of all plugins. The list is owned by the caller, and must be
+ *         g_list_free()d to avoid leaking the nodes.
+ */
+GList *purple_plugins_find_all(void);
+
+/**
+ * Returns a list of all loaded plugins.
+ *
+ * @constreturn A list of all loaded plugins.
+ */
+GList *purple_plugins_get_loaded(void);
+
+/**
+ * Add a new directory to search for plugins
+ *
+ * @param path The new search path.
+ */
+void purple_plugins_add_search_path(const gchar *path);
+
+/**
+ * Forces a refresh of all plugins found in the search paths, and loads plugins
+ * that are to be loaded on query.
+ *
+ * @see purple_plugins_add_search_path()
+ */
+void purple_plugins_refresh(void);
+
+/**
+ * Finds a plugin with the specified plugin ID.
+ *
+ * @param id The plugin ID.
+ *
+ * @return The plugin if found, or @c NULL if not found.
+ */
+PurplePlugin *purple_plugins_find_plugin(const gchar *id);
+
+/**
+ * Finds a plugin with the specified filename (filename with a path).
+ *
+ * @param filename The plugin filename.
+ *
+ * @return The plugin if found, or @c NULL if not found.
+ */
+PurplePlugin *purple_plugins_find_by_filename(const char *filename);
+
+/**
+ * Saves the list of loaded plugins to the specified preference key.
+ * Plugins that are set to load on query are not saved.
+ *
+ * @param key The preference key to save the list of plugins to.
+ */
+void purple_plugins_save_loaded(const char *key);
+
+/**
+ * Attempts to load all the plugins in the specified preference key
+ * that were loaded when purple last quit.
+ *
+ * @param key The preference key containing the list of plugins.
+ */
+void purple_plugins_load_saved(const char *key);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name Plugins Subsystem API                                           */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the plugin subsystem handle.
+ *
+ * @return The plugin sybsystem handle.
+ */
+void *purple_plugins_get_handle(void);
+
+/**
+ * Initializes the plugin subsystem
+ */
+void purple_plugins_init(void);
+
+/**
+ * Uninitializes the plugin subsystem
+ */
+void purple_plugins_uninit(void);
+
+/*@}*/
+
+G_END_DECLS
+
+#endif /* _PURPLE_PLUGINS_H_ */
--- a/libpurple/plugins/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -1,168 +1,175 @@
-DIST_SUBDIRS = mono perl ssl tcl keyrings
-
-if USE_PERL
-PERL_DIR = perl
-endif
-
-if USE_TCL
-TCL_DIR = tcl
-endif
-
-if ENABLE_DBUS
-DBUS_LTLIB = dbus-example.la
-endif
-
-if USE_MONO
-MONO_DIR = mono
-endif
+DIST_SUBDIRS = ssl keyrings
 
 SUBDIRS = \
-	$(MONO_DIR) \
-	$(PERL_DIR) \
 	ssl \
-	$(TCL_DIR) \
 	keyrings
 
-plugindir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-autoaccept_la_LDFLAGS       = -module -avoid-version
-buddynote_la_LDFLAGS        = -module -avoid-version
-ciphertest_la_LDFLAGS		= -module -avoid-version
-codeinline_la_LDFLAGS		= -module -avoid-version
-debug_example_la_LDFLAGS    = -module -avoid-version
-helloworld_la_LDFLAGS       = -module -avoid-version
-idle_la_LDFLAGS             = -module -avoid-version
-joinpart_la_LDFLAGS         = -module -avoid-version
-log_reader_la_LDFLAGS       = -module -avoid-version
-newline_la_LDFLAGS          = -module -avoid-version
-notify_example_la_LDFLAGS   = -module -avoid-version
-offlinemsg_la_LDFLAGS       = -module -avoid-version
-one_time_password_la_LDFLAGS	= -module -avoid-version
-pluginpref_example_la_LDFLAGS = -module -avoid-version
-psychic_la_LDFLAGS          = -module -avoid-version
-signals_test_la_LDFLAGS		= -module -avoid-version
-simple_la_LDFLAGS			= -module -avoid-version
-statenotify_la_LDFLAGS      = -module -avoid-version
-
-# this can't be in a conditional otherwise automake 1.4 yells
-dbus_example_la_LDFLAGS     = -module -avoid-version
-
-if PLUGINS
-
-plugin_LTLIBRARIES = \
-	autoaccept.la       \
-	buddynote.la        \
-	idle.la             \
-	joinpart.la         \
-	log_reader.la       \
-	newline.la          \
-	offlinemsg.la       \
-	psychic.la          \
-	statenotify.la      \
-	$(DBUS_LTLIB)
-
-noinst_LTLIBRARIES = \
-	ciphertest.la \
-	codeinline.la \
-	debug_example.la \
-	helloworld.la \
-	notify_example.la \
-	one_time_password.la \
-	pluginpref_example.la \
-	signals_test.la \
-	simple.la
-
-autoaccept_la_SOURCES       = autoaccept.c
-buddynote_la_SOURCES        = buddynote.c
-ciphertest_la_SOURCES		= ciphertest.c
-codeinline_la_SOURCES		= codeinline.c
-debug_example_la_SOURCES = debug_example.c
-helloworld_la_SOURCES       = helloworld.c
-idle_la_SOURCES             = idle.c
-joinpart_la_SOURCES         = joinpart.c
-log_reader_la_SOURCES       = log_reader.c
-newline_la_SOURCES          = newline.c
-notify_example_la_SOURCES   = notify_example.c
-offlinemsg_la_SOURCES       = offlinemsg.c
-one_time_password_la_SOURCES	= one_time_password.c
-pluginpref_example_la_SOURCES = pluginpref_example.c
-psychic_la_SOURCES          = psychic.c
-signals_test_la_SOURCES		= signals-test.c
-simple_la_SOURCES			= simple.c
-statenotify_la_SOURCES      = statenotify.c
-
-autoaccept_la_LIBADD        = $(GLIB_LIBS)
-buddynote_la_LIBADD         = $(GLIB_LIBS)
-ciphertest_la_LIBADD		= $(GLIB_LIBS)
-codeinline_la_LIBADD		= $(GLIB_LIBS)
-idle_la_LIBADD              = $(GLIB_LIBS)
-joinpart_la_LIBADD          = $(GLIB_LIBS)
-log_reader_la_LIBADD        = $(GLIB_LIBS)
-newline_la_LIBADD           = $(GLIB_LIBS)
-notify_example_la_LIBADD    = $(GLIB_LIBS)
-offlinemsg_la_LIBADD        = $(GLIB_LIBS)
-one_time_password_la_LIBADD = $(GLIB_LIBS)
-pluginpref_example_la_LIBADD = $(GLIB_LIBS)
-psychic_la_LIBADD           = $(GLIB_LIBS)
-signals_test_la_LIBADD		= $(GLIB_LIBS)
-simple_la_LIBADD			= $(GLIB_LIBS)
-statenotify_la_LIBADD       = $(GLIB_LIBS)
-
-if ENABLE_DBUS
-
-CLEANFILES              = dbus-example-bindings.c
-dbus_example_la_SOURCES = dbus-example.c
-
-dbus_example_la_LIBADD      = $(GLIB_LIBS) $(DBUS_LIBS)
-
-.PHONY: always
-
-$(top_builddir)/libpurple/dbus-types.h: always
-	@echo -e "  GEN\t$@"
-	@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
-
-dbus-example-bindings.c: $(top_srcdir)/libpurple/dbus-analyze-functions.py $(dbus_example_la_SOURCES)
-	@echo -e "  GEN\t$@"
-	@cat $(srcdir)/$(dbus_example_la_SOURCES) | \
-	$(PYTHON) $(top_srcdir)/libpurple/dbus-analyze-functions.py --export-only > $@
-
-$(dbus_example_la_OBJECTS) dbus-example.so: dbus-example-bindings.c $(top_builddir)/libpurple/dbus-types.h
-
-
-endif # ENABLE_DBUS
-
-endif # PLUGINS
-
-EXTRA_DIST = \
-	Makefile.mingw \
-	dbus-buddyicons-example.py \
-	filectl.c \
-	fortuneprofile.pl \
-	ipc-test-client.c \
-	ipc-test-server.c \
-	startup.py
-
-AM_CPPFLAGS = \
-	-DDATADIR=\"$(datadir)\" \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS) \
-	$(PLUGIN_CFLAGS) \
-	$(DBUS_CFLAGS) \
-	$(NSS_CFLAGS)
-
-PLUGIN_LIBS = \
-	$(NSS_LIBS)
-
+#DIST_SUBDIRS = mono perl ssl tcl keyrings
+#
+#if USE_PERL
+#PERL_DIR = perl
+#endif
+#
+#if USE_TCL
+#TCL_DIR = tcl
+#endif
+#
+#if ENABLE_DBUS
+#DBUS_LTLIB = dbus-example.la
+#endif
+#
+#if USE_MONO
+#MONO_DIR = mono
+#endif
+#
+#SUBDIRS = \
+#	$(MONO_DIR) \
+#	$(PERL_DIR) \
+#	ssl \
+#	$(TCL_DIR) \
+#	keyrings
+#
+#plugindir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+#
+#autoaccept_la_LDFLAGS       = -module -avoid-version
+#buddynote_la_LDFLAGS        = -module -avoid-version
+#ciphertest_la_LDFLAGS		= -module -avoid-version
+#codeinline_la_LDFLAGS		= -module -avoid-version
+#debug_example_la_LDFLAGS    = -module -avoid-version
+#helloworld_la_LDFLAGS       = -module -avoid-version
+#idle_la_LDFLAGS             = -module -avoid-version
+#joinpart_la_LDFLAGS         = -module -avoid-version
+#log_reader_la_LDFLAGS       = -module -avoid-version
+#newline_la_LDFLAGS          = -module -avoid-version
+#notify_example_la_LDFLAGS   = -module -avoid-version
+#offlinemsg_la_LDFLAGS       = -module -avoid-version
+#one_time_password_la_LDFLAGS	= -module -avoid-version
+#pluginpref_example_la_LDFLAGS = -module -avoid-version
+#psychic_la_LDFLAGS          = -module -avoid-version
+#signals_test_la_LDFLAGS		= -module -avoid-version
+#simple_la_LDFLAGS			= -module -avoid-version
+#statenotify_la_LDFLAGS      = -module -avoid-version
+#
+## this can't be in a conditional otherwise automake 1.4 yells
+#dbus_example_la_LDFLAGS     = -module -avoid-version
+#
+#if PLUGINS
+#
+#plugin_LTLIBRARIES = \
+#	autoaccept.la       \
+#	buddynote.la        \
+#	idle.la             \
+#	joinpart.la         \
+#	log_reader.la       \
+#	newline.la          \
+#	offlinemsg.la       \
+#	psychic.la          \
+#	statenotify.la      \
+#	$(DBUS_LTLIB)
+#
+#noinst_LTLIBRARIES = \
+#	ciphertest.la \
+#	codeinline.la \
+#	debug_example.la \
+#	helloworld.la \
+#	notify_example.la \
+#	one_time_password.la \
+#	pluginpref_example.la \
+#	signals_test.la \
+#	simple.la
 #
-# This part allows people to build their own plugins in here.
-# Yes, it's a mess.
+#autoaccept_la_SOURCES       = autoaccept.c
+#buddynote_la_SOURCES        = buddynote.c
+#ciphertest_la_SOURCES		= ciphertest.c
+#codeinline_la_SOURCES		= codeinline.c
+#debug_example_la_SOURCES = debug_example.c
+#helloworld_la_SOURCES       = helloworld.c
+#idle_la_SOURCES             = idle.c
+#joinpart_la_SOURCES         = joinpart.c
+#log_reader_la_SOURCES       = log_reader.c
+#newline_la_SOURCES          = newline.c
+#notify_example_la_SOURCES   = notify_example.c
+#offlinemsg_la_SOURCES       = offlinemsg.c
+#one_time_password_la_SOURCES	= one_time_password.c
+#pluginpref_example_la_SOURCES = pluginpref_example.c
+#psychic_la_SOURCES          = psychic.c
+#signals_test_la_SOURCES		= signals-test.c
+#simple_la_SOURCES			= simple.c
+#statenotify_la_SOURCES      = statenotify.c
+#
+#autoaccept_la_LIBADD        = $(GLIB_LIBS)
+#buddynote_la_LIBADD         = $(GLIB_LIBS)
+#ciphertest_la_LIBADD		= $(GLIB_LIBS)
+#codeinline_la_LIBADD		= $(GLIB_LIBS)
+#idle_la_LIBADD              = $(GLIB_LIBS)
+#joinpart_la_LIBADD          = $(GLIB_LIBS)
+#log_reader_la_LIBADD        = $(GLIB_LIBS)
+#newline_la_LIBADD           = $(GLIB_LIBS)
+#notify_example_la_LIBADD    = $(GLIB_LIBS)
+#offlinemsg_la_LIBADD        = $(GLIB_LIBS)
+#one_time_password_la_LIBADD = $(GLIB_LIBS)
+#pluginpref_example_la_LIBADD = $(GLIB_LIBS)
+#psychic_la_LIBADD           = $(GLIB_LIBS)
+#signals_test_la_LIBADD		= $(GLIB_LIBS)
+#simple_la_LIBADD			= $(GLIB_LIBS)
+#statenotify_la_LIBADD       = $(GLIB_LIBS)
+#
+#if ENABLE_DBUS
+#
+#CLEANFILES              = dbus-example-bindings.c
+#dbus_example_la_SOURCES = dbus-example.c
+#
+#dbus_example_la_LIBADD      = $(GLIB_LIBS) $(DBUS_LIBS)
+#
+#.PHONY: always
 #
-SUFFIXES = .c .so
-.c.so:
-	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
-	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
-	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
-	@cp .libs/libtmp$@*.so $@
-	@rm -rf .libs/libtmp$@.*
+#$(top_builddir)/libpurple/dbus-types.h: always
+#	@echo -e "  GEN\t$@"
+#	@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
+#
+#dbus-example-bindings.c: $(top_srcdir)/libpurple/dbus-analyze-functions.py $(dbus_example_la_SOURCES)
+#	@echo -e "  GEN\t$@"
+#	@cat $(srcdir)/$(dbus_example_la_SOURCES) | \
+#	$(PYTHON) $(top_srcdir)/libpurple/dbus-analyze-functions.py --export-only > $@
+#
+#$(dbus_example_la_OBJECTS) dbus-example.so: dbus-example-bindings.c $(top_builddir)/libpurple/dbus-types.h
+#
+#
+#endif # ENABLE_DBUS
+#
+#endif # PLUGINS
+#
+#EXTRA_DIST = \
+#	Makefile.mingw \
+#	dbus-buddyicons-example.py \
+#	filectl.c \
+#	fortuneprofile.pl \
+#	ipc-test-client.c \
+#	ipc-test-server.c \
+#	startup.py
+#
+#AM_CPPFLAGS = \
+#	-DDATADIR=\"$(datadir)\" \
+#	-I$(top_srcdir)/libpurple \
+#	-I$(top_builddir)/libpurple \
+#	$(DEBUG_CFLAGS) \
+#	$(GLIB_CFLAGS) \
+#	$(GPLUGIN_CFLAGS) \
+#	$(PLUGIN_CFLAGS) \
+#	$(DBUS_CFLAGS) \
+#	$(NSS_CFLAGS)
+#
+#PLUGIN_LIBS = \
+#	$(NSS_LIBS)
+#
+##
+## This part allows people to build their own plugins in here.
+## Yes, it's a mess.
+##
+#SUFFIXES = .c .so
+#.c.so:
+#	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
+#	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
+#	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
+#	@cp .libs/libtmp$@*.so $@
+#	@rm -rf .libs/libtmp$@.*
--- a/libpurple/plugins/autoaccept.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/autoaccept.c	Sun Aug 18 01:53:00 2013 +0530
@@ -31,7 +31,7 @@
 #include <glib/gstdio.h>
 
 /* Purple headers */
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 
 #include <buddylist.h>
--- a/libpurple/plugins/ciphertest.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ciphertest.c	Sun Aug 18 01:53:00 2013 +0530
@@ -33,7 +33,7 @@
 #include <string.h>
 
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 #include "util.h"
 
--- a/libpurple/plugins/codeinline.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/codeinline.c	Sun Aug 18 01:53:00 2013 +0530
@@ -21,7 +21,7 @@
  */
 
 #include "internal.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "notify.h"
 #include "util.h"
 #include "version.h"
--- a/libpurple/plugins/dbus-example.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/dbus-example.c	Sun Aug 18 01:53:00 2013 +0530
@@ -39,7 +39,7 @@
 
 #include "buddylist.h"
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #include <stdio.h>
--- a/libpurple/plugins/debug_example.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/debug_example.c	Sun Aug 18 01:53:00 2013 +0530
@@ -48,7 +48,7 @@
  * that we're including them in alphabetical order.  This isn't necessary but
  * we do this throughout our source for consistency. */
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 /* It's more convenient to type PLUGIN_ID all the time than it is to type
--- a/libpurple/plugins/helloworld.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/helloworld.c	Sun Aug 18 01:53:00 2013 +0530
@@ -44,7 +44,7 @@
 #endif
 
 #include <notify.h>
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 
 /* we're adding this here and assigning it in plugin_load because we need
--- a/libpurple/plugins/idle.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/idle.c	Sun Aug 18 01:53:00 2013 +0530
@@ -27,7 +27,7 @@
 #include "connection.h"
 #include "debug.h"
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "presence.h"
 #include "request.h"
 #include "server.h"
@@ -53,7 +53,7 @@
 {
 	PurplePlugin *prpl;
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	prpl = purple_find_protocol_info(purple_account_get_protocol_id(account));
 	g_return_val_if_fail(prpl != NULL, FALSE);
 
 	return (PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->set_idle != NULL);
--- a/libpurple/plugins/ipc-test-client.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ipc-test-client.c	Sun Aug 18 01:53:00 2013 +0530
@@ -20,7 +20,7 @@
  */
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #define IPC_TEST_CLIENT_PLUGIN_ID "core-ipc-test-client"
--- a/libpurple/plugins/ipc-test-server.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ipc-test-server.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
 
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 static int
--- a/libpurple/plugins/joinpart.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/joinpart.c	Sun Aug 18 01:53:00 2013 +0530
@@ -23,7 +23,7 @@
 #include "internal.h"
 #include "conversation.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #define JOINPART_PLUGIN_ID "core-rlaager-joinpart"
--- a/libpurple/plugins/keyrings/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/keyrings/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -72,5 +72,6 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CPPFLAGS) \
 	$(PLUGIN_CFLAGS)
--- a/libpurple/plugins/keyrings/gnomekeyring.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/keyrings/gnomekeyring.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "account.h"
 #include "debug.h"
 #include "keyring.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #include <gnome-keyring.h>
@@ -39,6 +39,7 @@
 	"GNOME Keyring.")
 #define GNOMEKEYRING_AUTHOR      "Tomek Wasilczyk (tomkiewicz@cpw.pidgin.im)"
 #define GNOMEKEYRING_ID          "keyring-gnomekeyring"
+#define GNOMEKEYRING_DOMAIN      (g_quark_from_static_string(GNOMEKEYRING_ID))
 
 static PurpleKeyring *keyring_handler = NULL;
 static GList *request_queue = NULL;
@@ -377,8 +378,26 @@
 	gnomekeyring_cancel();
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           GNOMEKEYRING_ID,
+		"name",         GNOMEKEYRING_NAME,
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Keyring"),
+		"summary",      "GNOME Keyring Plugin",
+		"description",  GNOMEKEYRING_DESCRIPTION,
+		"author",       GNOMEKEYRING_AUTHOR,
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
+}
+
 static gboolean
-gnomekeyring_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	GModule *gkr_module;
 
@@ -394,6 +413,8 @@
 	g_module_make_resident(gkr_module);
 
 	if (!gnome_keyring_is_available()) {
+		g_set_error(error, GNOMEKEYRING_DOMAIN, 0, "GNOME Keyring service is "
+			"disabled.");
 		purple_debug_info("keyring-gnome", "GNOME Keyring service is "
 			"disabled\n");
 		return FALSE;
@@ -415,9 +436,11 @@
 }
 
 static gboolean
-gnomekeyring_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if (purple_keyring_get_inuse() == keyring_handler) {
+		g_set_error(error, GNOMEKEYRING_DOMAIN, 0, "The keyring is currently "
+			"in use.");
 		purple_debug_warning("keyring-gnome",
 			"keyring in use, cannot unload\n");
 		return FALSE;
@@ -432,36 +455,4 @@
 	return TRUE;
 }
 
-PurplePluginInfo plugininfo =
-{
-	PURPLE_PLUGIN_MAGIC,		/* magic */
-	PURPLE_MAJOR_VERSION,		/* major_version */
-	PURPLE_MINOR_VERSION,		/* minor_version */
-	PURPLE_PLUGIN_STANDARD,		/* type */
-	NULL,				/* ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,	/* flags */
-	NULL,				/* dependencies */
-	PURPLE_PRIORITY_DEFAULT,	/* priority */
-	GNOMEKEYRING_ID,		/* id */
-	GNOMEKEYRING_NAME,		/* name */
-	DISPLAY_VERSION,		/* version */
-	"GNOME Keyring Plugin",		/* summary */
-	GNOMEKEYRING_DESCRIPTION,	/* description */
-	GNOMEKEYRING_AUTHOR,		/* author */
-	PURPLE_WEBSITE,			/* homepage */
-	gnomekeyring_load,		/* load */
-	gnomekeyring_unload,		/* unload */
-	NULL,				/* destroy */
-	NULL,				/* ui_info */
-	NULL,				/* extra_info */
-	NULL,				/* prefs_info */
-	NULL,				/* actions */
-	NULL, NULL, NULL, NULL		/* padding */
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(gnome_keyring, init_plugin, plugininfo)
+PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/keyrings/internalkeyring.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/keyrings/internalkeyring.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "account.h"
 #include "debug.h"
 #include "keyring.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #include "ciphers/aescipher.h"
@@ -40,6 +40,7 @@
 	"storage behaviour for libpurple.")
 #define INTKEYRING_AUTHOR "Tomek Wasilczyk (tomkiewicz@cpw.pidgin.im)"
 #define INTKEYRING_ID PURPLE_DEFAULT_KEYRING
+#define INTKEYRING_DOMAIN (g_quark_from_static_string(INTKEYRING_ID))
 
 #define INTKEYRING_VERIFY_STR "[verification-string]"
 #define INTKEYRING_PBKDF2_ITERATIONS 10000
@@ -954,9 +955,39 @@
 	return TRUE;
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           INTKEYRING_ID,
+		"name",         INTKEYRING_NAME,
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Keyring"),
+		"summary",      "Internal Keyring Plugin",
+		"description",  INTKEYRING_DESCRIPTION,
+		"author",       INTKEYRING_AUTHOR,
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
+}
+
 static gboolean
-intkeyring_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
+	purple_prefs_add_none("/plugins/keyrings");
+	purple_prefs_add_none("/plugins/keyrings/internal");
+	purple_prefs_add_bool(INTKEYRING_PREFS "encrypt_passwords", FALSE);
+	purple_prefs_add_string(INTKEYRING_PREFS "encryption_method",
+		INTKEYRING_ENCRYPTION_METHOD);
+	purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_desired_iterations",
+		INTKEYRING_PBKDF2_ITERATIONS);
+	purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_iterations",
+		INTKEYRING_PBKDF2_ITERATIONS);
+	purple_prefs_add_string(INTKEYRING_PREFS "pbkdf2_salt", "");
+	purple_prefs_add_string(INTKEYRING_PREFS "key_verifier", "");
+
 	keyring_handler = purple_keyring_new();
 
 	purple_keyring_set_name(keyring_handler, _(INTKEYRING_NAME));
@@ -982,9 +1013,11 @@
 }
 
 static gboolean
-intkeyring_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if (purple_keyring_get_inuse() == keyring_handler) {
+		g_set_error(error, INTKEYRING_DOMAIN, 0, "The keyring is currently "
+			"in use.");
 		purple_debug_warning("keyring-internal",
 			"keyring in use, cannot unload\n");
 		return FALSE;
@@ -1006,47 +1039,4 @@
 	return TRUE;
 }
 
-PurplePluginInfo plugininfo =
-{
-	PURPLE_PLUGIN_MAGIC,		/* magic */
-	PURPLE_MAJOR_VERSION,		/* major_version */
-	PURPLE_MINOR_VERSION,		/* minor_version */
-	PURPLE_PLUGIN_STANDARD,		/* type */
-	NULL,				/* ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,	/* flags */
-	NULL,				/* dependencies */
-	PURPLE_PRIORITY_DEFAULT,	/* priority */
-	INTKEYRING_ID,			/* id */
-	INTKEYRING_NAME,		/* name */
-	DISPLAY_VERSION,		/* version */
-	"Internal Keyring Plugin",	/* summary */
-	INTKEYRING_DESCRIPTION,		/* description */
-	INTKEYRING_AUTHOR,		/* author */
-	PURPLE_WEBSITE,			/* homepage */
-	intkeyring_load,		/* load */
-	intkeyring_unload,		/* unload */
-	NULL,				/* destroy */
-	NULL,				/* ui_info */
-	NULL,				/* extra_info */
-	NULL,				/* prefs_info */
-	NULL,				/* actions */
-	NULL, NULL, NULL, NULL		/* padding */
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	purple_prefs_add_none("/plugins/keyrings");
-	purple_prefs_add_none("/plugins/keyrings/internal");
-	purple_prefs_add_bool(INTKEYRING_PREFS "encrypt_passwords", FALSE);
-	purple_prefs_add_string(INTKEYRING_PREFS "encryption_method",
-		INTKEYRING_ENCRYPTION_METHOD);
-	purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_desired_iterations",
-		INTKEYRING_PBKDF2_ITERATIONS);
-	purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_iterations",
-		INTKEYRING_PBKDF2_ITERATIONS);
-	purple_prefs_add_string(INTKEYRING_PREFS "pbkdf2_salt", "");
-	purple_prefs_add_string(INTKEYRING_PREFS "key_verifier", "");
-}
-
-PURPLE_INIT_PLUGIN(internal_keyring, init_plugin, plugininfo)
+PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/keyrings/kwallet.cpp	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/keyrings/kwallet.cpp	Sun Aug 18 01:53:00 2013 +0530
@@ -29,7 +29,7 @@
 #include "core.h"
 #include "debug.h"
 #include "keyring.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #include <QQueue>
@@ -40,6 +40,7 @@
 #define KWALLET_DESCRIPTION N_("This plugin will store passwords in KWallet.")
 #define KWALLET_AUTHOR      "QuLogic (qulogic[at]pidgin.im)"
 #define KWALLET_ID          "keyring-kwallet"
+#define KWALLET_DOMAIN      (g_quark_from_static_string(KWALLET_ID))
 
 #define KWALLET_WALLET_NAME KWallet::Wallet::NetworkWallet()
 #define KWALLET_APP_NAME "Libpurple"
@@ -488,8 +489,26 @@
 	return ui_name;
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           KWALLET_ID,
+		"name",         KWALLET_NAME,
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Keyring"),
+		"summary",      "KWallet Keyring Plugin",
+		"description",  KWALLET_DESCRIPTION,
+		"author",       KWALLET_AUTHOR,
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
+}
+
 static gboolean
-kwallet_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	if (!qCoreApp) {
 		int argc = 0;
@@ -498,6 +517,7 @@
 	}
 
 	if (!kwallet_is_enabled()) {
+		g_set_error(error, KWALLET_DOMAIN, 0, "KWallet service is disabled.");
 		purple_debug_info("keyring-kwallet",
 			"KWallet service is disabled\n");
 		return FALSE;
@@ -519,9 +539,11 @@
 }
 
 static gboolean
-kwallet_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if (purple_keyring_get_inuse() == keyring_handler) {
+		g_set_error(error, KWALLET_DOMAIN, 0, "The keyring is currently "
+			"in use.");
 		purple_debug_warning("keyring-kwallet",
 			"keyring in use, cannot unload\n");
 		return FALSE;
@@ -543,39 +565,7 @@
 	return TRUE;
 }
 
-PurplePluginInfo plugininfo =
-{
-	PURPLE_PLUGIN_MAGIC,			/* magic */
-	PURPLE_MAJOR_VERSION,			/* major_version */
-	PURPLE_MINOR_VERSION,			/* minor_version */
-	PURPLE_PLUGIN_STANDARD,			/* type */
-	NULL,					/* ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,		/* flags */
-	NULL,					/* dependencies */
-	PURPLE_PRIORITY_DEFAULT,		/* priority */
-	KWALLET_ID,				/* id */
-	KWALLET_NAME,				/* name */
-	DISPLAY_VERSION,			/* version */
-	"KWallet Keyring Plugin",		/* summary */
-	KWALLET_DESCRIPTION,			/* description */
-	KWALLET_AUTHOR,				/* author */
-	PURPLE_WEBSITE,				/* homepage */
-	kwallet_load,				/* load */
-	kwallet_unload,				/* unload */
-	NULL,					/* destroy */
-	NULL,					/* ui_info */
-	NULL,					/* extra_info */
-	NULL,					/* prefs_info */
-	NULL,					/* actions */
-	NULL, NULL, NULL, NULL			/* padding */
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(kwallet_keyring, init_plugin, plugininfo)
+PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
 
 } /* extern "C" */
 
--- a/libpurple/plugins/keyrings/secretservice.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/keyrings/secretservice.c	Sun Aug 18 01:53:00 2013 +0530
@@ -38,13 +38,14 @@
 #include "account.h"
 #include "debug.h"
 #include "keyring.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #include <libsecret/secret.h>
 
 #define SECRETSERVICE_NAME        N_("Secret Service")
 #define SECRETSERVICE_ID          "keyring-libsecret"
+#define SECRETSERVICE_DOMAIN      (g_quark_from_static_string(SECRETSERVICE_ID))
 
 static PurpleKeyring *keyring_handler = NULL;
 
@@ -253,7 +254,7 @@
 }
 
 static gboolean
-ss_init(void)
+ss_init(GError **error)
 {
 	keyring_handler = purple_keyring_new();
 
@@ -281,57 +282,43 @@
 /*     Plugin interface                        */
 /***********************************************/
 
-static gboolean
-ss_load(PurplePlugin *plugin)
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	return ss_init();
+	return purple_plugin_info_new(
+		"id",           SECRETSERVICE_ID,
+		"name",         SECRETSERVICE_NAME,
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Keyring"),
+		"summary",      "Secret Service Plugin",
+		"description",  N_("This plugin will store passwords in Secret Service."),
+		"author",       "Elliott Sales de Andrade (qulogic[at]pidgin.im)",
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
 }
 
 static gboolean
-ss_unload(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
-	if (purple_keyring_get_inuse() == keyring_handler)
+	return ss_init(error);
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	if (purple_keyring_get_inuse() == keyring_handler) {
+		g_set_error(error, SECRETSERVICE_DOMAIN, 0, "The keyring is currently "
+			"in use.");
 		return FALSE;
+	}
 
 	ss_uninit();
 
 	return TRUE;
 }
 
-PurplePluginInfo plugininfo =
-{
-	PURPLE_PLUGIN_MAGIC,		/* magic */
-	PURPLE_MAJOR_VERSION,		/* major_version */
-	PURPLE_MINOR_VERSION,		/* minor_version */
-	PURPLE_PLUGIN_STANDARD,		/* type */
-	NULL,						/* ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,	/* flags */
-	NULL,						/* dependencies */
-	PURPLE_PRIORITY_DEFAULT,	/* priority */
-	SECRETSERVICE_ID,			/* id */
-	SECRETSERVICE_NAME,			/* name */
-	DISPLAY_VERSION,			/* version */
-	"Secret Service Plugin",		/* summary */
-	N_("This plugin will store passwords in Secret Service."),	/* description */
-	"Elliott Sales de Andrade (qulogic[at]pidgin.im)",		/* author */
-	PURPLE_WEBSITE,				/* homepage */
-	ss_load,					/* load */
-	ss_unload,					/* unload */
-	NULL,						/* destroy */
-	NULL,						/* ui_info */
-	NULL,						/* extra_info */
-	NULL,						/* prefs_info */
-	NULL,						/* actions */
-	NULL,						/* padding... */
-	NULL,
-	NULL,
-	NULL,
-};
+PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
 
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(secret_service, init_plugin, plugininfo)
-
--- a/libpurple/plugins/keyrings/wincred.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/keyrings/wincred.c	Sun Aug 18 01:53:00 2013 +0530
@@ -27,7 +27,7 @@
 #include "debug.h"
 #include "internal.h"
 #include "keyring.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 #include <wincred.h>
@@ -38,6 +38,7 @@
 	"credentials.")
 #define WINCRED_AUTHOR      "Tomek Wasilczyk (tomkiewicz@cpw.pidgin.im)"
 #define WINCRED_ID          "keyring-wincred"
+#define WINCRED_DOMAIN      (g_quark_from_static_string(WINCRED_ID))
 
 #define WINCRED_MAX_TARGET_NAME 256
 
@@ -255,8 +256,26 @@
 		g_error_free(error);
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           WINCRED_ID,
+		"name",         WINCRED_NAME,
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Keyring"),
+		"summary",      WINCRED_SUMMARY,
+		"description",  WINCRED_DESCRIPTION,
+		"author",       WINCRED_AUTHOR,
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
+}
+
 static gboolean
-wincred_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	keyring_handler = purple_keyring_new();
 
@@ -271,9 +290,11 @@
 }
 
 static gboolean
-wincred_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if (purple_keyring_get_inuse() == keyring_handler) {
+		g_set_error(error, WINCRED_DOMAIN, 0, "The keyring is currently "
+			"in use.");
 		purple_debug_warning("keyring-wincred",
 			"keyring in use, cannot unload\n");
 		return FALSE;
@@ -286,36 +307,4 @@
 	return TRUE;
 }
 
-PurplePluginInfo plugininfo =
-{
-	PURPLE_PLUGIN_MAGIC,		/* magic */
-	PURPLE_MAJOR_VERSION,		/* major_version */
-	PURPLE_MINOR_VERSION,		/* minor_version */
-	PURPLE_PLUGIN_STANDARD,		/* type */
-	NULL,				/* ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,	/* flags */
-	NULL,				/* dependencies */
-	PURPLE_PRIORITY_DEFAULT,	/* priority */
-	WINCRED_ID,			/* id */
-	WINCRED_NAME,			/* name */
-	DISPLAY_VERSION,		/* version */
-	WINCRED_SUMMARY,		/* summary */
-	WINCRED_DESCRIPTION,		/* description */
-	WINCRED_AUTHOR,			/* author */
-	PURPLE_WEBSITE,			/* homepage */
-	wincred_load,			/* load */
-	wincred_unload,			/* unload */
-	NULL,				/* destroy */
-	NULL,				/* ui_info */
-	NULL,				/* extra_info */
-	NULL,				/* prefs_info */
-	NULL,				/* actions */
-	NULL, NULL, NULL, NULL		/* padding */
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(wincred_keyring, init_plugin, plugininfo)
+PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/log_reader.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/log_reader.c	Sun Aug 18 01:53:00 2013 +0530
@@ -4,7 +4,7 @@
 
 #include "debug.h"
 #include "log.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "pluginpref.h"
 #include "prefs.h"
 #include "stringref.h"
@@ -67,8 +67,8 @@
 	GList *list = NULL;
 	const char *logdir;
 	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prpl_info;
-	char *prpl_name;
+	PurpleProtocol *protocol;
+	char *protocol_name;
 	char *temp;
 	char *path;
 	GDir *dir;
@@ -82,17 +82,17 @@
 	if (!logdir || !*logdir)
 		return NULL;
 
-	plugin = purple_find_prpl(purple_account_get_protocol_id(account));
+	plugin = purple_find_protocol_info(purple_account_get_protocol_id(account));
 	if (!plugin)
 		return NULL;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-	if (!prpl_info->list_icon)
+	protocol = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+	if (!protocol->list_icon)
 		return NULL;
 
-	prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1);
-
-	temp = g_strdup_printf("%s.%s", prpl_name, purple_account_get_username(account));
+	protocol_name = g_ascii_strup(protocol->list_icon(account, NULL), -1);
+
+	temp = g_strdup_printf("%s.%s", protocol_name, purple_account_get_username(account));
 	path = g_build_filename(logdir, temp, sn, NULL);
 	g_free(temp);
 
@@ -227,7 +227,7 @@
 		g_dir_close(dir);
 	}
 
-	g_free(prpl_name);
+	g_free(protocol_name);
 	g_free(path);
 
 	return list;
@@ -1206,8 +1206,8 @@
 	GList *list = NULL;
 	const char *logdir;
 	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prpl_info;
-	char *prpl_name;
+	PurpleProtocol *protocol;
+	char *protocol_name;
 	const char *buddy_name;
 	char *filename;
 	char *path;
@@ -1226,21 +1226,21 @@
 	if (!logdir || !*logdir)
 		return NULL;
 
-	plugin = purple_find_prpl(purple_account_get_protocol_id(account));
+	plugin = purple_find_protocol_info(purple_account_get_protocol_id(account));
 	if (!plugin)
 		return NULL;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-	if (!prpl_info->list_icon)
+	protocol = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+	if (!protocol->list_icon)
 		return NULL;
 
-	prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1);
+	protocol_name = g_ascii_strup(protocol->list_icon(account, NULL), -1);
 
 	buddy_name = purple_normalize(account, sn);
 
 	filename = g_strdup_printf("%s.log", buddy_name);
 	path = g_build_filename(
-		logdir, prpl_name, filename, NULL);
+		logdir, protocol_name, filename, NULL);
 
 	purple_debug_info("Trillian log list", "Reading %s\n", path);
 	/* FIXME: There's really no need to read the entire file at once.
@@ -1254,7 +1254,7 @@
 		g_free(path);
 
 		path = g_build_filename(
-			logdir, prpl_name, "Query", filename, NULL);
+			logdir, protocol_name, "Query", filename, NULL);
 		purple_debug_info("Trillian log list", "Reading %s\n", path);
 		if (!g_file_get_contents(path, &contents, &length, &error)) {
 			if (error)
@@ -1390,7 +1390,7 @@
 	}
 	g_free(path);
 
-	g_free(prpl_name);
+	g_free(protocol_name);
 
 	return g_list_reverse(list);
 }
@@ -1757,7 +1757,7 @@
 	GList *list = NULL;
 	const char *logdir;
 	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	char *username;
 	char *filename;
 	char *path;
@@ -1786,12 +1786,12 @@
 	if (!logdir || !*logdir)
 		return NULL;
 
-	plugin = purple_find_prpl(purple_account_get_protocol_id(account));
+	plugin = purple_find_protocol_info(purple_account_get_protocol_id(account));
 	if (!plugin)
 		return NULL;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-	if (!prpl_info->list_icon)
+	protocol = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+	if (!protocol->list_icon)
 		return NULL;
 
 	username = g_strdup(purple_normalize(account, purple_account_get_username(account)));
--- a/libpurple/plugins/mono/loader/mono-helper.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/mono/loader/mono-helper.h	Sun Aug 18 01:53:00 2013 +0530
@@ -7,7 +7,7 @@
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/tokentype.h>
-#include "plugin.h"
+#include "plugins.h"
 #include "debug.h"
 
 typedef struct {
--- a/libpurple/plugins/mono/loader/mono.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/mono/loader/mono.c	Sun Aug 18 01:53:00 2013 +0530
@@ -12,7 +12,7 @@
 
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 #include "mono-helper.h"
 
--- a/libpurple/plugins/newline.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/newline.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
 
 #include <conversation.h>
 #include <debug.h>
-#include <plugin.h>
+#include <plugins.h>
 #include <signals.h>
 #include <util.h>
 #include <version.h>
--- a/libpurple/plugins/notify_example.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/notify_example.c	Sun Aug 18 01:53:00 2013 +0530
@@ -47,7 +47,7 @@
 #define PLUGIN_AUTHOR "John Bailey <rekkanoryo@cpw.pidgin.im>"
 
 #include <notify.h>
-#include <plugin.h>
+#include <plugins.h>
 #include <version.h>
 
 static PurplePlugin *notify_example = NULL;
--- a/libpurple/plugins/one_time_password.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/one_time_password.c	Sun Aug 18 01:53:00 2013 +0530
@@ -20,7 +20,7 @@
  */
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 #include "account.h"
 #include "accountopt.h"
@@ -56,18 +56,18 @@
 plugin_load(PurplePlugin *plugin)
 {
 	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleAccountOption *option;
 	GList *l;
 
 	/* Register protocol preference. */
 	for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) {
 		prpl = (PurplePlugin *)l->data;
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-		if (prpl_info != NULL && !(prpl_info->options & OPT_PROTO_NO_PASSWORD)) {
+		protocol = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		if (protocol != NULL && !(protocol->options & OPT_PROTO_NO_PASSWORD)) {
 			option = purple_account_option_bool_new(_("One Time Password"),
 								PREF_NAME, FALSE);
-			prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+			protocol->protocol_options = g_list_append(protocol->protocol_options, option);
 		}
 	}
 
@@ -82,20 +82,20 @@
 plugin_unload(PurplePlugin *plugin)
 {
 	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleAccountOption *option;
 	GList *l, *options;
 
 	/* Remove protocol preference. */
 	for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) {
 		prpl = (PurplePlugin *)l->data;
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-		if (prpl_info != NULL && !(prpl_info->options & OPT_PROTO_NO_PASSWORD)) {
-			options = prpl_info->protocol_options;
+		protocol = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		if (protocol != NULL && !(protocol->options & OPT_PROTO_NO_PASSWORD)) {
+			options = protocol->protocol_options;
 			while (options != NULL) {
 				option = (PurpleAccountOption *) options->data;
 				if (strcmp(PREF_NAME, purple_account_option_get_setting(option)) == 0) {
-					prpl_info->protocol_options = g_list_delete_link(prpl_info->protocol_options, options);
+					protocol->protocol_options = g_list_delete_link(protocol->protocol_options, options);
 					purple_account_option_destroy(option);
 					break;
 				}
--- a/libpurple/plugins/perl/common/Cmds.xs	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/common/Cmds.xs	Sun Aug 18 01:53:00 2013 +0530
@@ -17,7 +17,7 @@
 		const_iv(FAILED),
 		const_iv(NOT_FOUND),
 		const_iv(WRONG_ARGS),
-		const_iv(WRONG_PRPL),
+		const_iv(WRONG_PROTOCOL),
 		const_iv(WRONG_TYPE),
 	};
 	static const constiv ret_const_iv[] = {
@@ -44,7 +44,7 @@
 #define const_iv(name) {#name, (IV)PURPLE_CMD_FLAG_##name}
 		const_iv(IM),
 		const_iv(CHAT),
-		const_iv(PRPL_ONLY),
+		const_iv(PROTOCOL_ONLY),
 		const_iv(ALLOW_WRONG_ARGS),
 	};
 
@@ -85,19 +85,19 @@
 	g_list_free(ll);
 
 Purple::Cmd::Id
-purple_cmd_register(plugin, command, args, priority, flag, prpl_id, func, helpstr, data = 0)
+purple_cmd_register(plugin, command, args, priority, flag, protocol_id, func, helpstr, data = 0)
 	Purple::Plugin plugin
 	const gchar *command
 	const gchar *args
 	Purple::Cmd::Priority priority
 	Purple::Cmd::Flag flag
-	const gchar *prpl_id
+	const gchar *protocol_id
 	SV *func
 	const gchar *helpstr
 	SV *data
 CODE:
 	RETVAL = purple_perl_cmd_register(plugin, command, args, priority, flag,
-	                                prpl_id, func, helpstr, data);
+	                                protocol_id, func, helpstr, data);
 OUTPUT:
 	RETVAL
 
--- a/libpurple/plugins/perl/common/Prpl.xs	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/common/Prpl.xs	Sun Aug 18 01:53:00 2013 +0530
@@ -4,26 +4,26 @@
 PROTOTYPES: ENABLE
 
 Purple::Plugin
-purple_find_prpl(id)
+purple_find_protocol_info(id)
 	const char *id
 
-MODULE = Purple::Prpl  PACKAGE = Purple::Prpl  PREFIX = purple_prpl_
+MODULE = Purple::Prpl  PACKAGE = Purple::Prpl  PREFIX = purple_protocol_
 PROTOTYPES: ENABLE
 
 void
-purple_prpl_change_account_status(account, old_status, new_status)
+purple_protocol_change_account_status(account, old_status, new_status)
 	Purple::Account account
 	Purple::Status old_status
 	Purple::Status new_status
 
 void
-purple_prpl_get_statuses(account, presence)
+purple_protocol_get_statuses(account, presence)
 	Purple::Account account
 	Purple::Presence presence
 PREINIT:
 	GList *l, *ll;
 PPCODE:
-	ll = purple_prpl_get_statuses(account,presence);
+	ll = purple_protocol_get_statuses(account,presence);
 	for (l = ll; l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status")));
 	}
@@ -32,42 +32,42 @@
 	g_list_free(ll);
 
 void
-purple_prpl_got_account_idle(account, idle, idle_time)
+purple_protocol_got_account_idle(account, idle, idle_time)
 	Purple::Account account
 	gboolean idle
 	time_t idle_time
 
 void
-purple_prpl_got_account_login_time(account, login_time)
+purple_protocol_got_account_login_time(account, login_time)
 	Purple::Account account
 	time_t login_time
 
 void
-purple_prpl_got_user_idle(account, name, idle, idle_time)
+purple_protocol_got_user_idle(account, name, idle, idle_time)
 	Purple::Account account
 	const char *name
 	gboolean idle
 	time_t idle_time
 
 void
-purple_prpl_got_user_login_time(account, name, login_time)
+purple_protocol_got_user_login_time(account, name, login_time)
 	Purple::Account account
 	const char *name
 	time_t login_time
 
 int
-purple_prpl_send_raw(gc, str)
+purple_protocol_send_raw(gc, str)
 	Purple::Connection gc
 	const char *str
 PREINIT:
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 CODE:
 	if (!gc)
 		RETVAL = 0;
 	else {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-		if (prpl_info && prpl_info->send_raw != NULL) {
-			RETVAL = prpl_info->send_raw(gc, str, strlen(str));
+		protocol = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_protocol_info(gc));
+		if (protocol && protocol->send_raw != NULL) {
+			RETVAL = protocol->send_raw(gc, str, strlen(str));
 		} else {
 			RETVAL = 0;
 		}
--- a/libpurple/plugins/perl/common/module.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/common/module.h	Sun Aug 18 01:53:00 2013 +0530
@@ -55,12 +55,12 @@
 #include "imgstore.h"
 #include "network.h"
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "pluginpref.h"
 #include "pounce.h"
 #include "prefs.h"
 #include "presence.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "proxy.h"
 #include "request.h"
 #include "roomlist.h"
@@ -203,7 +203,7 @@
 typedef PurpleNotifyUserInfo *	Purple__NotifyUserInfo;
 typedef PurpleNotifyUserInfoEntry *	Purple__NotifyUserInfoEntry;
 
-/* plugin.h */
+/* plugins.h */
 typedef PurplePlugin *			Purple__Plugin;
 typedef PurplePluginAction *		Purple__Plugin__Action;
 typedef PurplePluginInfo *		Purple__PluginInfo;
@@ -233,10 +233,10 @@
 typedef PurpleProxyInfo *			Purple__ProxyInfo;
 typedef PurpleProxyType			Purple__ProxyType;
 
-/* prpl.h */
+/* protocol.h */
 typedef PurpleBuddyIconSpec *		Purple__Buddy__Icon__Spec;
 typedef PurpleIconScaleRules		Purple__IconScaleRules;
-typedef PurplePluginProtocolInfo *	Purple__PluginProtocolInfo;
+typedef PurpleProtocol *	Purple__PluginProtocolInfo;
 typedef PurpleProtocolOptions		Purple__ProtocolOptions;
 
 /* request.h */
--- a/libpurple/plugins/perl/perl-common.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/perl-common.h	Sun Aug 18 01:53:00 2013 +0530
@@ -20,7 +20,7 @@
 #ifdef _WIN32
 #undef _WIN32DEP_H_
 #endif
-#include "plugin.h"
+#include "plugins.h"
 
 #define is_hvref(o) \
 	((o) && SvROK(o) && SvRV(o) && (SvTYPE(SvRV(o)) == SVt_PVHV))
--- a/libpurple/plugins/perl/perl-handlers.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/perl-handlers.c	Sun Aug 18 01:53:00 2013 +0530
@@ -625,7 +625,7 @@
 PurpleCmdId
 purple_perl_cmd_register(PurplePlugin *plugin, const gchar *command,
                        const gchar *args, PurpleCmdPriority priority,
-                       PurpleCmdFlag flag, const gchar *prpl_id, SV *callback,
+                       PurpleCmdFlag flag, const gchar *protocol_id, SV *callback,
                        const gchar *helpstr, SV *data)
 {
 	PurplePerlCmdHandler *handler;
@@ -633,7 +633,7 @@
 	handler          = g_new0(PurplePerlCmdHandler, 1);
 	handler->plugin  = plugin;
 	handler->cmd     = g_strdup(command);
-	handler->prpl_id = g_strdup(prpl_id);
+	handler->protocol_id = g_strdup(protocol_id);
 
 	if (callback != NULL && callback != &PL_sv_undef)
 		handler->callback = newSVsv(callback);
@@ -647,7 +647,7 @@
 
 	cmd_handlers = g_slist_append(cmd_handlers, handler);
 
-	handler->id = purple_cmd_register(command, args, priority, flag, prpl_id,
+	handler->id = purple_cmd_register(command, args, priority, flag, protocol_id,
 	                                PURPLE_CMD_FUNC(perl_cmd_cb), helpstr,
 	                                handler);
 
@@ -667,7 +667,7 @@
 		SvREFCNT_dec(handler->data);
 
 	g_free(handler->cmd);
-	g_free(handler->prpl_id);
+	g_free(handler->protocol_id);
 	g_free(handler);
 }
 
--- a/libpurple/plugins/perl/perl-handlers.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/perl-handlers.h	Sun Aug 18 01:53:00 2013 +0530
@@ -2,7 +2,7 @@
 #define _PURPLE_PERL_HANDLERS_H_
 
 #include "cmds.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "prefs.h"
 #include "pluginpref.h"
 #ifdef PURPLE_GTKPERL
@@ -15,7 +15,7 @@
 	PurpleCmdId id;
 	SV *callback;
 	SV *data;
-	gchar *prpl_id;
+	gchar *protocol_id;
 	gchar *cmd;
 	PurplePlugin *plugin;
 } PurplePerlCmdHandler;
@@ -73,7 +73,7 @@
 
 PurpleCmdId purple_perl_cmd_register(PurplePlugin *plugin, const gchar *cmd,
                                  const gchar *args, PurpleCmdPriority priority,
-                                 PurpleCmdFlag flag, const gchar *prpl_id,
+                                 PurpleCmdFlag flag, const gchar *protocol_id,
                                  SV *callback, const gchar *helpstr, SV *data);
 void purple_perl_cmd_unregister(PurpleCmdId id);
 void purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin);
--- a/libpurple/plugins/perl/perl.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/perl/perl.c	Sun Aug 18 01:53:00 2013 +0530
@@ -90,7 +90,7 @@
 #endif
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "signals.h"
 #include "version.h"
 
--- a/libpurple/plugins/pluginpref_example.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/pluginpref_example.c	Sun Aug 18 01:53:00 2013 +0530
@@ -29,7 +29,7 @@
 
 #include "internal.h"
 
-#include "plugin.h"
+#include "plugins.h"
 #include "pluginpref.h"
 #include "prefs.h"
 #include "version.h"
--- a/libpurple/plugins/psychic.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/psychic.c	Sun Aug 18 01:53:00 2013 +0530
@@ -10,7 +10,7 @@
 #include "status.h"
 #include "version.h"
 
-#include "plugin.h"
+#include "plugins.h"
 #include "pluginpref.h"
 #include "prefs.h"
 
--- a/libpurple/plugins/signals-test.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/signals-test.c	Sun Aug 18 01:53:00 2013 +0530
@@ -676,7 +676,7 @@
 		xmlnode_set_attrib(iq, "id", id);
 		xmlnode_set_attrib(iq, "type", "result");
 
-		purple_signal_emit(purple_connection_get_prpl(pc),
+		purple_signal_emit(purple_connection_get_protocol_info(pc),
 		                   "jabber-sending-xmlnode", pc, &iq);
 		if (iq != NULL)
 			xmlnode_free(iq);
--- a/libpurple/plugins/simple.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/simple.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1,6 +1,6 @@
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 
 /** Plugin id : type-author-name (to guarantee uniqueness) */
--- a/libpurple/plugins/ssl/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ssl/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -37,6 +37,7 @@
 	-I$(top_builddir)/libpurple \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(PLUGIN_CFLAGS)
 
 ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS)
--- a/libpurple/plugins/ssl/ssl-gnutls.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ssl/ssl-gnutls.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
 #include "internal.h"
 #include "debug.h"
 #include "certificate.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "sslconn.h"
 #include "version.h"
 #include "util.h"
@@ -1277,8 +1277,26 @@
 	NULL
 };
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           SSL_GNUTLS_PLUGIN_ID,
+		"name",         N_("GNUTLS"),
+		"version",      DISPLAY_VERSION,
+		"category",     N_("SSL"),
+		"summary",      N_("Provides SSL support through GNUTLS."),
+		"description",  N_("Provides SSL support through GNUTLS."),
+		"author",       "Christian Hammond <chipx86@gnupdate.org>",
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
+}
+
 static gboolean
-plugin_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	if(!purple_ssl_get_ops()) {
 		purple_ssl_set_ops(&ssl_ops);
@@ -1294,7 +1312,7 @@
 }
 
 static gboolean
-plugin_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if(purple_ssl_get_ops() == &ssl_ops) {
 		purple_ssl_set_ops(NULL);
@@ -1305,46 +1323,4 @@
 	return TRUE;
 }
 
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_STANDARD,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,                       /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	SSL_GNUTLS_PLUGIN_ID,                             /**< id             */
-	N_("GNUTLS"),                                     /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Provides SSL support through GNUTLS."),
-	                                                  /**  description    */
-	N_("Provides SSL support through GNUTLS."),
-	"Christian Hammond <chipx86@gnupdate.org>",
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	plugin_load,                                      /**< load           */
-	plugin_unload,                                    /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	NULL,                                             /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	NULL,                                             /**< actions        */
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(ssl_gnutls, init_plugin, info)
+PURPLE_PLUGIN_INIT(ssl_gnutls, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/ssl/ssl-nss.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ssl/ssl-nss.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
 #include "internal.h"
 #include "debug.h"
 #include "certificate.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "sslconn.h"
 #include "util.h"
 #include "version.h"
@@ -1053,9 +1053,26 @@
 	NULL
 };
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           SSL_NSS_PLUGIN_ID,
+		"name",         N_("NSS"),
+		"version",      DISPLAY_VERSION,
+		"category",     N_("SSL"),
+		"summary",      N_("Provides SSL support through Mozilla NSS."),
+		"description",  N_("Provides SSL support through Mozilla NSS."),
+		"author",       "Christian Hammond <chipx86@gnupdate.org>",
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
+}
 
 static gboolean
-plugin_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	if (!purple_ssl_get_ops()) {
 		purple_ssl_set_ops(&ssl_ops);
@@ -1071,7 +1088,7 @@
 }
 
 static gboolean
-plugin_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if (purple_ssl_get_ops() == &ssl_ops) {
 		purple_ssl_set_ops(NULL);
@@ -1083,46 +1100,4 @@
 	return TRUE;
 }
 
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_STANDARD,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,                       /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	SSL_NSS_PLUGIN_ID,                             /**< id             */
-	N_("NSS"),                                        /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Provides SSL support through Mozilla NSS."),
-	                                                  /**  description    */
-	N_("Provides SSL support through Mozilla NSS."),
-	"Christian Hammond <chipx86@gnupdate.org>",
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	plugin_load,                                      /**< load           */
-	plugin_unload,                                    /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	NULL,                                             /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	NULL,                                             /**< actions        */
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(ssl_nss, init_plugin, info)
+PURPLE_PLUGIN_INIT(ssl_nss, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/ssl/ssl.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/ssl/ssl.c	Sun Aug 18 01:53:00 2013 +0530
@@ -21,33 +21,36 @@
  */
 #include "internal.h"
 #include "debug.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "sslconn.h"
 #include "version.h"
 
-#define SSL_PLUGIN_ID "core-ssl"
+#define SSL_PLUGIN_ID      "core-ssl"
+#define SSL_PLUGIN_DOMAIN  (g_quark_from_static_string(SSL_PLUGIN_ID))
 
 static PurplePlugin *ssl_plugin = NULL;
 
 static gboolean
-probe_ssl_plugins(PurplePlugin *my_plugin)
+probe_ssl_plugins(PurplePlugin *my_plugin, GError **error)
 {
 	PurplePlugin *plugin;
-	GList *l;
+	GList *plugins, *l;
 
 	ssl_plugin = NULL;
 
-	for (l = purple_plugins_get_all(); l != NULL; l = l->next)
+	plugins = purple_plugins_find_all();
+
+	for (l = plugins; l != NULL; l = l->next)
 	{
-		plugin = (PurplePlugin *)l->data;
+		plugin = PURPLE_PLUGIN(l->data);
 
 		if (plugin == my_plugin)
 			continue;
 
-		if (plugin->info != NULL && plugin->info->id != NULL &&
-			strncmp(plugin->info->id, "ssl-", 4) == 0)
+		if (strncmp(purple_plugin_info_get_id(purple_plugin_get_info(plugin)),
+				"ssl-", 4) == 0)
 		{
-			if (purple_plugin_is_loaded(plugin) || purple_plugin_load(plugin))
+			if (purple_plugin_load(plugin, NULL))
 			{
 				ssl_plugin = plugin;
 
@@ -56,22 +59,49 @@
 		}
 	}
 
-	return (ssl_plugin != NULL);
+	g_list_free(plugins);
+
+	if (ssl_plugin == NULL) {
+		g_set_error(error, SSL_PLUGIN_DOMAIN, 0,
+				"Could not load a plugin that implements SSL.");
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           SSL_PLUGIN_ID,
+		"name",         N_("SSL"),
+		"version",      DISPLAY_VERSION,
+		"category",     N_("SSL"),
+		"summary",      N_("Provides a wrapper around SSL support libraries."),
+		"description",  N_("Provides a wrapper around SSL support libraries."),
+		"author",       "Christian Hammond <chipx86@gnupdate.org>",
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL,
+		NULL
+	);
 }
 
 static gboolean
-plugin_load(PurplePlugin *plugin)
+plugin_load(PurplePlugin *plugin, GError **error)
 {
-	return probe_ssl_plugins(plugin);
+	return probe_ssl_plugins(plugin, error);
 }
 
 static gboolean
-plugin_unload(PurplePlugin *plugin)
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	if (ssl_plugin != NULL &&
 		g_list_find(purple_plugins_get_loaded(), ssl_plugin) != NULL)
 	{
-		purple_plugin_unload(ssl_plugin);
+		if (!purple_plugin_unload(ssl_plugin, error))
+			return FALSE;
 	}
 
 	ssl_plugin = NULL;
@@ -79,46 +109,4 @@
 	return TRUE;
 }
 
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_STANDARD,                             /**< type           */
-    NULL,                                             /**< ui_requirement */
-	PURPLE_PLUGIN_FLAG_INVISIBLE,                       /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	SSL_PLUGIN_ID,                                    /**< id             */
-	N_("SSL"),                                        /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Provides a wrapper around SSL support libraries."),
-	                                                  /**  description    */
-	N_("Provides a wrapper around SSL support libraries."),
-	"Christian Hammond <chipx86@gnupdate.org>",
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	plugin_load,                                      /**< load           */
-	plugin_unload,                                    /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	NULL,                                             /**< extra_info     */
-	NULL,
-	NULL,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-}
-
-PURPLE_INIT_PLUGIN(ssl, init_plugin, info)
+PURPLE_PLUGIN_INIT(ssl, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/statenotify.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/statenotify.c	Sun Aug 18 01:53:00 2013 +0530
@@ -6,7 +6,7 @@
 #include "signals.h"
 #include "version.h"
 
-#include "plugin.h"
+#include "plugins.h"
 #include "pluginpref.h"
 #include "prefs.h"
 
--- a/libpurple/plugins/tcl/tcl.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/tcl/tcl.c	Sun Aug 18 01:53:00 2013 +0530
@@ -38,7 +38,7 @@
 
 #include "internal.h"
 #include "connection.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "signals.h"
 #include "debug.h"
 #include "util.h"
--- a/libpurple/plugins/tcl/tcl_cmd.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/tcl/tcl_cmd.c	Sun Aug 18 01:53:00 2013 +0530
@@ -71,7 +71,7 @@
 
 	if ((id = purple_cmd_register(Tcl_GetString(handler->cmd),
 				    handler->args, handler->priority,
-				    handler->flags, handler->prpl_id,
+				    handler->flags, handler->protocol_id,
 				    PURPLE_CMD_FUNC(tcl_cmd_callback),
 				    handler->helpstr, (void *)handler)) == 0)
 		return 0;
--- a/libpurple/plugins/tcl/tcl_cmds.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/tcl/tcl_cmds.c	Sun Aug 18 01:53:00 2013 +0530
@@ -631,7 +631,7 @@
 		break;
 	case CMD_CMD_REGISTER:
 		if (objc != 9) {
-			Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags prpl_id proc helpstr");
+			Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags protocol_id proc helpstr");
 			return TCL_ERROR;
 		}
 		handler = g_new0(struct tcl_cmd_handler, 1);
@@ -648,7 +648,7 @@
 			g_free(handler);
 			return error;
 		}
-		handler->prpl_id = Tcl_GetString(objv[6]);
+		handler->protocol_id = Tcl_GetString(objv[6]);
 		handler->proc = objv[7];
 		handler->helpstr = Tcl_GetString(objv[8]);
 		handler->interp = interp;
--- a/libpurple/plugins/tcl/tcl_purple.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/plugins/tcl/tcl_purple.h	Sun Aug 18 01:53:00 2013 +0530
@@ -27,7 +27,7 @@
 
 #include "internal.h"
 #include "cmds.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "stringref.h"
 
 struct tcl_signal_handler {
@@ -55,7 +55,7 @@
 	const char *args;
 	int priority;
 	int flags;
-	const char *prpl_id;
+	const char *protocol_id;
 	Tcl_Obj *proc;
 	const char *helpstr;
 
--- a/libpurple/presence.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/presence.c	Sun Aug 18 01:53:00 2013 +0530
@@ -553,8 +553,7 @@
 {
 	PurpleAccount *account;
 	PurpleConnection *gc = NULL;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	gboolean idle = purple_presence_is_idle(presence);
 	time_t idle_time = purple_presence_get_idle_time(presence);
 	time_t current_time = time(NULL);
@@ -585,14 +584,11 @@
 
 	gc = purple_account_get_connection(account);
 
-	if(gc)
-		prpl = purple_connection_get_prpl(gc);
+	if(PURPLE_CONNECTION_IS_CONNECTED(gc))
+		protocol = purple_connection_get_protocol_info(gc);
 
-	if(PURPLE_CONNECTION_IS_CONNECTED(gc) && prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info && prpl_info->set_idle)
-		prpl_info->set_idle(gc, (idle ? (current_time - idle_time) : 0));
+	if (protocol && protocol->set_idle)
+		protocol->set_idle(gc, (idle ? (current_time - idle_time) : 0));
 }
 
 PurpleAccount *
@@ -734,7 +730,7 @@
 	G_OBJECT_CLASS(presence_class)->constructed(object);
 
 	PURPLE_PRESENCE_GET_PRIVATE(presence)->statuses =
-			purple_prpl_get_statuses(priv->account, presence);
+			purple_protocol_get_statuses(priv->account, presence);
 }
 
 /* Class initializer function */
@@ -931,7 +927,7 @@
 
 	account = purple_buddy_get_account(priv->buddy);
 	PURPLE_PRESENCE_GET_PRIVATE(presence)->statuses =
-			purple_prpl_get_statuses(account, presence);
+			purple_protocol_get_statuses(account, presence);
 }
 
 /* Class initializer function */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocol.c	Sun Aug 18 01:53:00 2013 +0530
@@ -0,0 +1,756 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ *
+ */
+#include "internal.h"
+#include "accountopt.h"
+#include "conversation.h"
+#include "debug.h"
+#include "network.h"
+#include "notify.h"
+#include "protocol.h"
+#include "request.h"
+#include "util.h"
+
+static GHashTable *protocols = NULL;
+
+/**************************************************************************/
+/** @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)
+{
+	PurpleAttentionType *attn = g_new0(PurpleAttentionType, 1);
+
+	purple_attention_type_set_name(attn, name);
+	purple_attention_type_set_incoming_desc(attn, inc_desc);
+	purple_attention_type_set_outgoing_desc(attn, out_desc);
+	purple_attention_type_set_unlocalized_name(attn, ulname);
+
+	return attn;
+}
+
+
+void
+purple_attention_type_set_name(PurpleAttentionType *type, const char *name)
+{
+	g_return_if_fail(type != NULL);
+
+	type->name = name;
+}
+
+void
+purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc)
+{
+	g_return_if_fail(type != NULL);
+
+	type->incoming_description = desc;
+}
+
+void
+purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc)
+{
+	g_return_if_fail(type != NULL);
+
+	type->outgoing_description = desc;
+}
+
+void
+purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name)
+{
+	g_return_if_fail(type != NULL);
+
+	type->icon_name = name;
+}
+
+void
+purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname)
+{
+	g_return_if_fail(type != NULL);
+
+	type->unlocalized_name = ulname;
+}
+
+const char *
+purple_attention_type_get_name(const PurpleAttentionType *type)
+{
+	g_return_val_if_fail(type != NULL, NULL);
+
+	return type->name;
+}
+
+const char *
+purple_attention_type_get_incoming_desc(const PurpleAttentionType *type)
+{
+	g_return_val_if_fail(type != NULL, NULL);
+
+	return type->incoming_description;
+}
+
+const char *
+purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type)
+{
+	g_return_val_if_fail(type != NULL, NULL);
+
+	return type->outgoing_description;
+}
+
+const char *
+purple_attention_type_get_icon_name(const PurpleAttentionType *type)
+{
+	g_return_val_if_fail(type != NULL, NULL);
+
+	if(type->icon_name == NULL || *(type->icon_name) == '\0')
+		return NULL;
+
+	return type->icon_name;
+}
+
+const char *
+purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type)
+{
+	g_return_val_if_fail(type != NULL, NULL);
+
+	return type->unlocalized_name;
+}
+
+/**************************************************************************/
+/** @name Protocol Plugin API  */
+/**************************************************************************/
+void
+purple_protocol_got_account_idle(PurpleAccount *account, gboolean idle,
+						   time_t idle_time)
+{
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(purple_account_is_connected(account));
+
+	purple_presence_set_idle(purple_account_get_presence(account),
+						   idle, idle_time);
+}
+
+void
+purple_protocol_got_account_login_time(PurpleAccount *account, time_t login_time)
+{
+	PurplePresence *presence;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(purple_account_is_connected(account));
+
+	if (login_time == 0)
+		login_time = time(NULL);
+
+	presence = purple_account_get_presence(account);
+
+	purple_presence_set_login_time(presence, login_time);
+}
+
+void
+purple_protocol_got_account_status(PurpleAccount *account, const char *status_id, ...)
+{
+	PurplePresence *presence;
+	PurpleStatus *status;
+	va_list args;
+
+	g_return_if_fail(account   != NULL);
+	g_return_if_fail(status_id != NULL);
+	g_return_if_fail(purple_account_is_connected(account));
+
+	presence = purple_account_get_presence(account);
+	status   = purple_presence_get_status(presence, status_id);
+
+	g_return_if_fail(status != NULL);
+
+	va_start(args, status_id);
+	purple_status_set_active_with_attrs(status, TRUE, args);
+	va_end(args);
+}
+
+void
+purple_protocol_got_account_actions(PurpleAccount *account)
+{
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(purple_account_is_connected(account));
+
+	purple_signal_emit(purple_accounts_get_handle(), "account-actions-changed",
+	                   account);
+}
+
+void
+purple_protocol_got_user_idle(PurpleAccount *account, const char *name,
+		gboolean idle, time_t idle_time)
+{
+	PurplePresence *presence;
+	GSList *list;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(name    != NULL);
+	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
+
+	if ((list = purple_blist_find_buddies(account, name)) == NULL)
+		return;
+
+	while (list) {
+		presence = purple_buddy_get_presence(list->data);
+		list = g_slist_delete_link(list, list);
+		purple_presence_set_idle(presence, idle, idle_time);
+	}
+}
+
+void
+purple_protocol_got_user_login_time(PurpleAccount *account, const char *name,
+		time_t login_time)
+{
+	GSList *list;
+	PurplePresence *presence;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(name    != NULL);
+
+	if ((list = purple_blist_find_buddies(account, name)) == NULL)
+		return;
+
+	if (login_time == 0)
+		login_time = time(NULL);
+
+	while (list) {
+		PurpleBuddy *buddy = list->data;
+		presence = purple_buddy_get_presence(buddy);
+		list = g_slist_delete_link(list, list);
+
+		if (purple_presence_get_login_time(presence) != login_time)
+		{
+			purple_presence_set_login_time(presence, login_time);
+
+			purple_signal_emit(purple_blist_get_handle(), "buddy-got-login-time", buddy);
+		}
+	}
+}
+
+void
+purple_protocol_got_user_status(PurpleAccount *account, const char *name,
+		const char *status_id, ...)
+{
+	GSList *list, *l;
+	PurpleBuddy *buddy;
+	PurplePresence *presence;
+	PurpleStatus *status;
+	PurpleStatus *old_status;
+	va_list args;
+
+	g_return_if_fail(account   != NULL);
+	g_return_if_fail(name      != NULL);
+	g_return_if_fail(status_id != NULL);
+	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
+
+	if((list = purple_blist_find_buddies(account, name)) == NULL)
+		return;
+
+	for(l = list; l != NULL; l = l->next) {
+		buddy = l->data;
+
+		presence = purple_buddy_get_presence(buddy);
+		status   = purple_presence_get_status(presence, status_id);
+
+		if(NULL == status)
+			/*
+			 * TODO: This should never happen, right?  We should call
+			 *       g_warning() or something.
+			 */
+			continue;
+
+		old_status = purple_presence_get_active_status(presence);
+
+		va_start(args, status_id);
+		purple_status_set_active_with_attrs(status, TRUE, args);
+		va_end(args);
+
+		purple_buddy_update_status(buddy, old_status);
+	}
+
+	g_slist_free(list);
+
+	/* The buddy is no longer online, they are therefore by definition not
+	 * still typing to us. */
+	if (!purple_status_is_online(status)) {
+		serv_got_typing_stopped(purple_account_get_connection(account), name);
+		purple_protocol_got_media_caps(account, name);
+	}
+}
+
+void purple_protocol_got_user_status_deactive(PurpleAccount *account, const char *name,
+					const char *status_id)
+{
+	GSList *list, *l;
+	PurpleBuddy *buddy;
+	PurplePresence *presence;
+	PurpleStatus *status;
+
+	g_return_if_fail(account   != NULL);
+	g_return_if_fail(name      != NULL);
+	g_return_if_fail(status_id != NULL);
+	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
+
+	if((list = purple_blist_find_buddies(account, name)) == NULL)
+		return;
+
+	for(l = list; l != NULL; l = l->next) {
+		buddy = l->data;
+
+		presence = purple_buddy_get_presence(buddy);
+		status   = purple_presence_get_status(presence, status_id);
+
+		if(NULL == status)
+			continue;
+
+		if (purple_status_is_active(status)) {
+			purple_status_set_active(status, FALSE);
+			purple_buddy_update_status(buddy, status);
+		}
+	}
+
+	g_slist_free(list);
+}
+
+static void
+do_protocol_change_account_status(PurpleAccount *account,
+								PurpleStatus *old_status, PurpleStatus *new_status)
+{
+	PurpleProtocol *protocol;
+
+	if (purple_status_is_online(new_status) &&
+		purple_account_is_disconnected(account) &&
+		purple_network_is_available())
+	{
+		purple_account_connect(account);
+		return;
+	}
+
+	if (!purple_status_is_online(new_status))
+	{
+		if (!purple_account_is_disconnected(account))
+			purple_account_disconnect(account);
+		/* Clear out the unsaved password if we switch to offline status */
+		if (!purple_account_get_remember_password(account))
+			purple_account_set_password(account, NULL, NULL, NULL);
+
+		return;
+	}
+
+	if (purple_account_is_connecting(account))
+		/*
+		 * We don't need to call the set_status PRPL function because
+		 * the PRPL will take care of setting its status during the
+		 * connection process.
+		 */
+		return;
+
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+
+	if (protocol == NULL)
+		return;
+
+	if (!purple_account_is_disconnected(account) && protocol->set_status != NULL)
+	{
+		protocol->set_status(account, new_status);
+	}
+}
+
+void
+purple_protocol_change_account_status(PurpleAccount *account,
+								PurpleStatus *old_status, PurpleStatus *new_status)
+{
+	g_return_if_fail(account    != NULL);
+	g_return_if_fail(new_status != NULL);
+	g_return_if_fail(!purple_status_is_exclusive(new_status) || old_status != NULL);
+
+	do_protocol_change_account_status(account, old_status, new_status);
+
+	purple_signal_emit(purple_accounts_get_handle(), "account-status-changed",
+					account, old_status, new_status);
+}
+
+GList *
+purple_protocol_get_statuses(PurpleAccount *account, PurplePresence *presence)
+{
+	GList *statuses = NULL;
+	GList *l;
+	PurpleStatus *status;
+
+	g_return_val_if_fail(account  != NULL, NULL);
+	g_return_val_if_fail(presence != NULL, NULL);
+
+	for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
+	{
+		status = purple_status_new((PurpleStatusType *)l->data, presence);
+		statuses = g_list_prepend(statuses, status);
+	}
+
+	statuses = g_list_reverse(statuses);
+
+	return statuses;
+}
+
+static void
+purple_protocol_attention(PurpleConversation *conv, const char *who,
+	guint type, PurpleMessageFlags flags, time_t mtime)
+{
+	PurpleAccount *account = purple_conversation_get_account(conv);
+	purple_signal_emit(purple_conversations_get_handle(),
+		flags == PURPLE_MESSAGE_SEND ? "sent-attention" : "got-attention",
+		account, who, conv, type);
+}
+
+void
+purple_protocol_send_attention(PurpleConnection *gc, const char *who, guint type_code)
+{
+	PurpleAttentionType *attn;
+	PurpleMessageFlags flags;
+	PurpleProtocol *protocol;
+	PurpleIMConversation *im;
+	gboolean (*send_attention)(PurpleConnection *, const char *, guint);
+	PurpleBuddy *buddy;
+	const char *alias;
+	gchar *description;
+	time_t mtime;
+
+	g_return_if_fail(gc != NULL);
+	g_return_if_fail(who != NULL);
+
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_connection_get_account(gc)));
+	send_attention = protocol->send_attention;
+	g_return_if_fail(send_attention != NULL);
+
+	mtime = time(NULL);
+
+	attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code);
+
+	if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL)
+		alias = purple_buddy_get_contact_alias(buddy);
+	else
+		alias = who;
+
+	if (attn && purple_attention_type_get_outgoing_desc(attn)) {
+		description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias);
+	} else {
+		description = g_strdup_printf(_("Requesting %s's attention..."), alias);
+	}
+
+	flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM;
+
+	purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n",
+			description, who);
+
+	if (!send_attention(gc, who, type_code))
+		return;
+
+	im = purple_im_conversation_new(purple_connection_get_account(gc), who);
+	purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, description, flags, mtime);
+	purple_protocol_attention(PURPLE_CONVERSATION(im), who, type_code, PURPLE_MESSAGE_SEND, time(NULL));
+
+	g_free(description);
+}
+
+static void
+got_attention(PurpleConnection *gc, int id, const char *who, guint type_code)
+{
+	PurpleMessageFlags flags;
+	PurpleAttentionType *attn;
+	PurpleBuddy *buddy;
+	const char *alias;
+	gchar *description;
+	time_t mtime;
+
+	mtime = time(NULL);
+
+	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;
+
+	/* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display
+	 * it next to the attention command. And if it is null, display a generic icon. */
+
+	if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL)
+		alias = purple_buddy_get_contact_alias(buddy);
+	else
+		alias = who;
+
+	if (attn && purple_attention_type_get_incoming_desc(attn)) {
+		description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias);
+	} else {
+		description = g_strdup_printf(_("%s has requested your attention!"), alias);
+	}
+
+	purple_debug_info("server", "got_attention: got '%s' from %s\n",
+			description, who);
+
+	if (id == -1)
+		serv_got_im(gc, who, description, flags, mtime);
+	else
+		serv_got_chat_in(gc, id, who, flags, description, mtime);
+
+	/* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */
+
+	g_free(description);
+}
+
+void
+purple_protocol_got_attention(PurpleConnection *gc, const char *who, guint type_code)
+{
+	PurpleConversation *conv = NULL;
+	PurpleAccount *account = purple_connection_get_account(gc);
+
+	got_attention(gc, -1, who, type_code);
+	conv =
+		purple_conversations_find_with_account(who, account);
+	if (conv)
+		purple_protocol_attention(conv, who, type_code, PURPLE_MESSAGE_RECV,
+			time(NULL));
+}
+
+void
+purple_protocol_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code)
+{
+	got_attention(gc, id, who, type_code);
+}
+
+gboolean
+purple_protocol_initiate_media(PurpleAccount *account,
+			   const char *who,
+			   PurpleMediaSessionType type)
+{
+#ifdef USE_VV
+	PurpleConnection *gc = NULL;
+	PurpleProtocol *protocol = NULL;
+
+	if (account)
+		gc = purple_account_get_connection(account);
+	if (gc)
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, initiate_media)) {
+		/* should check that the protocol supports this media type here? */
+		return protocol->initiate_media(account, who, type);
+	} else
+#endif
+	return FALSE;
+}
+
+PurpleMediaCaps
+purple_protocol_get_media_caps(PurpleAccount *account, const char *who)
+{
+#ifdef USE_VV
+	PurpleConnection *gc = NULL;
+	PurpleProtocol *protocol = NULL;
+
+	if (account)
+		gc = purple_account_get_connection(account);
+	if (gc)
+		protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol,
+			get_media_caps)) {
+		return protocol->get_media_caps(account, who);
+	}
+#endif
+	return PURPLE_MEDIA_CAPS_NONE;
+}
+
+void
+purple_protocol_got_media_caps(PurpleAccount *account, const char *name)
+{
+#ifdef USE_VV
+	GSList *list;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(name    != NULL);
+
+	if ((list = purple_blist_find_buddies(account, name)) == NULL)
+		return;
+
+	while (list) {
+		PurpleBuddy *buddy = list->data;
+		PurpleMediaCaps oldcaps = purple_buddy_get_media_caps(buddy);
+		PurpleMediaCaps newcaps = 0;
+		const gchar *bname = purple_buddy_get_name(buddy);
+		list = g_slist_delete_link(list, list);
+
+
+		newcaps = purple_protocol_get_media_caps(account, bname);
+		purple_buddy_set_media_caps(buddy, newcaps);
+
+		if (oldcaps == newcaps)
+			continue;
+
+		purple_signal_emit(purple_blist_get_handle(),
+				"buddy-caps-changed", buddy,
+				newcaps, oldcaps);
+	}
+#endif
+}
+
+PurpleProtocolAction *
+purple_protocol_action_new(const char* label,
+		PurpleProtocolActionCallback callback)
+{
+	PurpleProtocolAction *action;
+
+	g_return_val_if_fail(label != NULL && callback != NULL, NULL);
+
+	action = g_new0(PurpleProtocolAction, 1);
+
+	action->label    = g_strdup(label);
+	action->callback = callback;
+
+	return action;
+}
+
+void
+purple_protocol_action_free(PurpleProtocolAction *action)
+{
+	g_return_if_fail(action != NULL);
+
+	g_free(action->label);
+	g_free(action);
+}
+
+/**************************************************************************
+ * Protocols API
+ **************************************************************************/
+static void
+purple_protocol_destroy(PurpleProtocol *protocol)
+{
+	GList *accounts, *l;
+
+	accounts = purple_accounts_get_all_active();
+	for (l = accounts; l != NULL; l = l->next) {
+		PurpleAccount *account = PURPLE_ACCOUNT(l->data);
+		if (purple_account_is_disconnected(account))
+			continue;
+
+		if (purple_strequal(protocol->id, purple_account_get_protocol_id(account)))
+			purple_account_disconnect(account);
+	}
+
+	g_list_free(accounts);
+
+	while (protocol->user_splits) {
+		PurpleAccountUserSplit *split = protocol->user_splits->data;
+		purple_account_user_split_destroy(split);
+		protocol->user_splits = g_list_delete_link(protocol->user_splits,
+				protocol->user_splits);
+	}
+
+	while (protocol->protocol_options) {
+		PurpleAccountOption *option = protocol->protocol_options->data;
+		purple_account_option_destroy(option);
+		protocol->protocol_options =
+				g_list_delete_link(protocol->protocol_options,
+				protocol->protocol_options);
+	}
+
+	purple_request_close_with_handle(protocol);
+	purple_notify_close_with_handle(protocol);
+
+	purple_signals_disconnect_by_handle(protocol);
+	purple_signals_unregister_by_instance(protocol);
+
+	purple_prefs_disconnect_by_handle(protocol);
+}
+
+PurpleProtocol *
+purple_find_protocol_info(const char *id)
+{
+	return g_hash_table_lookup(protocols, id);
+}
+
+gboolean
+purple_protocols_add(PurpleProtocol *protocol)
+{
+	if (purple_find_protocol_info(protocol->id))
+		return FALSE;
+
+	g_hash_table_insert(protocols, g_strdup(protocol->id), protocol);
+	return TRUE;
+}
+
+gboolean purple_protocols_remove(PurpleProtocol *protocol)
+{
+	if (purple_find_protocol_info(protocol->id) == NULL)
+		return FALSE;
+
+	g_hash_table_remove(protocols, protocol->id);
+	purple_protocol_destroy(protocol);
+
+	return TRUE;
+}
+
+GList *
+purple_protocols_get_all(void)
+{
+	GList *ret = NULL;
+	PurpleProtocol *protocol;
+	GHashTableIter iter;
+
+	g_hash_table_iter_init(&iter, protocols);
+	while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&protocol))
+		ret = g_list_append(ret, protocol);
+
+	return ret;
+}
+
+/**************************************************************************
+ * Protocols Subsystem API
+ **************************************************************************/
+void
+purple_protocols_init(void)
+{
+	protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+			(GDestroyNotify)purple_protocol_destroy);
+}
+
+void *
+purple_protocols_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
+}
+
+void
+purple_protocols_uninit(void) 
+{
+	g_hash_table_destroy(protocols);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocol.h	Sun Aug 18 01:53:00 2013 +0530
@@ -0,0 +1,1055 @@
+/**
+ * @file protocol.h Protocol Plugin functions
+ * @ingroup core
+ */
+
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+/* this file should be all that prpls need to include. therefore, by including
+ * this file, they should get glib, proxy, purple_connection, prpl, etc. */
+
+#ifndef _PURPLE_PROTOCOL_H_
+#define _PURPLE_PROTOCOL_H_
+
+typedef struct _PurpleProtocol PurpleProtocol;
+
+typedef struct _PurpleProtocolAction PurpleProtocolAction;
+
+typedef void (*PurpleProtocolActionCallback)(PurpleProtocolAction *);
+
+/** Represents "nudges" and "buzzes" that you may send to a buddy to attract
+ *  their attention (or vice-versa).
+ */
+typedef struct _PurpleAttentionType PurpleAttentionType;
+
+/**************************************************************************/
+/** @name Basic Protocol Information                                      */
+/**************************************************************************/
+
+typedef enum {
+	PURPLE_ICON_SCALE_DISPLAY = 0x01,		/**< We scale the icon when we display it */
+	PURPLE_ICON_SCALE_SEND = 0x02			/**< We scale the icon before we send it to the server */
+} PurpleIconScaleRules;
+
+
+/**
+ * A description of a Buddy Icon specification.  This tells Purple what kind of image file
+ * it should give this prpl, and what kind of image file it should expect back.
+ * Dimensions less than 1 should be ignored and the image not scaled.
+ */
+typedef struct _PurpleBuddyIconSpec PurpleBuddyIconSpec;
+
+/**
+ * A description of a file transfer thumbnail specification.
+ * This tells the UI if and what image formats the prpl support for file
+ * transfer thumbnails.
+ */
+typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec;
+
+/**
+ * This \#define exists just to make it easier to fill out the buddy icon
+ * field in the prpl info struct for protocols that couldn't care less.
+ */
+#define NO_BUDDY_ICONS {NULL, 0, 0, 0, 0, 0, 0}
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "buddylist.h"
+#include "conversations.h"
+#include "ft.h"
+#include "imgstore.h"
+#include "media.h"
+#include "notify.h"
+#include "proxy.h"
+#include "roomlist.h"
+#include "status.h"
+#include "whiteboard.h"
+
+
+/** @copydoc PurpleBuddyIconSpec */
+struct _PurpleBuddyIconSpec {
+	/** This is a comma-delimited list of image formats or @c NULL if icons
+	 *  are not supported.  Neither the core nor the prpl will actually
+	 *  check to see if the data it's given matches this; it's entirely up
+	 *  to the UI to do what it wants
+	 */
+	char *format;
+
+	int min_width;                     /**< Minimum width of this icon  */
+	int min_height;                    /**< Minimum height of this icon */
+	int max_width;                     /**< Maximum width of this icon  */
+	int max_height;                    /**< Maximum height of this icon */
+	size_t max_filesize;               /**< Maximum size in bytes */
+	PurpleIconScaleRules scale_rules;  /**< How to stretch this icon */
+};
+
+/** Represents an entry containing information that must be supplied by the
+ *  user when joining a chat.
+ */
+struct proto_chat_entry {
+	const char *label;       /**< User-friendly name of the entry */
+	const char *identifier;  /**< Used by the PRPL to identify the option */
+	gboolean required;       /**< True if it's required */
+	gboolean is_int;         /**< True if the entry expects an integer */
+	int min;                 /**< Minimum value in case of integer */
+	int max;                 /**< Maximum value in case of integer */
+	gboolean secret;         /**< True if the entry is secret (password) */
+};
+
+/**
+ * Protocol options
+ *
+ * These should all be stuff that some plugins can do and others can't.
+ */
+typedef enum
+{
+	/**
+	 * User names are unique to a chat and are not shared between rooms.
+	 *
+	 * XMPP lets you choose what name you want in chats, so it shouldn't
+	 * be pulling the aliases from the buddy list for the chat list;
+	 * it gets annoying.
+	 */
+	OPT_PROTO_UNIQUE_CHATNAME = 0x00000004,
+
+	/**
+	 * Chat rooms have topics.
+	 *
+	 * IRC and XMPP support this.
+	 */
+	OPT_PROTO_CHAT_TOPIC = 0x00000008,
+
+	/**
+	 * Don't require passwords for sign-in.
+	 *
+	 * Zephyr doesn't require passwords, so there's no
+	 * need for a password prompt.
+	 */
+	OPT_PROTO_NO_PASSWORD = 0x00000010,
+
+	/**
+	 * Notify on new mail.
+	 *
+	 * MSN and Yahoo notify you when you have new mail.
+	 */
+	OPT_PROTO_MAIL_CHECK = 0x00000020,
+
+	/**
+	 * Images in IMs.
+	 *
+	 * Oscar lets you send images in direct IMs.
+	 */
+	OPT_PROTO_IM_IMAGE = 0x00000040,
+
+	/**
+	 * Allow passwords to be optional.
+	 *
+	 * Passwords in IRC are optional, and are needed for certain
+	 * functionality.
+	 */
+	OPT_PROTO_PASSWORD_OPTIONAL = 0x00000080,
+
+	/**
+	 * Allows font size to be specified in sane point size
+	 *
+	 * Probably just XMPP and Y!M
+	 */
+	OPT_PROTO_USE_POINTSIZE = 0x00000100,
+
+	/**
+	 * Set the Register button active even when the username has not
+	 * been specified.
+	 *
+	 * Gadu-Gadu doesn't need a username to register new account (because
+	 * usernames are assigned by the server).
+	 */
+	OPT_PROTO_REGISTER_NOSCREENNAME = 0x00000200,
+
+	/**
+	 * Indicates that slash commands are native to this protocol.
+	 * Used as a hint that unknown commands should not be sent as messages.
+	 */
+	OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400,
+
+	/**
+	 * Indicates that this protocol supports sending a user-supplied message
+	 * along with an invitation.
+	 */
+	OPT_PROTO_INVITE_MESSAGE = 0x00000800,
+
+	/**
+	 * Indicates that this protocol supports sending a user-supplied message
+	 * along with an authorization acceptance.
+	 */
+	OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE = 0x00001000,
+
+	/**
+	 * Indicates that this protocol supports sending a user-supplied message
+	 * along with an authorization denial.
+	 */
+	OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE = 0x00002000
+
+} PurpleProtocolOptions;
+
+/**
+ * Represents an action that the protocol can perform. This shows up in the
+ * Accounts menu, under a submenu with the name of the account.
+ */
+struct _PurpleProtocolAction {
+	char *label;
+	PurpleProtocolActionCallback callback;
+	PurpleConnection *connection;
+	gpointer user_data;
+};
+
+/**
+ * A protocol plugin information structure.
+ *
+ * Every protocol plugin initializes this structure. It is the gateway
+ * between purple and the protocol plugin.  Many of these callbacks can be
+ * NULL.  If a callback must be implemented, it has a comment indicating so.
+ */
+struct _PurpleProtocol
+{
+	const char *id;
+	const char *name;
+
+	/**
+	 * The size of the PurpleProtocol. This should always be sizeof(PurpleProtocol).
+	 * 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 */
+	GList *protocol_options; /**< A GList of PurpleAccountOption    */
+
+	PurpleBuddyIconSpec icon_spec; /**< The icon spec. */
+
+	/**
+	 * Callback that returns the actions the protocol can perform
+	 */
+	GList *(*get_actions)(PurpleConnection *);
+
+	/**
+	 * Returns the base icon name for the given buddy and account.
+	 * If buddy is NULL and the account is non-NULL, it will return the
+	 * name to use for the account's icon. If both are NULL, it will
+	 * return the name to use for the protocol's icon.
+	 *
+	 * This must be implemented.
+	 */
+	const char *(*list_icon)(PurpleAccount *account, PurpleBuddy *buddy);
+
+	/**
+	 * Fills the four char**'s with string identifiers for "emblems"
+	 * that the UI will interpret and display as relevant
+	 */
+	const char *(*list_emblem)(PurpleBuddy *buddy);
+
+	/**
+	 * Gets a short string representing this buddy's status.  This will
+	 * be shown on the buddy list.
+	 */
+	char *(*status_text)(PurpleBuddy *buddy);
+
+	/**
+	 * Allows the prpl to add text to a buddy's tooltip.
+	 */
+	void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full);
+
+	/**
+	 * Returns a list of #PurpleStatusType which exist for this account;
+	 * this must be implemented, and must add at least the offline and
+	 * online states.
+	 */
+	GList *(*status_types)(PurpleAccount *account);
+
+	/**
+	 * Returns a list of #PurpleMenuAction structs, which represent extra
+	 * actions to be shown in (for example) the right-click menu for @a
+	 * node.
+	 */
+	GList *(*blist_node_menu)(PurpleBlistNode *node);
+
+	/**
+	 * Returns a list of #proto_chat_entry structs, which represent
+	 * information required by the PRPL to join a chat. libpurple will
+	 * call join_chat along with the information filled by the user.
+	 *
+	 * @return A list of #proto_chat_entry structs
+	 */
+	GList *(*chat_info)(PurpleConnection *);
+
+	/**
+	 * Returns a hashtable which maps #proto_chat_entry struct identifiers
+	 * to default options as strings based on chat_name. The resulting
+	 * hashtable should be created with g_hash_table_new_full(g_str_hash,
+	 * g_str_equal, NULL, g_free);. Use #get_chat_name if you instead need
+	 * to extract a chat name from a hashtable.
+	 *
+	 * @param chat_name The chat name to be turned into components
+	 * @return Hashtable containing the information extracted from chat_name
+	 */
+	GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name);
+
+	/* All the server-related functions */
+
+	/** This must be implemented. */
+	void (*login)(PurpleAccount *);
+
+	/** This must be implemented. */
+	void (*close)(PurpleConnection *);
+
+	/**
+	 * This PRPL function should return a positive value on success.
+	 * If the message is too big to be sent, return -E2BIG.  If
+	 * the account is not connected, return -ENOTCONN.  If the
+	 * PRPL is unable to send the message for another reason, return
+	 * some other negative value.  You can use one of the valid
+	 * errno values, or just big something.  If the message should
+	 * not be echoed to the conversation window, return 0.
+	 */
+	int  (*send_im)(PurpleConnection *, const char *who,
+					const char *message,
+					PurpleMessageFlags flags);
+
+	void (*set_info)(PurpleConnection *, const char *info);
+
+	/**
+	 * @return If this protocol requires the PURPLE_IM_TYPING message to
+	 *         be sent repeatedly to signify that the user is still
+	 *         typing, then the PRPL should return the number of
+	 *         seconds to wait before sending a subsequent notification.
+	 *         Otherwise the PRPL should return 0.
+	 */
+	unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleIMTypingState state);
+
+	/**
+	 * Should arrange for purple_notify_userinfo() to be called with
+	 * @a who's user info.
+	 */
+	void (*get_info)(PurpleConnection *, const char *who);
+	void (*set_status)(PurpleAccount *account, PurpleStatus *status);
+
+	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.
+	 *
+	 * 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.
+	 */
+	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);
+	void (*add_deny)(PurpleConnection *, const char *name);
+	void (*rem_permit)(PurpleConnection *, const char *name);
+	void (*rem_deny)(PurpleConnection *, const char *name);
+	void (*set_permit_deny)(PurpleConnection *);
+
+	/**
+	 * Called when the user requests joining a chat. Should arrange for
+	 * #serv_got_joined_chat to be called.
+	 *
+	 * @param components A hashtable containing information required to
+	 *                   join the chat as described by the entries returned
+	 *                   by #chat_info. It may also be called when accepting
+	 *                   an invitation, in which case this matches the
+	 *                   data parameter passed to #serv_got_chat_invite.
+	 */
+	void (*join_chat)(PurpleConnection *, GHashTable *components);
+
+	/**
+	 * Called when the user refuses a chat invitation.
+	 *
+	 * @param components A hashtable containing information required to
+	 *                   join the chat as passed to #serv_got_chat_invite.
+	 */
+	void (*reject_chat)(PurpleConnection *, GHashTable *components);
+
+	/**
+	 * Returns a chat name based on the information in components. Use
+	 * #chat_info_defaults if you instead need to generate a hashtable
+	 * from a chat name.
+	 *
+	 * @param components A hashtable containing information about the chat.
+	 */
+	char *(*get_chat_name)(GHashTable *components);
+
+	/**
+	 * Invite a user to join a chat.
+	 *
+	 * @param id      The id of the chat to invite the user to.
+	 * @param message A message displayed to the user when the invitation
+	 *                is received.
+	 * @param who     The name of the user to send the invation to.
+	 */
+	void (*chat_invite)(PurpleConnection *, int id,
+						const char *message, const char *who);
+	/**
+	 * Called when the user requests leaving a chat.
+	 *
+	 * @param id The id of the chat to leave
+	 */
+	void (*chat_leave)(PurpleConnection *, int id);
+
+	/**
+	 * Send a whisper to a user in a chat.
+	 *
+	 * @param id      The id of the chat.
+	 * @param who     The name of the user to send the whisper to.
+	 * @param message The message of the whisper.
+	 */
+	void (*chat_whisper)(PurpleConnection *, int id,
+						 const char *who, const char *message);
+
+	/**
+	 * Send a message to a chat.
+	 * This PRPL function should return a positive value on success.
+	 * If the message is too big to be sent, return -E2BIG.  If
+	 * the account is not connected, return -ENOTCONN.  If the
+	 * PRPL is unable to send the message for another reason, return
+	 * some other negative value.  You can use one of the valid
+	 * errno values, or just big something.
+	 *
+	 * @param id      The id of the chat to send the message to.
+	 * @param message The message to send to the chat.
+	 * @param flags   A bitwise OR of #PurpleMessageFlags representing
+	 *                message flags.
+	 * @return 	  A positive number or 0 in case of success,
+	 *                a negative error number in case of failure.
+	 */
+	int  (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags);
+
+	/** If implemented, this will be called regularly for this prpl's
+	 *  active connections.  You'd want to do this if you need to repeatedly
+	 *  send some kind of keepalive packet to the server to avoid being
+	 *  disconnected.  ("Regularly" is defined by
+	 *  <code>KEEPALIVE_INTERVAL</code> in <tt>libpurple/connection.c</tt>.)
+	 */
+	void (*keepalive)(PurpleConnection *);
+
+	/** new user registration */
+	void (*register_user)(PurpleAccount *);
+
+	/**
+	 * @deprecated Use #PurpleProtocol.get_info instead.
+	 */
+	void (*get_cb_info)(PurpleConnection *, int, const char *who);
+
+	/** save/store buddy's alias on server list/roster */
+	void (*alias_buddy)(PurpleConnection *, const char *who,
+						const char *alias);
+
+	/** change a buddy's group on a server list/roster */
+	void (*group_buddy)(PurpleConnection *, const char *who,
+						const char *old_group, const char *new_group);
+
+	/** rename a group on a server list/roster */
+	void (*rename_group)(PurpleConnection *, const char *old_name,
+						 PurpleGroup *group, GList *moved_buddies);
+
+	void (*buddy_free)(PurpleBuddy *);
+
+	void (*convo_closed)(PurpleConnection *, const char *who);
+
+	/**
+	 * Convert the username @a who to its canonical form. Also checks for
+	 * validity.
+	 *
+	 * For example, AIM treats "fOo BaR" and "foobar" as the same user; this
+	 * function should return the same normalized string for both of those.
+	 * On the other hand, both of these are invalid for protocols with
+	 * number-based usernames, so function should return NULL in such case.
+	 *
+	 * @param account  The account the username is related to. Can
+	 *                 be NULL.
+	 * @param who      The username to convert.
+	 * @return         Normalized username, or NULL, if it's invalid.
+	 */
+	const char *(*normalize)(const PurpleAccount *account, const char *who);
+
+	/**
+	 * Set the buddy icon for the given connection to @a img.  The prpl
+	 * does NOT own a reference to @a img; if it needs one, it must
+	 * #purple_imgstore_ref(@a img) itself.
+	 */
+	void (*set_buddy_icon)(PurpleConnection *, PurpleStoredImage *img);
+
+	void (*remove_group)(PurpleConnection *gc, PurpleGroup *group);
+
+	/** Gets the real name of a participant in a chat.  For example, on
+	 *  XMPP this turns a chat room nick <tt>foo</tt> into
+	 *  <tt>room\@server/foo</tt>
+	 *  @param gc  the connection on which the room is.
+	 *  @param id  the ID of the chat room.
+	 *  @param who the nickname of the chat participant.
+	 *  @return    the real name of the participant.  This string must be
+	 *             freed by the caller.
+	 */
+	char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who);
+
+	void (*set_chat_topic)(PurpleConnection *gc, int id, const char *topic);
+
+	PurpleChat *(*find_blist_chat)(PurpleAccount *account, const char *name);
+
+	/* room listing prpl callbacks */
+	PurpleRoomlist *(*roomlist_get_list)(PurpleConnection *gc);
+	void (*roomlist_cancel)(PurpleRoomlist *list);
+	void (*roomlist_expand_category)(PurpleRoomlist *list, PurpleRoomlistRoom *category);
+
+	/* file transfer callbacks */
+	gboolean (*can_receive_file)(PurpleConnection *, const char *who);
+	void (*send_file)(PurpleConnection *, const char *who, const char *filename);
+	PurpleXfer *(*new_xfer)(PurpleConnection *, const char *who);
+
+	/** Checks whether offline messages to @a buddy are supported.
+	 *  @return @c TRUE if @a buddy can be sent messages while they are
+	 *          offline, or @c FALSE if not.
+	 */
+	gboolean (*offline_message)(const PurpleBuddy *buddy);
+
+	PurpleWhiteboardPrplOps *whiteboard_protocol_ops;
+
+	/** For use in plugins that may understand the underlying protocol */
+	int (*send_raw)(PurpleConnection *gc, const char *buf, int len);
+
+	/* room list serialize */
+	char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room);
+
+	/** Remove the user from the server.  The account can either be
+	 * connected or disconnected. After the removal is finished, the
+	 * connection will stay open and has to be closed!
+	 */
+	/* This is here rather than next to register_user for API compatibility
+	 * reasons.
+	 */
+	void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data);
+
+	/* Attention API for sending & receiving zaps/nudges/buzzes etc. */
+	gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type);
+	GList *(*get_attention_types)(PurpleAccount *acct);
+
+	/** 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
+	 * table is allocated every call and MUST be unrefed by the caller.
+	 *
+	 * @param account The account to specify.  This can be NULL.
+	 * @return The protocol's string hash table. The hash table should be
+	 *         destroyed by the caller when it's no longer needed.
+	 */
+	GHashTable *(*get_account_text_table)(PurpleAccount *account);
+
+	/**
+	 * Initiate a media session with the given contact.
+	 *
+	 * @param account The account to initiate the media session on.
+	 * @param who The remote user to initiate the session with.
+	 * @param type The type of media session to initiate.
+	 * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created)
+	 */
+	gboolean (*initiate_media)(PurpleAccount *account, const char *who,
+					PurpleMediaSessionType type);
+
+	/**
+	 * Checks to see if the given contact supports the given type of media session.
+	 *
+	 * @param account The account the contact is on.
+	 * @param who The remote user to check for media capability with.
+	 * @return The media caps the contact supports.
+	 */
+	PurpleMediaCaps (*get_media_caps)(PurpleAccount *account,
+					  const char *who);
+
+	/**
+	 * Returns an array of "PurpleMood"s, with the last one having
+	 * "mood" set to @c NULL.
+	 */
+	PurpleMood *(*get_moods)(PurpleAccount *account);
+
+	/**
+	 * Set the user's "friendly name" (or alias or nickname or
+	 * whatever term you want to call it) on the server.  The
+	 * protocol plugin should call success_cb or failure_cb
+	 * *asynchronously* (if it knows immediately that the set will fail,
+	 * call one of the callbacks from an idle/0-second timeout) depending
+	 * on if the nickname is set successfully.
+	 *
+	 * @param gc    The connection for which to set an alias
+	 * @param alias The new server-side alias/nickname for this account,
+	 *              or NULL to unset the alias/nickname (or return it to
+	 *              a protocol-specific "default").
+	 * @param success_cb Callback to be called if the public alias is set
+	 * @param failure_cb Callback to be called if setting the public alias
+	 *                   fails
+	 * @see purple_account_set_public_alias
+	 */
+	void (*set_public_alias)(PurpleConnection *gc, const char *alias,
+	                         PurpleSetPublicAliasSuccessCallback success_cb,
+	                         PurpleSetPublicAliasFailureCallback failure_cb);
+	/**
+	 * Retrieve the user's "friendly name" as set on the server.
+	 * The protocol plugin should call success_cb or failure_cb
+	 * *asynchronously* (even if it knows immediately that the get will fail,
+	 * call one of the callbacks from an idle/0-second timeout) depending
+	 * on if the nickname is retrieved.
+	 *
+	 * @param gc    The connection for which to retireve the alias
+	 * @param success_cb Callback to be called with the retrieved alias
+	 * @param failure_cb Callback to be called if the prpl is unable to
+	 *                   retrieve the alias
+	 * @see purple_account_get_public_alias
+	 */
+	void (*get_public_alias)(PurpleConnection *gc,
+	                         PurpleGetPublicAliasSuccessCallback success_cb,
+	                         PurpleGetPublicAliasFailureCallback failure_cb);
+};
+
+#define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
+	(G_STRUCT_OFFSET(PurpleProtocol, member) < prpl->struct_size && \
+	 prpl->member != NULL)
+
+G_BEGIN_DECLS
+
+/**************************************************************************/
+/** @name Attention Type API                                              */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Creates a new #PurpleAttentionType object and sets its mandatory parameters.
+ *
+ * @param ulname A non-localized string that can be used by UIs in need of such
+ *               non-localized strings.  This should be the same as @a name,
+ *               without localization.
+ * @param name A localized string that the UI may display for the event. This
+ *             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.
+ */
+PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name,
+								const char *inc_desc, const char *out_desc);
+
+/**
+ * Sets the displayed name of the attention-demanding event.
+ *
+ * @param type The attention type.
+ * @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.
+ */
+void purple_attention_type_set_name(PurpleAttentionType *type, const char *name);
+
+/**
+ * Sets the description of the attention-demanding event shown in  conversations
+ * when the event is received.
+ *
+ * @param type The attention type.
+ * @param desc The localized description for incoming events.
+ */
+void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc);
+
+/**
+ * Sets the description of the attention-demanding event shown in conversations
+ * when the event is sent.
+ *
+ * @param type The attention type.
+ * @param desc The localized description for outgoing events.
+ */
+void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc);
+
+/**
+ * Sets the name of the icon to display for the attention event; this is optional.
+ *
+ * @param type The attention type.
+ * @param name The icon's name.
+ * @note Icons are optional for attention events.
+ */
+void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name);
+
+/**
+ * Sets the unlocalized name of the attention event; some UIs may need this,
+ * thus it is required.
+ *
+ * @param type The attention type.
+ * @param ulname The unlocalized name.  This should be the same string given as
+ *               the localized name, but without localization.
+ */
+void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname);
+
+/**
+ * Get the attention type's name as displayed by the UI.
+ *
+ * @param type The attention type.
+ *
+ * @return The name.
+ */
+const char *purple_attention_type_get_name(const PurpleAttentionType *type);
+
+/**
+ * Get the attention type's description shown when the event is received.
+ *
+ * @param type The attention type.
+ * @return The description.
+ */
+const char *purple_attention_type_get_incoming_desc(const PurpleAttentionType *type);
+
+/**
+ * Get the attention type's description shown when the event is sent.
+ *
+ * @param type The attention type.
+ * @return The description.
+ */
+const char *purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type);
+
+/**
+ * Get the attention type's icon name.
+ *
+ * @param type The attention type.
+ * @return The icon name or @c NULL if unset/empty.
+ * @note Icons are optional for attention events.
+ */
+const char *purple_attention_type_get_icon_name(const PurpleAttentionType *type);
+
+/**
+ * Get the attention type's unlocalized name; this is useful for some UIs.
+ *
+ * @param type The attention type
+ * @return The unlocalized name.
+ */
+const char *purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name Protocol Plugin API                                             */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Notifies Purple that our account's idle state and time have changed.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account   The account.
+ * @param idle      The user's idle state.
+ * @param idle_time The user's idle time.
+ */
+void purple_protocol_got_account_idle(PurpleAccount *account, gboolean idle,
+								time_t idle_time);
+
+/**
+ * Notifies Purple of our account's log-in time.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account    The account the user is on.
+ * @param login_time The user's log-in time.
+ */
+void purple_protocol_got_account_login_time(PurpleAccount *account, time_t login_time);
+
+/**
+ * Notifies Purple that our account's status has changed.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account   The account the user is on.
+ * @param status_id The status ID.
+ * @param ...       A NULL-terminated list of attribute IDs and values,
+ *                  beginning with the value for @a attr_id.
+ */
+void purple_protocol_got_account_status(PurpleAccount *account,
+								  const char *status_id, ...) G_GNUC_NULL_TERMINATED;
+
+/**
+ * Notifies Purple that our account's actions have changed. This is only
+ * called after the initial connection. Emits the account-actions-changed
+ * signal.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account   The account.
+ *
+ * @see account-actions-changed
+ */
+void purple_protocol_got_account_actions(PurpleAccount *account);
+
+/**
+ * Notifies Purple that a buddy's idle state and time have changed.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account   The account the user is on.
+ * @param name      The name of the buddy.
+ * @param idle      The user's idle state.
+ * @param idle_time The user's idle time.  This is the time at
+ *                  which the user became idle, in seconds since
+ *                  the epoch.  If the PRPL does not know this value
+ *                  then it should pass 0.
+ */
+void purple_protocol_got_user_idle(PurpleAccount *account, const char *name,
+							 gboolean idle, time_t idle_time);
+
+/**
+ * Notifies Purple of a buddy's log-in time.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account    The account the user is on.
+ * @param name       The name of the buddy.
+ * @param login_time The user's log-in time.
+ */
+void purple_protocol_got_user_login_time(PurpleAccount *account, const char *name,
+								   time_t login_time);
+
+/**
+ * Notifies Purple that a buddy's status has been activated.
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account   The account the user is on.
+ * @param name      The name of the buddy.
+ * @param status_id The status ID.
+ * @param ...       A NULL-terminated list of attribute IDs and values,
+ *                  beginning with the value for @a attr_id.
+ */
+void purple_protocol_got_user_status(PurpleAccount *account, const char *name,
+							   const char *status_id, ...) G_GNUC_NULL_TERMINATED;
+
+/**
+ * Notifies libpurple that a buddy's status has been deactivated
+ *
+ * This is meant to be called from protocol plugins.
+ *
+ * @param account   The account the user is on.
+ * @param name      The name of the buddy.
+ * @param status_id The status ID.
+ */
+void purple_protocol_got_user_status_deactive(PurpleAccount *account, const char *name,
+					const char *status_id);
+
+/**
+ * Informs the server that our account's status changed.
+ *
+ * @param account    The account the user is on.
+ * @param old_status The previous status.
+ * @param new_status The status that was activated, or deactivated
+ *                   (in the case of independent statuses).
+ */
+void purple_protocol_change_account_status(PurpleAccount *account,
+									 PurpleStatus *old_status,
+									 PurpleStatus *new_status);
+
+/**
+ * Retrieves the list of stock status types from a prpl.
+ *
+ * @param account The account the user is on.
+ * @param presence The presence for which we're going to get statuses
+ *
+ * @return List of statuses
+ */
+GList *purple_protocol_get_statuses(PurpleAccount *account, PurplePresence *presence);
+
+/**
+ * Send an attention request message.
+ *
+ * @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 purple_protocol_send_attention(PurpleConnection *gc, const char *who, guint type_code);
+
+/**
+ * Process an incoming attention message.
+ *
+ * @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 purple_protocol_got_attention(PurpleConnection *gc, const char *who, guint type_code);
+
+/**
+ * Process an incoming attention message in a chat.
+ *
+ * @param gc The connection that received the attention message.
+ * @param id The chat id.
+ * @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 purple_protocol_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code);
+
+/**
+ * Determines if the contact supports the given media session type.
+ *
+ * @param account The account the user is on.
+ * @param who The name of the contact to check capabilities for.
+ *
+ * @return The media caps the contact supports.
+ */
+PurpleMediaCaps purple_protocol_get_media_caps(PurpleAccount *account,
+				  const char *who);
+
+/**
+ * Initiates a media session with the given contact.
+ *
+ * @param account The account the user is on.
+ * @param who The name of the contact to start a session with.
+ * @param type The type of media session to start.
+ *
+ * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created)
+ */
+gboolean purple_protocol_initiate_media(PurpleAccount *account,
+					const char *who,
+					PurpleMediaSessionType type);
+
+/**
+ * Signals that the prpl received capabilities for the given contact.
+ *
+ * This function is intended to be used only by prpls.
+ *
+ * @param account The account the user is on.
+ * @param who The name of the contact for which capabilities have been received.
+ */
+void purple_protocol_got_media_caps(PurpleAccount *account, const char *who);
+
+/** TODO A sanity check is needed
+ * Allocates and returns a new PurpleProtocolAction. Use this to add actions in
+ * a list in the get_actions function of the protocol.
+ *
+ * @param label    The description of the action to show to the user.
+ * @param callback The callback to call when the user selects this action.
+ */
+PurpleProtocolAction *purple_protocol_action_new(const char* label,
+		PurpleProtocolActionCallback callback);
+
+/** TODO A sanity check is needed
+ * Frees a PurpleProtocolAction
+ *
+ * @param action The PurpleProtocolAction to free.
+ */
+void purple_protocol_action_free(PurpleProtocolAction *action);
+
+/**************************************************************************/
+/** @name Protocols API                                                   */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Finds a protocol plugin info structure by ID.
+ *
+ * @param id The protocol's ID.
+ */
+PurpleProtocol *purple_find_protocol_info(const char *id);
+
+/** TODO A sanity check is needed
+ * Adds a protocol to the list of protocols.
+ *
+ * @param protocol  The protocol to add.
+ *
+ * @return TRUE if the protocol was added, else FALSE.
+ */
+gboolean purple_protocols_add(PurpleProtocol *protocol);
+
+/** TODO A sanity check is needed
+ * Removes a protocol from the list of protocols. This will disconnect all
+ * connected accounts using this protocol, and free the protocol's user splits
+ * and protocol options.
+ *
+ * @param protocol  The protocol to remove.
+ *
+ * @return TRUE if the protocol was removed, else FALSE.
+ */
+gboolean purple_protocols_remove(PurpleProtocol *protocol);
+
+/** TODO A sanity check is needed
+ * Returns a list of all loaded protocols.
+ *
+ * @constreturn A list of all loaded protocols.
+ */
+GList *purple_protocols_get_all(void);
+
+/*@}*/
+
+/**************************************************************************/
+/** @name Protocols Subsytem API                                          */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Initializes the protocols subsystem.
+ */
+void purple_protocols_init(void);
+
+/** TODO Make protocols use this handle, instead of plugins handle
+ * Returns the protocols subsystem handle.
+ *
+ * @return The protocols subsystem handle.
+ */
+void *purple_protocols_get_handle(void);
+
+/**
+ * Uninitializes the protocols subsystem.
+ */
+void purple_protocols_uninit(void);
+
+/*@}*/
+
+G_END_DECLS
+
+#endif /* _PROTOCOL_H_ */
--- a/libpurple/protocols/bonjour/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/bonjour/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -48,6 +48,7 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS) \
 	$(LIBXML_CFLAGS) \
-	$(AVAHI_CFLAGS)
\ No newline at end of file
+	$(AVAHI_CFLAGS)
--- a/libpurple/protocols/bonjour/bonjour.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/bonjour/bonjour.c	Sun Aug 18 01:53:00 2013 +0530
@@ -35,6 +35,7 @@
 #include "account.h"
 #include "accountopt.h"
 #include "debug.h"
+#include "plugins.h"
 #include "util.h"
 #include "version.h"
 
@@ -468,26 +469,18 @@
 	return (buddy != NULL && purple_buddy_get_protocol_data(buddy) != NULL);
 }
 
-static gboolean
-plugin_unload(PurplePlugin *plugin)
-{
-	/* These shouldn't happen here because they are allocated in _init() */
-
-	g_free(default_firstname);
-	g_free(default_lastname);
+static PurpleProtocol *my_protocol = NULL;
 
-	return TRUE;
-}
-
-static PurplePlugin *my_protocol = NULL;
-
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),                        /* struct_size */
+	"prpl-bonjour",                                          /* id */
+	"Bonjour",                                               /* name */
+	sizeof(PurpleProtocol),                        /* struct_size */
 	OPT_PROTO_NO_PASSWORD,
 	NULL,                                                    /* user_splits */
 	NULL,                                                    /* protocol_options */
 	{"png,gif,jpeg", 0, 0, 96, 96, 65535, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+	NULL,                                                    /* get_actions */
 	bonjour_list_icon,                                       /* list_icon */
 	NULL,                                                    /* list_emblem */
 	bonjour_status_text,                                     /* status_text */
@@ -542,7 +535,7 @@
 	bonjour_send_file,                                       /* send_file */
 	bonjour_new_xfer,                                        /* new_xfer */
 	NULL,                                                    /* offline_message */
-	NULL,                                                    /* whiteboard_prpl_ops */
+	NULL,                                                    /* whiteboard_protocol_ops */
 	NULL,                                                    /* send_raw */
 	NULL,                                                    /* roomlist_room_serialize */
 	NULL,                                                    /* unregister_user */
@@ -556,49 +549,12 @@
 	NULL                                                     /* get_public_alias */
 };
 
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                           /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                          /**< priority       */
-
-	"prpl-bonjour",                                   /**< id             */
-	"Bonjour",                                        /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Bonjour Protocol Plugin"),
-	                                                  /**  description    */
-	N_("Bonjour Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                   /**< homepage       */
-
-	NULL,                                             /**< load           */
-	plugin_unload,                                    /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	NULL,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
 #ifdef WIN32
 static gboolean
 _set_default_name_cb(gpointer data) {
 	gchar *fullname = data;
 	const char *splitpoint;
-	GList *tmp = prpl_info.protocol_options;
+	GList *tmp = protocol.protocol_options;
 	PurpleAccountOption *option;
 
 	if (!fullname) {
@@ -745,8 +701,26 @@
 	g_free(conv);
 }
 
-static void
-init_plugin(PurplePlugin *plugin)
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-bonjour",
+		"name", "       Bonjour",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Bonjour Protocol Plugin"),
+		"description",  N_("Bonjour Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 
@@ -754,24 +728,38 @@
 
 	/* Creating the options for the protocol */
 	option = purple_account_option_int_new(_("Local Port"), "port", BONJOUR_DEFAULT_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("First name"), "first", default_firstname);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Last name"), "last", default_lastname);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Email"), "email", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("AIM Account"), "AIM", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("XMPP Account"), "jid", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
-	my_protocol = plugin;
+	my_protocol = &protocol;
+	purple_protocols_add(my_protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(bonjour, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	g_free(default_firstname);
+	g_free(default_lastname);
+
+	purple_protocols_remove(my_protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(bonjour, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/bonjour/buddy.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/bonjour/buddy.c	Sun Aug 18 01:53:00 2013 +0530
@@ -179,12 +179,12 @@
 
 	/* Set the user's status */
 	if (bonjour_buddy->msg != NULL)
-		purple_prpl_got_user_status(account, name, status_id,
+		purple_protocol_got_user_status(account, name, status_id,
 					    "message", bonjour_buddy->msg, NULL);
 	else
-		purple_prpl_got_user_status(account, name, status_id, NULL);
+		purple_protocol_got_user_status(account, name, status_id, NULL);
 
-	purple_prpl_got_user_idle(account, name, FALSE, 0);
+	purple_protocol_got_user_idle(account, name, FALSE, 0);
 
 	/* TODO: Because we don't save Bonjour buddies in blist.xml,
 	 * we will always have to look up the buddy icon at login time.
@@ -211,7 +211,7 @@
 		purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL);
 		purple_blist_remove_buddy(pb);
 	} else {
-		purple_prpl_got_user_status(purple_buddy_get_account(pb),
+		purple_protocol_got_user_status(purple_buddy_get_account(pb),
 					    purple_buddy_get_name(pb), "offline", NULL);
 		bonjour_buddy_delete(purple_buddy_get_protocol_data(pb));
 		purple_buddy_set_protocol_data(pb, NULL);
--- a/libpurple/protocols/gg/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/gg/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -123,4 +123,5 @@
 	-I$(top_builddir)/libpurple \
 	$(INTGG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/gg/gg.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/gg/gg.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 
 #include <internal.h>
 
-#include "plugin.h"
+#include "plugins.h"
 #include "version.h"
 #include "notify.h"
 #include "buddylist.h"
@@ -146,10 +146,10 @@
 
 /*
  */
-/* static void ggp_action_buddylist_save(PurplePluginAction *action) {{{ */
-static void ggp_action_buddylist_save(PurplePluginAction *action)
+/* static void ggp_action_buddylist_save(PurpleProtocolAction *action) {{{ */
+static void ggp_action_buddylist_save(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *)action->context;
+	PurpleConnection *gc = action->connection;
 
 	purple_request_file(action, _("Save buddylist..."), NULL, TRUE,
 			G_CALLBACK(ggp_callback_buddylist_save_ok), NULL,
@@ -157,9 +157,9 @@
 			gc);
 }
 
-static void ggp_action_buddylist_load(PurplePluginAction *action)
+static void ggp_action_buddylist_load(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *)action->context;
+	PurpleConnection *gc = action->connection;
 
 	purple_request_file(action, _("Load buddylist from file..."), NULL,
 			FALSE,
@@ -776,7 +776,7 @@
 }
 
 /* ---------------------------------------------------------------------- */
-/* ----- PurplePluginProtocolInfo ----------------------------------------- */
+/* ----- PurpleProtocol ----------------------------------------- */
 /* ---------------------------------------------------------------------- */
 
 static const char *ggp_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
@@ -1288,56 +1288,56 @@
 	}
 }
 
-static void ggp_action_chpass(PurplePluginAction *action)
+static void ggp_action_chpass(PurpleProtocolAction *action)
 {
-	ggp_account_chpass((PurpleConnection *)action->context);
+	ggp_account_chpass(action->connection);
 }
 
-static void ggp_action_status_broadcasting(PurplePluginAction *action)
+static void ggp_action_status_broadcasting(PurpleProtocolAction *action)
 {
-	ggp_status_broadcasting_dialog((PurpleConnection *)action->context);
+	ggp_status_broadcasting_dialog(action->connection);
 }
 
-static void ggp_action_search(PurplePluginAction *action)
+static void ggp_action_search(PurpleProtocolAction *action)
 {
-	ggp_pubdir_search((PurpleConnection *)action->context, NULL);
+	ggp_pubdir_search(action->connection, NULL);
 }
 
-static void ggp_action_set_info(PurplePluginAction *action)
+static void ggp_action_set_info(PurpleProtocolAction *action)
 {
-	ggp_pubdir_set_info((PurpleConnection *)action->context);
+	ggp_pubdir_set_info(action->connection);
 }
 
-static GList *ggp_actions(PurplePlugin *plugin, gpointer context)
+static GList *ggp_get_actions(PurpleConnection *gc)
 {
 	GList *m = NULL;
-	PurplePluginAction *act;
+	PurpleProtocolAction *act;
 
-	act = purple_plugin_action_new(_("Change password..."),
+	act = purple_protocol_action_new(_("Change password..."),
 		ggp_action_chpass);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Show status only for buddies"),
+	act = purple_protocol_action_new(_("Show status only for buddies"),
 		ggp_action_status_broadcasting);
 	m = g_list_append(m, act);
 
 	m = g_list_append(m, NULL);
 
-	act = purple_plugin_action_new(_("Find buddies..."),
+	act = purple_protocol_action_new(_("Find buddies..."),
 		ggp_action_search);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Set User Info"),
+	act = purple_protocol_action_new(_("Set User Info"),
 		ggp_action_set_info);
 	m = g_list_append(m, act);
 
 	m = g_list_append(m, NULL);
 
-	act = purple_plugin_action_new(_("Save buddylist to file..."),
+	act = purple_protocol_action_new(_("Save buddylist to file..."),
 				     ggp_action_buddylist_save);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Load buddylist from file..."),
+	act = purple_protocol_action_new(_("Load buddylist from file..."),
 				     ggp_action_buddylist_load);
 	m = g_list_append(m, act);
 
@@ -1367,13 +1367,16 @@
 	return table;
 }
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-gg",			/* id */
+	"Gadu-Gadu",			/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE,
 	NULL,				/* user_splits */
 	NULL,				/* protocol_options */
 	{"png", 1, 1, 200, 200, 0, PURPLE_ICON_SCALE_DISPLAY | PURPLE_ICON_SCALE_SEND},	/* icon_spec */
+	ggp_get_actions,		/* get_actions */
 	ggp_list_icon,			/* list_icon */
 	ggp_list_emblem,		/* list_emblem */
 	ggp_status_buddy_text,		/* status_text */
@@ -1387,7 +1390,7 @@
 	ggp_send_im,			/* send_im */
 	NULL,				/* set_info */
 	ggp_send_typing,		/* send_typing */
-	ggp_pubdir_get_info_prpl,	/* get_info */
+	ggp_pubdir_get_info_protocol,	/* get_info */
 	ggp_status_set_purplestatus,	/* set_away */
 	NULL,				/* set_idle */
 	NULL,				/* change_passwd */
@@ -1428,7 +1431,7 @@
 	NULL,				/* send_file */
 	NULL,				/* new_xfer */
 	ggp_offline_message,		/* offline_message */
-	NULL,				/* whiteboard_prpl_ops */
+	NULL,				/* whiteboard_protocol_ops */
 	NULL,				/* send_raw */
 	NULL,				/* roomlist_room_serialize */
 	NULL,				/* unregister_user */
@@ -1442,44 +1445,6 @@
 	NULL				/* get_public_alias */
 };
 
-static gboolean ggp_load(PurplePlugin *plugin);
-static gboolean ggp_unload(PurplePlugin *plugin);
-
-static PurplePluginInfo info = {
-	PURPLE_PLUGIN_MAGIC,			/* magic */
-	PURPLE_MAJOR_VERSION,			/* major_version */
-	PURPLE_MINOR_VERSION,			/* minor_version */
-	PURPLE_PLUGIN_PROTOCOL,			/* plugin type */
-	NULL,					/* ui_requirement */
-	0,					/* flags */
-	NULL,					/* dependencies */
-	PURPLE_PRIORITY_DEFAULT,		/* priority */
-
-	"prpl-gg",				/* id */
-	"Gadu-Gadu",				/* name */
-	DISPLAY_VERSION,			/* version */
-
-	N_("Gadu-Gadu Protocol Plugin"),	/* summary */
-	N_("Polish popular IM"),		/* description */
-	"boler@sourceforge.net",		/* author */
-	PURPLE_WEBSITE,				/* homepage */
-
-	ggp_load,				/* load */
-	ggp_unload,				/* unload */
-	NULL,					/* destroy */
-
-	NULL,					/* ui_info */
-	&prpl_info,				/* extra_info */
-	NULL,					/* prefs_info */
-	ggp_actions,				/* actions */
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
 static void purple_gg_debug_handler(int level, const char * format, va_list args) {
 	PurpleDebugLevel purple_level;
 	char *msg = g_strdup_vprintf(format, args);
@@ -1503,9 +1468,29 @@
 	g_free(msg);
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-gg",
+		"name",         "Gadu-Gadu",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Gadu-Gadu Protocol Plugin"),
+		"description",  N_("Polish popular IM"),
+		"author",       "boler@sourceforge.net",
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
 static PurpleAccountOption *ggp_server_option;
 
-static void init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 	GList *encryption_options = NULL;
@@ -1514,7 +1499,7 @@
 
 	option = purple_account_option_string_new(_("GG server"),
 			"gg_server", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 			option);
 	ggp_server_option = option;
 
@@ -1532,34 +1517,36 @@
 
 	option = purple_account_option_list_new(_("Connection security"),
 		"encryption", encryption_options);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.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,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 		option);
 
 	gg_debug_handler = purple_gg_debug_handler;
-}
 
-static gboolean ggp_load(PurplePlugin *plugin)
-{
 	purple_debug_info("gg", "Loading Gadu-Gadu protocol plugin with "
 		"libgadu %s...\n", gg_libgadu_version());
 
 	ggp_resolver_purple_setup();
 	ggp_servconn_setup(ggp_server_option);
-	
+
+	purple_protocols_add(&protocol);
+
 	return TRUE;
 }
 
-static gboolean ggp_unload(PurplePlugin *plugin)
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
 	ggp_servconn_cleanup();
+	purple_protocols_remove(&protocol);
+
 	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(gg, init_plugin, info);
+PURPLE_PLUGIN_INIT(gg, plugin_query, plugin_load, plugin_unload);
 
 /* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/pubdir-prpl.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/gg/pubdir-prpl.c	Sun Aug 18 01:53:00 2013 +0530
@@ -66,7 +66,7 @@
 static void ggp_pubdir_got_data(PurpleHttpConnection *http_conn,
 	PurpleHttpResponse *response, gpointer user_data);
 
-static void ggp_pubdir_get_info_prpl_got(PurpleConnection *gc,
+static void ggp_pubdir_get_info_protocol_got(PurpleConnection *gc,
 	int records_count, const ggp_pubdir_record *records, int next_offset,
 	void *_uin_p);
 
@@ -350,19 +350,19 @@
 	ggp_pubdir_record_free(records, record_count);
 }
 
-void ggp_pubdir_get_info_prpl(PurpleConnection *gc, const char *name)
+void ggp_pubdir_get_info_protocol(PurpleConnection *gc, const char *name)
 {
 	uin_t uin = ggp_str_to_uin(name);
 	uin_t *uin_p = g_new0(uin_t, 1);
 
 	*uin_p = uin;
 
-	purple_debug_info("gg", "ggp_pubdir_get_info_prpl: %u\n", uin);
+	purple_debug_info("gg", "ggp_pubdir_get_info_protocol: %u\n", uin);
 
-	ggp_pubdir_get_info(gc, uin, ggp_pubdir_get_info_prpl_got, uin_p);
+	ggp_pubdir_get_info(gc, uin, ggp_pubdir_get_info_protocol_got, uin_p);
 }
 
-static void ggp_pubdir_get_info_prpl_got(PurpleConnection *gc,
+static void ggp_pubdir_get_info_protocol_got(PurpleConnection *gc,
 	int records_count, const ggp_pubdir_record *records, int next_offset,
 	void *_uin_p)
 {
@@ -375,7 +375,7 @@
 	
 	if (records_count < 1)
 	{
-		purple_debug_error("gg", "ggp_pubdir_get_info_prpl_got: "
+		purple_debug_error("gg", "ggp_pubdir_get_info_protocol_got: "
 			"couldn't get info for %u\n", uin);
 		purple_notify_user_info_add_pair_plaintext(info, NULL,
 			_("Cannot get user information"));
@@ -385,7 +385,7 @@
 		return;
 	}
 	
-	purple_debug_info("gg", "ggp_pubdir_get_info_prpl_got: %u\n", uin);
+	purple_debug_info("gg", "ggp_pubdir_get_info_protocol_got: %u\n", uin);
 	g_assert(uin == record->uin);
 	g_assert(records_count == 1);
 	
@@ -785,7 +785,7 @@
 static void ggp_pubdir_search_results_info(PurpleConnection *gc, GList *row,
 	gpointer _form)
 {
-	ggp_pubdir_get_info_prpl(gc, g_list_nth_data(row, 0));
+	ggp_pubdir_get_info_protocol(gc, g_list_nth_data(row, 0));
 }
 
 static void ggp_pubdir_search_results_new(PurpleConnection *gc, GList *row,
--- a/libpurple/protocols/gg/pubdir-prpl.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/gg/pubdir-prpl.h	Sun Aug 18 01:53:00 2013 +0530
@@ -27,8 +27,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
-#ifndef _GGP_PUBDIR_PRPL_H
-#define _GGP_PUBDIR_PRPL_H
+#ifndef _GGP_PUBDIR_PROTOCOL_H
+#define _GGP_PUBDIR_PROTOCOL_H
 
 #include <internal.h>
 #include <libgadu.h>
@@ -62,7 +62,7 @@
 void ggp_pubdir_get_info(PurpleConnection *gc, uin_t uin,
 	ggp_pubdir_request_cb cb, void *user_data);
 
-void ggp_pubdir_get_info_prpl(PurpleConnection *gc, const char *name);
+void ggp_pubdir_get_info_protocol(PurpleConnection *gc, const char *name);
 void ggp_pubdir_request_buddy_alias(PurpleConnection *gc, PurpleBuddy *buddy);
 
 void ggp_pubdir_search(PurpleConnection *gc,
@@ -70,4 +70,4 @@
 
 void ggp_pubdir_set_info(PurpleConnection *gc);
 
-#endif /* _GGP_PUBDIR_PRPL_H */
+#endif /* _GGP_PUBDIR_PROTOCOL_H */
--- a/libpurple/protocols/gg/status.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/gg/status.c	Sun Aug 18 01:53:00 2013 +0530
@@ -313,7 +313,7 @@
 			GG_STATUS_DESCR_MAXSIZE);
 	}
 	
-	purple_prpl_got_user_status(account,
+	purple_protocol_got_user_status(account,
 		purple_account_get_username(account),
 		purple_status_get_id(status),
 		status_msg_gg ? "message" : NULL, status_msg_gg, NULL);
@@ -446,12 +446,12 @@
 	
 	if (status_message)
 	{
-		purple_prpl_got_user_status(account, ggp_uin_to_str(uin),
+		purple_protocol_got_user_status(account, ggp_uin_to_str(uin),
 			purple_status, "message", status_message, NULL);
 	}
 	else
 	{
-		purple_prpl_got_user_status(account, ggp_uin_to_str(uin),
+		purple_protocol_got_user_status(account, ggp_uin_to_str(uin),
 			purple_status, NULL);
 	}
 	
--- a/libpurple/protocols/irc/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/irc/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -35,4 +35,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/irc/irc.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/irc/irc.c	Sun Aug 18 01:53:00 2013 +0530
@@ -30,8 +30,8 @@
 #include "conversation.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
-#include "plugin.h"
+#include "protocol.h"
+#include "plugins.h"
 #include "util.h"
 #include "version.h"
 
@@ -43,7 +43,7 @@
 
 static const char *irc_blist_icon(PurpleAccount *a, PurpleBuddy *b);
 static GList *irc_status_types(PurpleAccount *account);
-static GList *irc_actions(PurplePlugin *plugin, gpointer context);
+static GList *irc_get_actions(PurpleConnection *gc);
 /* static GList *irc_chat_info(PurpleConnection *gc); */
 static void irc_login(PurpleAccount *account);
 static void irc_login_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
@@ -60,11 +60,11 @@
 static gboolean irc_nick_equal(const char *nick1, const char *nick2);
 static void irc_buddy_free(struct irc_buddy *ib);
 
-PurplePlugin *_irc_plugin = NULL;
+PurpleProtocol *_irc_protocol = NULL;
 
-static void irc_view_motd(PurplePluginAction *action)
+static void irc_view_motd(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	struct irc_conn *irc;
 	char *title;
 
@@ -157,7 +157,7 @@
 	int ret;
  	char *tosend= g_strdup(buf);
 
-	purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend);
+	purple_signal_emit(_irc_protocol, "irc-sending-text", purple_account_get_connection(irc->account), &tosend);
 	
 	if (tosend == NULL)
 		return 0;
@@ -284,12 +284,12 @@
 	return types;
 }
 
-static GList *irc_actions(PurplePlugin *plugin, gpointer context)
+static GList *irc_get_actions(PurpleConnection *gc)
 {
 	GList *list = NULL;
-	PurplePluginAction *act = NULL;
+	PurpleProtocolAction *act = NULL;
 
-	act = purple_plugin_action_new(_("View MOTD"), irc_view_motd);
+	act = purple_protocol_action_new(_("View MOTD"), irc_view_motd);
 	list = g_list_append(list, act);
 
 	return list;
@@ -614,7 +614,7 @@
 	ib = g_hash_table_lookup(irc->buddies, bname);
 	if (ib != NULL) {
 		ib->ref++;
-		purple_prpl_got_user_status(irc->account, bname,
+		purple_protocol_got_user_status(irc->account, bname,
 				ib->online ? "available" : "offline", NULL);
 	} else {
 		ib = g_new0(struct irc_buddy, 1);
@@ -915,14 +915,17 @@
 		irc_cmd_ping(irc, NULL, NULL, NULL);
 }
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),    /* struct_size */
+	"prpl-irc",			/* id */
+	"IRC",					/* name */
+	sizeof(PurpleProtocol),    /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL |
 	OPT_PROTO_SLASH_COMMANDS_NATIVE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
 	NO_BUDDY_ICONS,		/* icon_spec */
+	irc_get_actions,		/* get_actions */
 	irc_blist_icon,		/* list_icon */
 	NULL,			/* list_emblems */
 	NULL,					/* status_text */
@@ -977,7 +980,7 @@
 	irc_dccsend_send_file,	/* send_file */
 	irc_dccsend_new_xfer,	/* new_xfer */
 	NULL,					/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
+	NULL,					/* whiteboard_protocol_ops */
 	irc_send_raw,			/* send_raw */
 	NULL,					/* roomlist_room_serialize */
 	NULL,                   /* unregister_user */
@@ -991,102 +994,93 @@
 	NULL					 /* get_public_alias */
 };
 
-static gboolean load_plugin (PurplePlugin *plugin) {
-
-	purple_signal_register(plugin, "irc-sending-text",
-			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			     PURPLE_TYPE_CONNECTION,
-			     G_TYPE_POINTER); /* pointer to a string */
-	purple_signal_register(plugin, "irc-receiving-text",
-			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
-			     PURPLE_TYPE_CONNECTION,
-			     G_TYPE_POINTER); /* pointer to a string */
-	return TRUE;
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-irc",
+		"name",         "IRC",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("IRC Protocol Plugin"),
+		"description",  N_("The IRC Protocol Plugin that Sucks Less"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
 }
 
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	"prpl-irc",                                       /**< id             */
-	"IRC",                                            /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	N_("IRC Protocol Plugin"),                        /**  summary        */
-	N_("The IRC Protocol Plugin that Sucks Less"),    /**  description    */
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	load_plugin,                                      /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	irc_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void _init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountUserSplit *split;
 	PurpleAccountOption *option;
 
 	split = purple_account_user_split_new(_("Server"), IRC_DEFAULT_SERVER, '@');
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 	option = purple_account_option_int_new(_("Port"), "port", IRC_DEFAULT_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Encodings"), "encoding", IRC_DEFAULT_CHARSET);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Auto-detect incoming UTF-8"), "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Username"), "username", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Real name"), "realname", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	/*
 	option = purple_account_option_string_new(_("Quit message"), "quitmsg", IRC_DEFAULT_QUIT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	*/
 
 	option = purple_account_option_bool_new(_("Use SSL"), "ssl", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 #ifdef HAVE_CYRUS_SASL
 	option = purple_account_option_bool_new(_("Authenticate with SASL"), "sasl", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(
 						_("Allow plaintext SASL auth over unencrypted connection"),
 						"auth_plain_in_clear", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 #endif
 
-	_irc_plugin = plugin;
+	_irc_protocol = &protocol;
 
 	purple_prefs_remove("/plugins/prpl/irc/quitmsg");
 	purple_prefs_remove("/plugins/prpl/irc");
 
 	irc_register_commands();
+
+	purple_signal_register(_irc_protocol, "irc-sending-text",
+			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
+			     PURPLE_TYPE_CONNECTION,
+			     G_TYPE_POINTER); /* pointer to a string */
+	purple_signal_register(_irc_protocol, "irc-receiving-text",
+			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
+			     PURPLE_TYPE_CONNECTION,
+			     G_TYPE_POINTER); /* pointer to a string */
+
+	purple_protocols_add(_irc_protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(irc, _init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(_irc_protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(irc, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/irc/msgs.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/irc/msgs.c	Sun Aug 18 01:53:00 2013 +0530
@@ -100,8 +100,8 @@
 	/* If we're away then set our away message */
 	status = purple_account_get_active_status(irc->account);
 	if (purple_status_type_get_primitive(purple_status_get_status_type(status)) != PURPLE_STATUS_AVAILABLE) {
-		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-		prpl_info->set_status(irc->account, status);
+		PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
+		protocol->set_status(irc->account, status);
 	}
 
 	/* this used to be in the core, but it's not now */
@@ -945,10 +945,10 @@
 		return;
 
 	if (ib->online && !ib->new_online_status) {
-		purple_prpl_got_user_status(irc->account, name, "offline", NULL);
+		purple_protocol_got_user_status(irc->account, name, "offline", NULL);
 		ib->online = FALSE;
 	} else if (!ib->online && ib->new_online_status) {
-		purple_prpl_got_user_status(irc->account, name, "available", NULL);
+		purple_protocol_got_user_status(irc->account, name, "available", NULL);
 		ib->online = TRUE;
 	}
 }
--- a/libpurple/protocols/irc/parse.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/irc/parse.c	Sun Aug 18 01:53:00 2013 +0530
@@ -44,7 +44,7 @@
 		"orange", "yellow", "green", "teal", "cyan", "light blue",
 		"pink", "grey", "light grey" };
 
-extern PurplePlugin *_irc_plugin;
+extern PurpleProtocol *_irc_protocol;
 
 /*typedef void (*IRCMsgCallback)(struct irc_conn *irc, char *from, char *name, char **args);*/
 static struct _irc_msg {
@@ -200,7 +200,7 @@
 	char *format;
 	size_t i;
 
-	f = PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY
+	f = PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY
 	    | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS;
 
 	format = c->format;
@@ -221,7 +221,7 @@
 
 	args[i] = '\0';
 
-	purple_cmd_register(c->name, args, PURPLE_CMD_P_PRPL, f, "prpl-irc",
+	purple_cmd_register(c->name, args, PURPLE_CMD_P_PROTOCOL, f, "prpl-irc",
 	                  irc_parse_purple_cmd, _(c->help), NULL);
 }
 
@@ -670,7 +670,7 @@
 	 * TODO: It should be passed as an array of bytes and a length
 	 * instead of a null terminated string.
 	 */
-	purple_signal_emit(_irc_plugin, "irc-receiving-text", gc, &input);
+	purple_signal_emit(_irc_protocol, "irc-receiving-text", gc, &input);
 
 	if (!strncmp(input, "PING ", 5)) {
 		msg = irc_format(irc, "vv", "PONG", input + 5);
--- a/libpurple/protocols/jabber/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -133,6 +133,7 @@
 	-I$(top_builddir)/libpurple \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(IDN_CFLAGS) \
 	$(LIBXML_CFLAGS) \
 	$(FARSIGHT_CFLAGS) \
--- a/libpurple/protocols/jabber/adhoccommands.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/adhoccommands.c	Sun Aug 18 01:53:00 2013 +0530
@@ -269,7 +269,7 @@
 	}
 
 	if (js->state == JABBER_STREAM_CONNECTED)
-		purple_prpl_got_account_actions(purple_connection_get_account(js->gc));
+		purple_protocol_got_account_actions(purple_connection_get_account(js->gc));
 }
 
 static void
@@ -318,10 +318,10 @@
 	jabber_iq_send(iq);
 }
 
-static void jabber_adhoc_server_execute(PurplePluginAction *action) {
+static void jabber_adhoc_server_execute(PurpleProtocolAction *action) {
 	JabberAdHocCommands *cmd = action->user_data;
 	if(cmd) {
-		PurpleConnection *gc = (PurpleConnection *) action->context;
+		PurpleConnection *gc = (PurpleConnection *) action->connection;
 		JabberStream *js = purple_connection_get_protocol_data(gc);
 
 		jabber_adhoc_execute(js, cmd);
@@ -342,7 +342,7 @@
 			for(riter = jbr->commands; riter; riter = g_list_next(riter)) {
 				JabberAdHocCommands *cmd = riter->data;
 				char *cmdname = g_strdup_printf("%s (%s)",cmd->name,jbr->name);
-				PurplePluginAction *act = purple_plugin_action_new(cmdname, jabber_adhoc_server_execute);
+				PurpleProtocolAction *act = purple_protocol_action_new(cmdname, jabber_adhoc_server_execute);
 				act->user_data = cmd;
 				*m = g_list_append(*m, act);
 				g_free(cmdname);
@@ -354,7 +354,7 @@
 	/* now add server commands */
 	for(cmdlst = js->commands; cmdlst; cmdlst = g_list_next(cmdlst)) {
 		JabberAdHocCommands *cmd = cmdlst->data;
-		PurplePluginAction *act = purple_plugin_action_new(cmd->name, jabber_adhoc_server_execute);
+		PurpleProtocolAction *act = purple_protocol_action_new(cmd->name, jabber_adhoc_server_execute);
 		act->user_data = cmd;
 		*m = g_list_append(*m, act);
 	}
--- a/libpurple/protocols/jabber/buddy.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/buddy.c	Sun Aug 18 01:53:00 2013 +0530
@@ -23,7 +23,7 @@
 #include "internal.h"
 #include "debug.h"
 #include "imgstore.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "notify.h"
 #include "request.h"
 #include "util.h"
@@ -624,9 +624,9 @@
  * string (if any) into GSLists for the (multi-entry) edit dialog and
  * calls the set_vcard dialog.
  */
-void jabber_setup_set_info(PurplePluginAction *action)
+void jabber_setup_set_info(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = (PurpleConnection *) action->connection;
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
@@ -1361,7 +1361,7 @@
 
 									if (jbr ==
 										jabber_buddy_find_resource(jb, NULL)) {
-										purple_prpl_got_user_idle(purple_connection_get_account(js->gc),
+										purple_protocol_got_user_idle(purple_connection_get_account(js->gc),
 											buddy_name, jbr->idle, jbr->idle);
 									}
 								}
@@ -2270,9 +2270,9 @@
 	jabber_iq_send(iq);
 }
 
-void jabber_user_search_begin(PurplePluginAction *action)
+void jabber_user_search_begin(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = (PurpleConnection *) action->connection;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 	const char *def_val = purple_account_get_string(purple_connection_get_account(js->gc), "user_directory", "");
 	if(!*def_val && js->user_directories)
--- a/libpurple/protocols/jabber/buddy.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/buddy.h	Sun Aug 18 01:53:00 2013 +0530
@@ -103,11 +103,11 @@
 GList *jabber_blist_node_menu(PurpleBlistNode *node);
 
 void jabber_set_info(PurpleConnection *gc, const char *info);
-void jabber_setup_set_info(PurplePluginAction *action);
+void jabber_setup_set_info(PurpleProtocolAction *action);
 void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img);
 
 void jabber_user_search(JabberStream *js, const char *directory);
-void jabber_user_search_begin(PurplePluginAction *);
+void jabber_user_search_begin(PurpleProtocolAction *);
 
 void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js);
 
--- a/libpurple/protocols/jabber/caps.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/caps.c	Sun Aug 18 01:53:00 2013 +0530
@@ -972,8 +972,8 @@
 
 	for (node = accounts; node; node = node->next) {
 		PurpleAccount *account = node->data;
-		const char *prpl_id = purple_account_get_protocol_id(account);
-		if (g_str_equal("prpl-jabber", prpl_id) && purple_account_is_connected(account)) {
+		const char *protocol_id = purple_account_get_protocol_id(account);
+		if (g_str_equal("prpl-jabber", protocol_id) && purple_account_is_connected(account)) {
 			PurpleConnection *gc = purple_account_get_connection(account);
 			jabber_presence_send(purple_connection_get_protocol_data(gc), TRUE);
 		}
--- a/libpurple/protocols/jabber/chat.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/chat.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
  */
 #include "internal.h"
 #include "debug.h"
-#include "prpl.h" /* for proto_chat_entry */
+#include "protocol.h" /* for proto_chat_entry */
 #include "notify.h"
 #include "request.h"
 #include "roomlist.h"
--- a/libpurple/protocols/jabber/google/google_presence.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/google/google_presence.c	Sun Aug 18 01:53:00 2013 +0530
@@ -27,12 +27,12 @@
 	if (!js->googletalk)
 		return;
 	if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) {
-		purple_prpl_got_user_status(purple_connection_get_account(js->gc), user, "tune",
+		purple_protocol_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(purple_connection_get_account(js->gc), user, "tune");
+		purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), user, "tune");
 	}
 }
 
--- a/libpurple/protocols/jabber/google/google_roster.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/google/google_roster.c	Sun Aug 18 01:53:00 2013 +0530
@@ -156,7 +156,7 @@
 		}
 	}
 
-	purple_prpl_got_user_status(account, who, "offline", NULL);
+	purple_protocol_got_user_status(account, who, "offline", NULL);
 }
 
 void jabber_google_roster_rem_deny(JabberStream *js, const char *who)
--- a/libpurple/protocols/jabber/google/google_session.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/google/google_session.c	Sun Aug 18 01:53:00 2013 +0530
@@ -357,7 +357,7 @@
 			purple_connection_get_account(js->gc),
 			"fsrtpconference", session->remote_jid, TRUE);
 
-	purple_media_set_prpl_data(session_data->media, session);
+	purple_media_set_protocol_data(session_data->media, session);
 
 	g_signal_connect_swapped(G_OBJECT(session_data->media),
 			"candidates-prepared",
@@ -584,7 +584,7 @@
 			purple_connection_get_account(js->gc),
 			"fsrtpconference", session->remote_jid, FALSE);
 
-	purple_media_set_prpl_data(session_data->media, session);
+	purple_media_set_protocol_data(session_data->media, session);
 
 	g_signal_connect_swapped(G_OBJECT(session_data->media),
 			"candidates-prepared",
@@ -829,7 +829,7 @@
 			purple_connection_get_account(js->gc));
 	for (; iter; iter = g_list_delete_link(iter, iter)) {
 		GoogleSession *gsession =
-				purple_media_get_prpl_data(iter->data);
+				purple_media_get_protocol_data(iter->data);
 		if (google_session_id_equal(&(gsession->id), &id)) {
 			session = gsession;
 			break;
--- a/libpurple/protocols/jabber/iq.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/iq.c	Sun Aug 18 01:53:00 2013 +0530
@@ -345,7 +345,7 @@
 		return;
 	}
 
-	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc),
+	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc),
 			"jabber-receiving-iq", js->gc, iq_type, id, from, packet));
 	if (signal_return)
 		return;
@@ -370,7 +370,7 @@
 		g_free(key);
 
 		if (signal_ref > 0) {
-			signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), "jabber-watched-iq",
+			signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc), "jabber-watched-iq",
 					js->gc, iq_type, id, from, child));
 			if (signal_return)
 				return;
--- a/libpurple/protocols/jabber/jabber.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/jabber.c	Sun Aug 18 01:53:00 2013 +0530
@@ -37,7 +37,7 @@
 #include "notify.h"
 #include "pluginpref.h"
 #include "proxy.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "server.h"
 #include "status.h"
@@ -81,7 +81,7 @@
 GList *jabber_features = NULL;
 GList *jabber_identities = NULL;
 
-static GHashTable *jabber_cmds = NULL; /* PurplePlugin * => GSList of ids */
+static GHashTable *jabber_cmds = NULL; /* PurpleProtocol * => GSList of ids */
 
 static gint plugin_ref = 0;
 
@@ -332,7 +332,7 @@
 	const char *name;
 	const char *xmlns;
 
-	purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-receiving-xmlnode", js->gc, packet);
+	purple_signal_emit(purple_connection_get_protocol_info(js->gc), "jabber-receiving-xmlnode", js->gc, packet);
 
 	/* if the signal leaves us with a null packet, we're done */
 	if(NULL == *packet)
@@ -514,7 +514,7 @@
 		g_free(text);
 	}
 
-	purple_signal_emit(purple_connection_get_prpl(gc), "jabber-sending-text", gc, &data);
+	purple_signal_emit(purple_connection_get_protocol_info(gc), "jabber-sending-text", gc, &data);
 	if (data == NULL)
 		return;
 
@@ -571,7 +571,7 @@
 		do_jabber_send_raw(js, data, len);
 }
 
-int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len)
+int jabber_protocol_send_raw(PurpleConnection *gc, const char *buf, int len)
 {
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 
@@ -614,7 +614,7 @@
 
 void jabber_send(JabberStream *js, xmlnode *packet)
 {
-	purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-sending-xmlnode", js->gc, &packet);
+	purple_signal_emit(purple_connection_get_protocol_info(js->gc), "jabber-sending-xmlnode", js->gc, &packet);
 }
 
 static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
@@ -2513,10 +2513,10 @@
 	jabber_iq_send(iq);
 }
 
-static void jabber_password_change(PurplePluginAction *action)
+static void jabber_password_change(PurpleProtocolAction *action)
 {
 
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = (PurpleConnection *) action->connection;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *group;
@@ -2546,28 +2546,27 @@
 			js);
 }
 
-GList *jabber_actions(PurplePlugin *plugin, gpointer context)
+GList *jabber_get_actions(PurpleConnection *gc)
 {
-	PurpleConnection *gc = (PurpleConnection *) context;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 	GList *m = NULL;
-	PurplePluginAction *act;
-
-	act = purple_plugin_action_new(_("Set User Info..."),
+	PurpleProtocolAction *act;
+
+	act = purple_protocol_action_new(_("Set User Info..."),
 	                             jabber_setup_set_info);
 	m = g_list_append(m, act);
 
 	/* if (js->protocol_options & CHANGE_PASSWORD) { */
-		act = purple_plugin_action_new(_("Change Password..."),
+		act = purple_protocol_action_new(_("Change Password..."),
 		                             jabber_password_change);
 		m = g_list_append(m, act);
 	/* } */
 
-	act = purple_plugin_action_new(_("Search for Users..."),
+	act = purple_protocol_action_new(_("Search for Users..."),
 	                             jabber_user_search_begin);
 	m = g_list_append(m, act);
 
-	purple_debug_info("jabber", "jabber_actions: have pep: %s\n", js->pep?"YES":"NO");
+	purple_debug_info("jabber", "jabber_get_actions: have pep: %s\n", js->pep?"YES":"NO");
 
 	if(js->pep)
 		jabber_pep_init_actions(&m);
@@ -3597,129 +3596,129 @@
 	}
 }
 
-static void jabber_register_commands(PurplePlugin *plugin)
+static void jabber_register_commands(PurpleProtocol *protocol)
 {
 	GSList *commands = NULL;
 	PurpleCmdId id;
-	id = purple_cmd_register("config", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	id = purple_cmd_register("config", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-jabber", jabber_cmd_chat_config,
 	                  _("config:  Configure a chat room."), NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("configure", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	id = purple_cmd_register("configure", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-jabber", jabber_cmd_chat_config,
 	                  _("configure:  Configure a chat room."), NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("nick", "s", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	id = purple_cmd_register("nick", "s", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-jabber", jabber_cmd_chat_nick,
 	                  _("nick &lt;new nickname&gt;:  Change your nickname."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("part", "s", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_part, _("part [message]:  Leave the room."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("register", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	id = purple_cmd_register("register", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-jabber", jabber_cmd_chat_register,
 	                  _("register:  Register with a chat room."), NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
 	/* XXX: there needs to be a core /topic cmd, methinks */
-	id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_topic,
 	                  _("topic [new topic]:  View or change the topic."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("ban", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("ban", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_ban,
 	                  _("ban &lt;user&gt; [reason]:  Ban a user from the room."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_affiliate,
 	                  _("affiliate &lt;owner|admin|member|outcast|none&gt; [nick1] [nick2] ...: Get the users with an affiliation or set users' affiliation with the room."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("role", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_role,
 	                  _("role &lt;moderator|participant|visitor|none&gt; [nick1] [nick2] ...: Get the users with a role or set users' role with the room."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_invite,
 	                  _("invite &lt;user&gt; [message]:  Invite a user to the room."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_join,
 	                  _("join: &lt;room[@server]&gt; [password]:  Join a chat."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("kick", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("kick", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 	                  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
 	                  jabber_cmd_chat_kick,
 	                  _("kick &lt;user&gt; [reason]:  Kick a user from the room."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-jabber", jabber_cmd_chat_msg,
 	                  _("msg &lt;user&gt; &lt;message&gt;:  Send a private message to another user."),
 	                  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("ping", "w", PURPLE_CMD_P_PRPL,
+	id = purple_cmd_register("ping", "w", PURPLE_CMD_P_PROTOCOL,
 					  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM |
-					  PURPLE_CMD_FLAG_PRPL_ONLY,
+					  PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 					  "prpl-jabber", jabber_cmd_ping,
 					  _("ping &lt;jid&gt;:	Ping a user/component/server."),
 					  NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("buzz", "w", PURPLE_CMD_P_PRPL,
-					  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY |
+	id = purple_cmd_register("buzz", "w", PURPLE_CMD_P_PROTOCOL,
+					  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 					  PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 					  "prpl-jabber", jabber_cmd_buzz,
 					  _("buzz: Buzz a user to get their attention"), NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	id = purple_cmd_register("mood", "ws", PURPLE_CMD_P_PRPL,
+	id = purple_cmd_register("mood", "ws", PURPLE_CMD_P_PROTOCOL,
 	    			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM |
-	    			  PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+	    			  PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 	    			  "prpl-jabber", jabber_cmd_mood,
 	    			  _("mood &lt;mood&gt; [text]: Set current user mood"), NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
-	g_hash_table_insert(jabber_cmds, plugin, commands);
+	g_hash_table_insert(jabber_cmds, protocol, commands);
 }
 
 static void cmds_free_func(gpointer value)
@@ -3731,11 +3730,12 @@
 	}
 }
 
-static void jabber_unregister_commands(PurplePlugin *plugin)
+static void jabber_unregister_commands(PurpleProtocol *protocol)
 {
-	g_hash_table_remove(jabber_cmds, plugin);
+	g_hash_table_remove(jabber_cmds, protocol);
 }
 
+#if 0
 /* IPC functions */
 
 /**
@@ -3783,6 +3783,7 @@
 	/* send presence with new caps info for all connected accounts */
 	jabber_caps_broadcast_change();
 }
+#endif
 
 static void
 jabber_do_init(void)
@@ -3931,15 +3932,16 @@
 	jabber_cmds = NULL;
 }
 
-void jabber_plugin_init(PurplePlugin *plugin)
+void jabber_plugin_init(PurpleProtocol *protocol)
 {
 	++plugin_ref;
 
 	if (plugin_ref == 1)
 		jabber_do_init();
 
-	jabber_register_commands(plugin);
-
+	jabber_register_commands(protocol);
+
+#if 0
 	/* IPC functions */
 	purple_plugin_ipc_register(plugin, "contact_has_feature", PURPLE_CALLBACK(jabber_ipc_contact_has_feature),
 							 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER,
@@ -3963,31 +3965,32 @@
 	                           G_TYPE_NONE, 2,
 	                           G_TYPE_STRING,  /* node */
 	                           G_TYPE_STRING); /* namespace */
-
-	purple_signal_register(plugin, "jabber-register-namespace-watcher",
+#endif
+
+	purple_signal_register(protocol, "jabber-register-namespace-watcher",
 			purple_marshal_VOID__POINTER_POINTER,
 			G_TYPE_NONE, 2,
 			G_TYPE_STRING,  /* node */
 			G_TYPE_STRING); /* namespace */
 
-	purple_signal_register(plugin, "jabber-unregister-namespace-watcher",
+	purple_signal_register(protocol, "jabber-unregister-namespace-watcher",
 			purple_marshal_VOID__POINTER_POINTER,
 			G_TYPE_NONE, 2,
 			G_TYPE_STRING,  /* node */
 			G_TYPE_STRING); /* namespace */
 
-	purple_signal_connect(plugin, "jabber-register-namespace-watcher",
-			plugin, PURPLE_CALLBACK(jabber_iq_signal_register), NULL);
-	purple_signal_connect(plugin, "jabber-unregister-namespace-watcher",
-			plugin, PURPLE_CALLBACK(jabber_iq_signal_unregister), NULL);
-
-
-	purple_signal_register(plugin, "jabber-receiving-xmlnode",
+	purple_signal_connect(protocol, "jabber-register-namespace-watcher",
+			protocol, PURPLE_CALLBACK(jabber_iq_signal_register), NULL);
+	purple_signal_connect(protocol, "jabber-unregister-namespace-watcher",
+			protocol, PURPLE_CALLBACK(jabber_iq_signal_unregister), NULL);
+
+
+	purple_signal_register(protocol, "jabber-receiving-xmlnode",
 			purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
 			PURPLE_TYPE_CONNECTION,
 			G_TYPE_POINTER); /* modifiable xmlnode */
 
-	purple_signal_register(plugin, "jabber-sending-xmlnode",
+	purple_signal_register(protocol, "jabber-sending-xmlnode",
 			purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
 			PURPLE_TYPE_CONNECTION,
 			G_TYPE_POINTER); /* modifiable xmlnode */
@@ -3996,16 +3999,16 @@
 	 * Do not remove this or the plugin will fail. Completely. You have been
 	 * warned!
 	 */
-	purple_signal_connect_priority(plugin, "jabber-sending-xmlnode",
-			plugin, PURPLE_CALLBACK(jabber_send_signal_cb),
+	purple_signal_connect_priority(protocol, "jabber-sending-xmlnode",
+			protocol, PURPLE_CALLBACK(jabber_send_signal_cb),
 			NULL, PURPLE_SIGNAL_PRIORITY_HIGHEST);
 
-	purple_signal_register(plugin, "jabber-sending-text",
+	purple_signal_register(protocol, "jabber-sending-text",
 			     purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2,
 			     PURPLE_TYPE_CONNECTION,
 			     G_TYPE_POINTER); /* pointer to a string */
 
-	purple_signal_register(plugin, "jabber-receiving-message",
+	purple_signal_register(protocol, "jabber-receiving-message",
 			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER,
 			G_TYPE_BOOLEAN, 6,
 			PURPLE_TYPE_CONNECTION,
@@ -4015,7 +4018,7 @@
 			G_TYPE_STRING, /* to */
 			PURPLE_TYPE_XMLNODE);
 
-	purple_signal_register(plugin, "jabber-receiving-iq",
+	purple_signal_register(protocol, "jabber-receiving-iq",
 			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
 			G_TYPE_BOOLEAN, 5,
 			PURPLE_TYPE_CONNECTION,
@@ -4024,7 +4027,7 @@
 			G_TYPE_STRING, /* from */
 			PURPLE_TYPE_XMLNODE);
 
-	purple_signal_register(plugin, "jabber-watched-iq",
+	purple_signal_register(protocol, "jabber-watched-iq",
 			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
 			G_TYPE_BOOLEAN, 5,
 			PURPLE_TYPE_CONNECTION,
@@ -4033,7 +4036,7 @@
 			G_TYPE_STRING, /* from */
 			PURPLE_TYPE_XMLNODE); /* child */
 
-	purple_signal_register(plugin, "jabber-receiving-presence",
+	purple_signal_register(protocol, "jabber-receiving-presence",
 			purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER,
 			G_TYPE_BOOLEAN, 4,
 			PURPLE_TYPE_CONNECTION,
@@ -4042,14 +4045,15 @@
 			PURPLE_TYPE_XMLNODE);
 }
 
-void jabber_plugin_uninit(PurplePlugin *plugin)
+void jabber_plugin_uninit(PurpleProtocol *protocol)
 {
 	g_return_if_fail(plugin_ref > 0);
 
-	purple_signals_unregister_by_instance(plugin);
+	purple_signals_unregister_by_instance(protocol);
+#if 0
 	purple_plugin_ipc_unregister_all(plugin);
-
-	jabber_unregister_commands(plugin);
+#endif
+	jabber_unregister_commands(protocol);
 
 	--plugin_ref;
 	if (plugin_ref == 0)
--- a/libpurple/protocols/jabber/jabber.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/jabber.h	Sun Aug 18 01:53:00 2013 +0530
@@ -402,8 +402,8 @@
 void jabber_convo_closed(PurpleConnection *gc, const char *who);
 PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name);
 gboolean jabber_offline_message(const PurpleBuddy *buddy);
-int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len);
-GList *jabber_actions(PurplePlugin *plugin, gpointer context);
+int jabber_protocol_send_raw(PurpleConnection *gc, const char *buf, int len);
+GList *jabber_get_actions(PurpleConnection *gc);
 
 gboolean jabber_audio_enabled(JabberStream *js, const char *unused);
 gboolean jabber_video_enabled(JabberStream *js, const char *unused);
@@ -412,7 +412,7 @@
 PurpleMediaCaps jabber_get_media_caps(PurpleAccount *account, const char *who);
 gboolean jabber_can_receive_file(PurpleConnection *gc, const gchar *who);
 
-void jabber_plugin_init(PurplePlugin *plugin);
-void jabber_plugin_uninit(PurplePlugin *plugin);
+void jabber_plugin_init(PurpleProtocol *protocol);
+void jabber_plugin_uninit(PurpleProtocol *protocol);
 
 #endif /* PURPLE_JABBER_H_ */
--- a/libpurple/protocols/jabber/jingle/rtp.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/jingle/rtp.c	Sun Aug 18 01:53:00 2013 +0530
@@ -215,7 +215,7 @@
 
 	for (; iter; iter = g_list_delete_link(iter, iter)) {
 		JingleSession *media_session =
-				purple_media_get_prpl_data(iter->data);
+				purple_media_get_protocol_data(iter->data);
 		if (media_session == session) {
 			media = iter->data;
 			break;
@@ -425,7 +425,7 @@
 		return NULL;
 	}
 
-	purple_media_set_prpl_data(media, session);
+	purple_media_set_protocol_data(media, session);
 
 	/* connect callbacks */
 	g_signal_connect(G_OBJECT(media), "candidates-prepared",
--- a/libpurple/protocols/jabber/libfacebook.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/libfacebook.c	Sun Aug 18 01:53:00 2013 +0530
@@ -40,6 +40,7 @@
 #include "roster.h"
 #include "si.h"
 #include "message.h"
+#include "plugins.h"
 #include "presence.h"
 #include "google/google.h"
 #include "pep.h"
@@ -55,11 +56,13 @@
 	return "facebook";
 }
 
-static PurplePlugin *my_protocol = NULL;
+static PurpleProtocol *my_protocol = NULL;
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-facebook-xmpp",                   /* id */
+	"Facebook (XMPP)",                      /* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK |
 #ifdef HAVE_CYRUS_SASL
 	OPT_PROTO_PASSWORD_OPTIONAL |
@@ -68,6 +71,7 @@
 	NULL,							/* user_splits */
 	NULL,							/* protocol_options */
 	{"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+	jabber_get_actions,				/* get_actions */
 	facebook_list_icon,				/* list_icon */
 	jabber_list_emblem,			/* list_emblems */
 	jabber_status_text,				/* status_text */
@@ -122,8 +126,8 @@
 	NULL,							/* send_file */
 	NULL,							/* new_xfer */
 	jabber_offline_message,			/* offline_message */
-	NULL,							/* whiteboard_prpl_ops */
-	jabber_prpl_send_raw,			/* send_raw */
+	NULL,							/* whiteboard_protocol_ops */
+	jabber_protocol_send_raw,			/* send_raw */
 	jabber_roomlist_room_serialize, /* roomlist_room_serialize */
 	NULL,							/* unregister_user */
 	NULL,							/* send_attention */
@@ -136,57 +140,6 @@
 	NULL  /* get_public_alias */
 };
 
-static gboolean load_plugin(PurplePlugin *plugin)
-{
-	jabber_plugin_init(plugin);
-
-	return TRUE;
-}
-
-static gboolean unload_plugin(PurplePlugin *plugin)
-{
-	jabber_plugin_uninit(plugin);
-
-	return TRUE;
-}
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                         /**< type           */
-	NULL,                                           /**< ui_requirement */
-	0,                                              /**< flags          */
-	NULL,                                           /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                        /**< priority       */
-
-	"prpl-facebook-xmpp",                           /**< id             */
-	"Facebook (XMPP)",                              /**< name           */
-	DISPLAY_VERSION,                                /**< version        */
-	                                                /**  summary        */
-	N_("Facebook XMPP Protocol Plugin"),
-	                                                /**  description    */
-	N_("Facebook XMPP Protocol Plugin"),
-	NULL,                                           /**< author         */
-	PURPLE_WEBSITE,                                 /**< homepage       */
-
-	load_plugin,                                    /**< load           */
-	unload_plugin,                                  /**< unload         */
-	NULL,                                           /**< destroy        */
-
-	NULL,                                           /**< ui_info        */
-	&prpl_info,                                     /**< extra_info     */
-	NULL,                                           /**< prefs_info     */
-	jabber_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
 static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
 {
 	PurpleAccount *acct = NULL;
@@ -219,7 +172,7 @@
 	if (g_ascii_strcasecmp(proto, "xmpp"))
 		return FALSE;
 
-	acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
+	acct = find_acct(my_protocol->id, acct_id);
 
 	if (!acct)
 		return FALSE;
@@ -251,9 +204,26 @@
 	return FALSE;
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-facebook-xmpp",
+		"name",         "Facebook (XMPP)",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Facebook XMPP Protocol Plugin"),
+		"description",  N_("Facebook XMPP Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountUserSplit *split;
 	PurpleAccountOption *option;
@@ -262,11 +232,11 @@
 	/* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
 	split = purple_account_user_split_new(_("Domain"), "chat.facebook.com", '@');
 	purple_account_user_split_set_reverse(split, FALSE);
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 	split = purple_account_user_split_new(_("Resource"), "", '/');
 	purple_account_user_split_set_reverse(split, FALSE);
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 #define ADD_VALUE(list, desc, v) { \
 	PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
@@ -286,41 +256,55 @@
 #undef ADD_VALUE
 
 	option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_bool_new(
 						_("Allow plaintext auth over unencrypted streams"),
 						"auth_plain_in_clear", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_int_new(_("Connect port"), "port", 5222);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_string_new(_("Connect server"),
 						  "connect_server", NULL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	option = purple_account_option_string_new(_("BOSH URL"),
 						  "bosh_url", NULL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	/* this should probably be part of global smiley theme settings later on,
 	  shared with MSN */
 	option = purple_account_option_bool_new(_("Show Custom Smileys"),
 		"custom_smileys", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 		option);
 
-	my_protocol = plugin;
+	my_protocol = &protocol;
+
+	purple_signal_connect(purple_get_core(), "uri-handler", my_protocol,
+		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
 
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
+	purple_protocols_add(my_protocol);
+	jabber_plugin_init(my_protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(facebookxmpp, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	jabber_plugin_uninit(my_protocol);
+	purple_protocols_remove(my_protocol);
 
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(facebookxmpp, plugin_query, plugin_load, plugin_unload);
+
--- a/libpurple/protocols/jabber/libgtalk.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/libgtalk.c	Sun Aug 18 01:53:00 2013 +0530
@@ -40,6 +40,7 @@
 #include "roster.h"
 #include "si.h"
 #include "message.h"
+#include "plugins.h"
 #include "presence.h"
 #include "google/google.h"
 #include "pep.h"
@@ -55,11 +56,13 @@
 	return "google-talk";
 }
 
-static PurplePlugin *my_protocol = NULL;
+static PurpleProtocol *my_protocol = NULL;
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-gtalk",                           /* id */
+	"Google Talk (XMPP)",                   /* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK |
 #ifdef HAVE_CYRUS_SASL
 	OPT_PROTO_PASSWORD_OPTIONAL |
@@ -68,6 +71,7 @@
 	NULL,							/* user_splits */
 	NULL,							/* protocol_options */
 	{"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+	jabber_get_actions,				/* get_actions */
 	gtalk_list_icon,				/* list_icon */
 	jabber_list_emblem,			/* list_emblems */
 	jabber_status_text,				/* status_text */
@@ -122,8 +126,8 @@
 	jabber_si_xfer_send,			/* send_file */
 	jabber_si_new_xfer,				/* new_xfer */
 	jabber_offline_message,			/* offline_message */
-	NULL,							/* whiteboard_prpl_ops */
-	jabber_prpl_send_raw,			/* send_raw */
+	NULL,							/* whiteboard_protocol_ops */
+	jabber_protocol_send_raw,			/* send_raw */
 	jabber_roomlist_room_serialize, /* roomlist_room_serialize */
 	NULL,							/* unregister_user */
 	jabber_send_attention,			/* send_attention */
@@ -136,57 +140,6 @@
 	NULL  /* get_public_alias */
 };
 
-static gboolean load_plugin(PurplePlugin *plugin)
-{
-	jabber_plugin_init(plugin);
-
-	return TRUE;
-}
-
-static gboolean unload_plugin(PurplePlugin *plugin)
-{
-	jabber_plugin_uninit(plugin);
-
-	return TRUE;
-}
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                         /**< type           */
-	NULL,                                           /**< ui_requirement */
-	0,                                              /**< flags          */
-	NULL,                                           /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                        /**< priority       */
-
-	"prpl-gtalk",                                   /**< id             */
-	"Google Talk (XMPP)",                           /**< name           */
-	DISPLAY_VERSION,                                /**< version        */
-	                                                /**  summary        */
-	N_("Google Talk Protocol Plugin"),
-	                                                /**  description    */
-	N_("Google Talk Protocol Plugin"),
-	NULL,                                           /**< author         */
-	PURPLE_WEBSITE,                                 /**< homepage       */
-
-	load_plugin,                                    /**< load           */
-	unload_plugin,                                  /**< unload         */
-	NULL,                                           /**< destroy        */
-
-	NULL,                                           /**< ui_info        */
-	&prpl_info,                                     /**< extra_info     */
-	NULL,                                           /**< prefs_info     */
-	jabber_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
 static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
 {
 	PurpleAccount *acct = NULL;
@@ -219,7 +172,7 @@
 	if (g_ascii_strcasecmp(proto, "xmpp"))
 		return FALSE;
 
-	acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
+	acct = find_acct(my_protocol->id, acct_id);
 
 	if (!acct)
 		return FALSE;
@@ -251,9 +204,26 @@
 	return FALSE;
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-gtalk",
+		"name",         "Google Talk (XMPP)",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Google Talk Protocol Plugin"),
+		"description",  N_("Google Talk Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountUserSplit *split;
 	PurpleAccountOption *option;
@@ -262,11 +232,11 @@
 	/* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
 	split = purple_account_user_split_new(_("Domain"), "gmail.com", '@');
 	purple_account_user_split_set_reverse(split, FALSE);
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 	split = purple_account_user_split_new(_("Resource"), "", '/');
 	purple_account_user_split_set_reverse(split, FALSE);
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 #define ADD_VALUE(list, desc, v) { \
 	PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
@@ -286,22 +256,22 @@
 #undef ADD_VALUE
 
 	option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_bool_new(
 						_("Allow plaintext auth over unencrypted streams"),
 						"auth_plain_in_clear", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_int_new(_("Connect port"), "port", 5222);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_string_new(_("Connect server"),
 						  "connect_server", NULL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	option = purple_account_option_string_new(_("File transfer proxies"),
@@ -309,26 +279,40 @@
 						/* TODO: Is this an acceptable default?
 						 * Also, keep this in sync as they add more servers */
 						  JABBER_DEFAULT_FT_PROXIES);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	option = purple_account_option_string_new(_("BOSH URL"),
 						  "bosh_url", NULL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	/* this should probably be part of global smiley theme settings later on,
 	  shared with MSN */
 	option = purple_account_option_bool_new(_("Show Custom Smileys"),
 		"custom_smileys", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 		option);
 
-	my_protocol = plugin;
+	my_protocol = &protocol;
+
+	purple_signal_connect(purple_get_core(), "uri-handler", my_protocol,
+		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
 
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
+	purple_protocols_add(my_protocol);
+	jabber_plugin_init(my_protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(gtalk, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	jabber_plugin_uninit(my_protocol);
+	purple_protocols_remove(my_protocol);
 
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(gtalk, plugin_query, plugin_load, plugin_unload);
+
--- a/libpurple/protocols/jabber/libxmpp.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/libxmpp.c	Sun Aug 18 01:53:00 2013 +0530
@@ -40,6 +40,7 @@
 #include "roster.h"
 #include "si.h"
 #include "message.h"
+#include "plugins.h"
 #include "presence.h"
 #include "google/google.h"
 #include "pep.h"
@@ -49,11 +50,13 @@
 #include "data.h"
 #include "ibb.h"
 
-static PurplePlugin *my_protocol = NULL;
+static PurpleProtocol *my_protocol = NULL;
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-jabber",                          /* id */
+	"XMPP",                                 /* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK |
 #ifdef HAVE_CYRUS_SASL
 	OPT_PROTO_PASSWORD_OPTIONAL |
@@ -62,6 +65,7 @@
 	NULL,							/* user_splits */
 	NULL,							/* protocol_options */
 	{"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+	jabber_get_actions,				/* get_actions */
 	jabber_list_icon,				/* list_icon */
 	jabber_list_emblem,			/* list_emblems */
 	jabber_status_text,				/* status_text */
@@ -116,8 +120,8 @@
 	jabber_si_xfer_send,			/* send_file */
 	jabber_si_new_xfer,				/* new_xfer */
 	jabber_offline_message,			/* offline_message */
-	NULL,							/* whiteboard_prpl_ops */
-	jabber_prpl_send_raw,			/* send_raw */
+	NULL,							/* whiteboard_protocol_ops */
+	jabber_protocol_send_raw,			/* send_raw */
 	jabber_roomlist_room_serialize, /* roomlist_room_serialize */
 	jabber_unregister_account,		/* unregister_user */
 	jabber_send_attention,			/* send_attention */
@@ -130,57 +134,6 @@
 	NULL  /* get_public_alias */
 };
 
-static gboolean load_plugin(PurplePlugin *plugin)
-{
-	jabber_plugin_init(plugin);
-
-	return TRUE;
-}
-
-static gboolean unload_plugin(PurplePlugin *plugin)
-{
-	jabber_plugin_uninit(plugin);
-
-	return TRUE;
-}
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	"prpl-jabber",                                    /**< id             */
-	"XMPP",                                           /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("XMPP Protocol Plugin"),
-	                                                  /**  description    */
-	N_("XMPP Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	load_plugin,                                      /**< load           */
-	unload_plugin,                                    /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	jabber_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
 static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
 {
 	PurpleAccount *acct = NULL;
@@ -213,7 +166,7 @@
 	if (g_ascii_strcasecmp(proto, "xmpp"))
 		return FALSE;
 
-	acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
+	acct = find_acct(my_protocol->id, acct_id);
 
 	if (!acct)
 		return FALSE;
@@ -245,9 +198,26 @@
 	return FALSE;
 }
 
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-jabber",
+		"name",         "XMPP",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("XMPP Protocol Plugin"),
+		"description",  N_("XMPP Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountUserSplit *split;
 	PurpleAccountOption *option;
@@ -256,11 +226,11 @@
 	/* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
 	split = purple_account_user_split_new(_("Domain"), NULL, '@');
 	purple_account_user_split_set_reverse(split, FALSE);
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 	split = purple_account_user_split_new(_("Resource"), "", '/');
 	purple_account_user_split_set_reverse(split, FALSE);
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 #define ADD_VALUE(list, desc, v) { \
 	PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
@@ -280,22 +250,22 @@
 #undef ADD_VALUE
 
 	option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_bool_new(
 						_("Allow plaintext auth over unencrypted streams"),
 						"auth_plain_in_clear", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_int_new(_("Connect port"), "port", 5222);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						   option);
 
 	option = purple_account_option_string_new(_("Connect server"),
 						  "connect_server", NULL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	option = purple_account_option_string_new(_("File transfer proxies"),
@@ -303,28 +273,42 @@
 						/* TODO: Is this an acceptable default?
 						 * Also, keep this in sync as they add more servers */
 						  JABBER_DEFAULT_FT_PROXIES);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	option = purple_account_option_string_new(_("BOSH URL"),
 						  "bosh_url", NULL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 						  option);
 
 	/* this should probably be part of global smiley theme settings later on,
 	  shared with MSN */
 	option = purple_account_option_bool_new(_("Show Custom Smileys"),
 		"custom_smileys", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 		option);
 
-	my_protocol = plugin;
+	my_protocol = &protocol;
 
 	purple_prefs_remove("/plugins/prpl/jabber");
 
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+	purple_signal_connect(purple_get_core(), "uri-handler", my_protocol,
 		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
+
+	purple_protocols_add(my_protocol);
+	jabber_plugin_init(my_protocol);
+
+	return TRUE;
 }
 
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	jabber_plugin_uninit(my_protocol);
+	purple_protocols_remove(my_protocol);
 
-PURPLE_INIT_PLUGIN(jabber, init_plugin, info);
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(jabber, plugin_query, plugin_load, plugin_unload);
+
--- a/libpurple/protocols/jabber/message.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/message.c	Sun Aug 18 01:53:00 2013 +0530
@@ -313,7 +313,7 @@
 		return; /* Do not accept buzzes from unknown people */
 
 	/* xmpp only has 1 attention type, so index is 0 */
-	purple_prpl_got_attention(jm->js->gc, jm->from, 0);
+	purple_protocol_got_attention(jm->js->gc, jm->from, 0);
 }
 
 /* used internally by the functions below */
@@ -510,7 +510,7 @@
 	to   = xmlnode_get_attrib(packet, "to");
 	type = xmlnode_get_attrib(packet, "type");
 
-	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc),
+	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc),
 			"jabber-receiving-message", js->gc, type, id, from, to, packet));
 	if (signal_return)
 		return;
--- a/libpurple/protocols/jabber/presence.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/presence.c	Sun Aug 18 01:53:00 2013 +0530
@@ -133,14 +133,14 @@
 	if (purple_blist_find_buddy(account, username)) {
 		jbr = jabber_buddy_find_resource(jb, NULL);
 		if (jbr) {
-			purple_prpl_got_user_status(account, username,
+			purple_protocol_got_user_status(account, username,
 					jabber_buddy_state_get_status_id(jbr->state),
 					"priority", jbr->priority,
 					jbr->status ? "message" : NULL, jbr->status,
 					NULL);
-			purple_prpl_got_user_idle(account, username, jbr->idle, jbr->idle);
+			purple_protocol_got_user_idle(account, username, jbr->idle, jbr->idle);
 		} else {
-			purple_prpl_got_user_status(account, username, "offline",
+			purple_protocol_got_user_status(account, username, "offline",
 					msg ? "message" : NULL, msg,
 					NULL);
 		}
@@ -502,7 +502,7 @@
 	jbr->caps.info = info;
 	jbr->caps.exts = exts;
 
-	purple_prpl_got_media_caps(
+	purple_protocol_got_media_caps(
 			purple_connection_get_account(userdata->js->gc),
 			userdata->from);
 	if (info == NULL)
@@ -878,17 +878,17 @@
 	jbr = jabber_buddy_find_resource(presence->jb, NULL);
 	if (jbr) {
 		jabber_google_presence_incoming(js, buddy_name, jbr);
-		purple_prpl_got_user_status(account, buddy_name,
+		purple_protocol_got_user_status(account, buddy_name,
 				jabber_buddy_state_get_status_id(jbr->state),
 				"priority", jbr->priority,
 				"message", jbr->status,
 				NULL);
-		purple_prpl_got_user_idle(account, buddy_name,
+		purple_protocol_got_user_idle(account, buddy_name,
 				jbr->idle, jbr->idle);
 		if (presence->nickname)
 			serv_got_alias(js->gc, buddy_name, presence->nickname);
 	} else {
-		purple_prpl_got_user_status(account, buddy_name,
+		purple_protocol_got_user_status(account, buddy_name,
 				jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE),
 				presence->status ? "message" : NULL, presence->status,
 				NULL);
@@ -926,7 +926,7 @@
 		return;
 	}
 
-	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc),
+	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc),
 			"jabber-receiving-presence", js->gc, type, presence.from, packet));
 	if (signal_return) {
 		goto out;
--- a/libpurple/protocols/jabber/roster.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/roster.c	Sun Aug 18 01:53:00 2013 +0530
@@ -413,7 +413,7 @@
 	} else if(!jb || !(jb->subscription & JABBER_SUB_TO)) {
 		jabber_presence_subscription_set(js, who, "subscribe");
 	} else if((jbr =jabber_buddy_find_resource(jb, NULL))) {
-		purple_prpl_got_user_status(purple_connection_get_account(gc), who,
+		purple_protocol_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);
 	}
--- a/libpurple/protocols/jabber/si.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/si.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1012,7 +1012,7 @@
 		purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n",
 			size);
 		purple_circular_buffer_append(jsx->ibb_buffer, data, size);
-		purple_xfer_prpl_ready(xfer);
+		purple_xfer_protocol_ready(xfer);
 	} else {
 		/* trying to write past size of file transfers negotiated size,
 		  reject transfer to protect against malicious behaviour */
@@ -1117,7 +1117,7 @@
 		purple_xfer_end(xfer);
 	} else {
 		/* send more... */
-		purple_xfer_prpl_ready(xfer);
+		purple_xfer_protocol_ready(xfer);
 	}
 }
 
@@ -1128,7 +1128,7 @@
 
 	if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) {
 		purple_xfer_start(xfer, -1, NULL, 0);
-		purple_xfer_prpl_ready(xfer);
+		purple_xfer_protocol_ready(xfer);
 	} else {
 		/* error */
 		purple_xfer_end(xfer);
--- a/libpurple/protocols/jabber/usermood.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/usermood.c	Sun Aug 18 01:53:00 2013 +0530
@@ -167,12 +167,12 @@
 			break;
 	}
 	if (newmood != NULL) {
-		purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "mood",
+		purple_protocol_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(purple_connection_get_account(js->gc), from, "mood");
+		purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), from, "mood");
 	}
 	g_free(moodtext);
 }
--- a/libpurple/protocols/jabber/usernick.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/usernick.c	Sun Aug 18 01:53:00 2013 +0530
@@ -85,8 +85,8 @@
 	g_free(oldnickname);
 }
 
-static void do_nick_set_nick(PurplePluginAction *action) {
-	PurpleConnection *gc = action->context;
+static void do_nick_set_nick(PurpleProtocolAction *action) {
+	PurpleConnection *gc = action->connection;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	/* since the nickname might have been changed by another resource of this account, we always have to request the old one
@@ -100,6 +100,6 @@
 }
 
 void jabber_nick_init_action(GList **m) {
-	PurplePluginAction *act = purple_plugin_action_new(_("Set Nickname..."), do_nick_set_nick);
+	PurpleProtocolAction *act = purple_protocol_action_new(_("Set Nickname..."), do_nick_set_nick);
 	*m = g_list_append(*m, act);
 }
--- a/libpurple/protocols/jabber/usertune.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/jabber/usertune.c	Sun Aug 18 01:53:00 2013 +0530
@@ -92,7 +92,7 @@
 	}
 
 	if (valid) {
-		purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "tune",
+		purple_protocol_got_user_status(purple_connection_get_account(js->gc), from, "tune",
 				PURPLE_TUNE_ARTIST, tuneinfodata.artist,
 				PURPLE_TUNE_TITLE, tuneinfodata.title,
 				PURPLE_TUNE_ALBUM, tuneinfodata.album,
@@ -100,7 +100,7 @@
 				PURPLE_TUNE_TIME, tuneinfodata.time,
 				PURPLE_TUNE_URL, tuneinfodata.url, NULL);
 	} else {
-		purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), from, "tune");
+		purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), from, "tune");
 	}
 
 	g_free(tuneinfodata.artist);
--- a/libpurple/protocols/msn/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -99,4 +99,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/msn/contact.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/contact.c	Sun Aug 18 01:53:00 2013 +0530
@@ -853,8 +853,8 @@
 		if (mobile && user)
 		{
 			user->mobile = TRUE;
-			purple_prpl_got_user_status(session->account, user->passport, "mobile", NULL);
-			purple_prpl_got_user_status(session->account, user->passport, "available", NULL);
+			purple_protocol_got_user_status(session->account, user->passport, "mobile", NULL);
+			purple_protocol_got_user_status(session->account, user->passport, "available", NULL);
 		}
 		if (alias)
 			purple_serv_got_private_alias(pc, passport, alias);
--- a/libpurple/protocols/msn/msg.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/msg.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1036,12 +1036,12 @@
 			if (swboard->current_users > 1 ||
 				((swboard->conv != NULL) &&
 				 PURPLE_IS_CHAT_CONVERSATION(swboard->conv)))
-				purple_prpl_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE);
+				purple_protocol_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE);
 
 			else
-				purple_prpl_got_attention(gc, user, MSN_NUDGE);
+				purple_protocol_got_attention(gc, user, MSN_NUDGE);
 		} else {
-			purple_prpl_got_attention(gc, user, MSN_NUDGE);
+			purple_protocol_got_attention(gc, user, MSN_NUDGE);
 		}
 
 	} else if (!strcmp(id, "2")) {
--- a/libpurple/protocols/msn/msn.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/msn.c	Sun Aug 18 01:53:00 2013 +0530
@@ -33,7 +33,7 @@
 #include "contact.h"
 #include "msg.h"
 #include "page.h"
-#include "pluginpref.h"
+#include "plugins.h"
 #include "prefs.h"
 #include "session.h"
 #include "smiley.h"
@@ -41,7 +41,7 @@
 #include "util.h"
 #include "cmds.h"
 #include "core.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "msnutils.h"
 #include "version.h"
 
@@ -163,7 +163,7 @@
 
 	username = purple_conversation_get_name(conv);
 
-	purple_prpl_send_attention(gc, username, MSN_NUDGE);
+	purple_protocol_send_attention(gc, username, MSN_NUDGE);
 
 	return PURPLE_CMD_RET_OK;
 }
@@ -434,13 +434,13 @@
 /* -- */
 
 static void
-msn_show_set_friendly_name(PurplePluginAction *action)
+msn_show_set_friendly_name(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 	PurpleAccount *account;
 	char *tmp;
 
-	gc = (PurpleConnection *) action->context;
+	gc = action->connection;
 	account = purple_connection_get_account(gc);
 
 	tmp = g_strdup_printf(_("Set friendly name for %s."),
@@ -504,7 +504,7 @@
 }
 
 static void
-msn_show_locations(PurplePluginAction *action)
+msn_show_locations(PurpleProtocolAction *action)
 {
 	PurpleConnection *pc;
 	PurpleAccount *account;
@@ -516,7 +516,7 @@
 	GSList *l;
 	MsnLocationData *data;
 
-	pc = (PurpleConnection *)action->context;
+	pc = action->connection;
 	account = purple_connection_get_account(pc);
 	session = purple_connection_get_protocol_data(pc);
 
@@ -590,7 +590,7 @@
 	session->enable_mpop = TRUE;
 	msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL);
 
-	purple_prpl_got_account_actions(purple_connection_get_account(pc));
+	purple_protocol_got_account_actions(purple_connection_get_account(pc));
 }
 
 static void
@@ -620,15 +620,15 @@
 		g_free(user);
 	}
 
-	purple_prpl_got_account_actions(account);
+	purple_protocol_got_account_actions(account);
 }
 
 static void
-msn_show_set_mpop(PurplePluginAction *action)
+msn_show_set_mpop(PurpleProtocolAction *action)
 {
 	PurpleConnection *pc;
 
-	pc = (PurpleConnection *)action->context;
+	pc = action->connection;
 
 	purple_request_action(pc, NULL, _("Allow multiple logins?"),
 						_("Do you want to allow or disallow connecting from "
@@ -642,12 +642,12 @@
 }
 
 static void
-msn_show_set_home_phone(PurplePluginAction *action)
+msn_show_set_home_phone(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 	MsnSession *session;
 
-	gc = (PurpleConnection *) action->context;
+	gc = action->connection;
 	session = purple_connection_get_protocol_data(gc);
 
 	purple_request_input(gc, NULL, _("Set your home phone number."), NULL,
@@ -659,12 +659,12 @@
 }
 
 static void
-msn_show_set_work_phone(PurplePluginAction *action)
+msn_show_set_work_phone(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 	MsnSession *session;
 
-	gc = (PurpleConnection *) action->context;
+	gc = action->connection;
 	session = purple_connection_get_protocol_data(gc);
 
 	purple_request_input(gc, NULL, _("Set your work phone number."), NULL,
@@ -676,12 +676,12 @@
 }
 
 static void
-msn_show_set_mobile_phone(PurplePluginAction *action)
+msn_show_set_mobile_phone(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 	MsnSession *session;
 
-	gc = (PurpleConnection *) action->context;
+	gc = action->connection;
 	session = purple_connection_get_protocol_data(gc);
 
 	purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
@@ -693,11 +693,11 @@
 }
 
 static void
-msn_show_set_mobile_pages(PurplePluginAction *action)
+msn_show_set_mobile_pages(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 
-	gc = (PurpleConnection *) action->context;
+	gc = action->connection;
 
 	purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"),
 						_("Do you want to allow or disallow people on "
@@ -714,9 +714,9 @@
 /* QuLogic: Disabled until confirmed correct. */
 #if 0
 static void
-msn_show_blocked_text(PurplePluginAction *action)
+msn_show_blocked_text(PurpleProtocolAction *action)
 {
-	PurpleConnection *pc = (PurpleConnection *) action->context;
+	PurpleConnection *pc = action->connection;
 	MsnSession *session;
 	char *title;
 
@@ -738,12 +738,12 @@
 #endif
 
 static void
-msn_show_hotmail_inbox(PurplePluginAction *action)
+msn_show_hotmail_inbox(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 	MsnSession *session;
 
-	gc = (PurpleConnection *) action->context;
+	gc = action->connection;
 	session = purple_connection_get_protocol_data(gc);
 
 	if (!session->passport_info.email_enabled) {
@@ -1210,66 +1210,64 @@
 }
 
 static GList *
-msn_actions(PurplePlugin *plugin, gpointer context)
+msn_get_actions(PurpleConnection *gc)
 {
-	PurpleConnection *gc;
 	MsnSession *session;
 	GList *m = NULL;
-	PurplePluginAction *act;
-
-	gc = (PurpleConnection *) context;
+	PurpleProtocolAction *act;
+
 	session = purple_connection_get_protocol_data(gc);
 
-	act = purple_plugin_action_new(_("Set Friendly Name..."),
+	act = purple_protocol_action_new(_("Set Friendly Name..."),
 								 msn_show_set_friendly_name);
 	m = g_list_append(m, act);
 	m = g_list_append(m, NULL);
 
 	if (session->enable_mpop)
 	{
-		act = purple_plugin_action_new(_("View Locations..."),
+		act = purple_protocol_action_new(_("View Locations..."),
 		                               msn_show_locations);
 		m = g_list_append(m, act);
 		m = g_list_append(m, NULL);
 	}
 
-	act = purple_plugin_action_new(_("Set Home Phone Number..."),
+	act = purple_protocol_action_new(_("Set Home Phone Number..."),
 								 msn_show_set_home_phone);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Set Work Phone Number..."),
+	act = purple_protocol_action_new(_("Set Work Phone Number..."),
 			msn_show_set_work_phone);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Set Mobile Phone Number..."),
+	act = purple_protocol_action_new(_("Set Mobile Phone Number..."),
 			msn_show_set_mobile_phone);
 	m = g_list_append(m, act);
 	m = g_list_append(m, NULL);
 
 #if 0
-	act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."),
+	act = purple_protocol_action_new(_("Enable/Disable Mobile Devices..."),
 			msn_show_set_mobile_support);
 	m = g_list_append(m, act);
 #endif
 
-	act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."),
+	act = purple_protocol_action_new(_("Allow/Disallow Multiple Logins..."),
 			msn_show_set_mpop);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."),
+	act = purple_protocol_action_new(_("Allow/Disallow Mobile Pages..."),
 			msn_show_set_mobile_pages);
 	m = g_list_append(m, act);
 
 /* QuLogic: Disabled until confirmed correct. */
 #if 0
 	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("View Blocked Text..."),
+	act = purple_protocol_action_new(_("View Blocked Text..."),
 			msn_show_blocked_text);
 	m = g_list_append(m, act);
 #endif
 
 	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("Open Hotmail Inbox"),
+	act = purple_protocol_action_new(_("Open Hotmail Inbox"),
 			msn_show_hotmail_inbox);
 	m = g_list_append(m, act);
 
@@ -2803,22 +2801,6 @@
 			PROFILE_URL, name));
 }
 
-static gboolean msn_load(PurplePlugin *plugin)
-{
-	msn_notification_init();
-	msn_switchboard_init();
-
-	return TRUE;
-}
-
-static gboolean msn_unload(PurplePlugin *plugin)
-{
-	msn_notification_end();
-	msn_switchboard_end();
-
-	return TRUE;
-}
-
 static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
 {
 	PurpleAccount *acct = NULL;
@@ -2884,13 +2866,16 @@
 }
 
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),	/* struct_size */
+	"prpl-msn",                         /* id */
+	"MSN",                              /* name */
+	sizeof(PurpleProtocol),	/* struct_size */
 	OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE,
 	NULL,                               /* user_splits */
 	NULL,                               /* protocol_options */
 	{"png,gif", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND},   /* icon_spec */
+	msn_get_actions,                    /* get_actions */
 	msn_list_icon,                      /* list_icon */
 	msn_list_emblems,                   /* list_emblems */
 	msn_status_text,                    /* status_text */
@@ -2945,7 +2930,7 @@
 	msn_send_file,                      /* send_file */
 	msn_new_xfer,                       /* new_xfer */
 	msn_offline_message,                /* offline_message */
-	NULL,                               /* whiteboard_prpl_ops */
+	NULL,                               /* whiteboard_protocol_ops */
 	NULL,                               /* send_raw */
 	NULL,                               /* roomlist_room_serialize */
 	NULL,                               /* unregister_user */
@@ -2959,89 +2944,90 @@
 	msn_get_public_alias                /* get_public_alias */
 };
 
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                           /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                          /**< priority       */
-
-	"prpl-msn",                                       /**< id             */
-	"MSN",                                            /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	N_("Windows Live Messenger Protocol Plugin"),     /**< summary        */
-	N_("Windows Live Messenger Protocol Plugin"),     /**< description    */
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                   /**< homepage       */
-
-	msn_load,                                         /**< load           */
-	msn_unload,                                       /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	msn_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
+	return purple_plugin_info_new(
+		"id",           "prpl-msn",
+		"name",         "MSN",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Windows Live Messenger Protocol Plugin"),
+		"description",  N_("Windows Live Messenger Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 
 	option = purple_account_option_string_new(_("Server"), "server",
 											MSN_SERVER);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
 	option = purple_account_option_int_new(_("Port"), "port", MSN_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
 	option = purple_account_option_bool_new(_("Use HTTP Method"),
 										  "http_method", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
 	option = purple_account_option_string_new(_("HTTP Method Server"),
 										  "http_method_server", MSN_HTTPCONN_SERVER);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
 	option = purple_account_option_bool_new(_("Show custom smileys"),
 										  "custom_smileys", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
 	option = purple_account_option_bool_new(_("Allow direct connections"),
 										  "direct_connect", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
 	option = purple_account_option_bool_new(_("Allow connecting from multiple locations"),
 										  "mpop", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+	protocol.protocol_options = g_list_append(protocol.protocol_options,
 											   option);
 
-	purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("nudge", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                 "prpl-msn", msn_cmd_nudge,
 	                  _("nudge: nudge a user to get their attention"), NULL);
 
 	purple_prefs_remove("/plugins/prpl/msn");
 
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+	purple_signal_connect(purple_get_core(), "uri-handler", &protocol,
 		PURPLE_CALLBACK(msn_uri_handler), NULL);
+
+	msn_notification_init();
+	msn_switchboard_init();
+
+	purple_protocols_add(&protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(msn, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	msn_notification_end();
+	msn_switchboard_end();
+
+	purple_protocols_remove(&protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(msn, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/msn/slplink.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/slplink.c	Sun Aug 18 01:53:00 2013 +0530
@@ -538,7 +538,7 @@
 	if (slpmsg->ft) {
 		slpmsg->slpcall->u.incoming_data =
 				g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size);
-		purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+		purple_xfer_protocol_ready(slpmsg->slpcall->xfer);
 	}
 	else if (slpmsg->size && slpmsg->buffer) {
 		guint64 offset = msn_p2p_info_get_offset(part->info);
--- a/libpurple/protocols/msn/slpmsg_part.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/slpmsg_part.c	Sun Aug 18 01:53:00 2013 +0530
@@ -190,7 +190,7 @@
 		if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
 		{
 			slpmsg->slpcall->xfer_msg = slpmsg;
-			purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+			purple_xfer_protocol_ready(slpmsg->slpcall->xfer);
 		}
 		else
 			msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
--- a/libpurple/protocols/msn/user.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/msn/user.c	Sun Aug 18 01:53:00 2013 +0530
@@ -130,34 +130,34 @@
 	offline = (user->status == NULL);
 
 	if (!offline) {
-		purple_prpl_got_user_status(account, user->passport, user->status,
+		purple_protocol_got_user_status(account, user->passport, user->status,
 				"message", user->statusline, NULL);
 	} else {
 		if (user->mobile) {
-			purple_prpl_got_user_status(account, user->passport, "mobile", NULL);
-			purple_prpl_got_user_status(account, user->passport, "available", NULL);
+			purple_protocol_got_user_status(account, user->passport, "mobile", NULL);
+			purple_protocol_got_user_status(account, user->passport, "available", NULL);
 		} else {
-			purple_prpl_got_user_status(account, user->passport, "offline", NULL);
+			purple_protocol_got_user_status(account, user->passport, "offline", NULL);
 		}
 	}
 
 	if (!offline || !user->mobile) {
-		purple_prpl_got_user_status_deactive(account, user->passport, "mobile");
+		purple_protocol_got_user_status_deactive(account, user->passport, "mobile");
 	}
 
 	if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) {
 		if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) {
-			purple_prpl_got_user_status(account, user->passport, "tune",
+			purple_protocol_got_user_status(account, user->passport, "tune",
 			                            PURPLE_TUNE_ARTIST, user->extinfo->media_artist,
 			                            PURPLE_TUNE_ALBUM, user->extinfo->media_album,
 			                            PURPLE_TUNE_TITLE, user->extinfo->media_title,
 			                            NULL);
 		} else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) {
-			purple_prpl_got_user_status(account, user->passport, "tune",
+			purple_protocol_got_user_status(account, user->passport, "tune",
 			                            "game", user->extinfo->media_title,
 			                            NULL);
 		} else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) {
-			purple_prpl_got_user_status(account, user->passport, "tune",
+			purple_protocol_got_user_status(account, user->passport, "tune",
 			                            "office", user->extinfo->media_title,
 			                            NULL);
 		} else {
@@ -165,13 +165,13 @@
 			                     user->extinfo->media_type);
 		}
 	} else {
-		purple_prpl_got_user_status_deactive(account, user->passport, "tune");
+		purple_protocol_got_user_status_deactive(account, user->passport, "tune");
 	}
 
 	if (user->idle)
-		purple_prpl_got_user_idle(account, user->passport, TRUE, -1);
+		purple_protocol_got_user_idle(account, user->passport, TRUE, -1);
 	else
-		purple_prpl_got_user_idle(account, user->passport, FALSE, 0);
+		purple_protocol_got_user_idle(account, user->passport, FALSE, 0);
 }
 
 void
--- a/libpurple/protocols/mxit/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -12,6 +12,8 @@
 	chunk.h \
 	cipher.c \
 	cipher.h \
+	client.c \
+	client.h \
 	filexfer.c \
 	filexfer.h \
 	formcmds.c \
@@ -26,8 +28,6 @@
 	mxit.h \
 	profile.c \
 	profile.h \
-	protocol.c \
-	protocol.h \
 	roster.c \
 	roster.h \
 	splashscreen.c \
@@ -60,4 +60,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/mxit/actions.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/actions.c	Sun Aug 18 01:53:00 2013 +0530
@@ -27,7 +27,7 @@
 #include	"debug.h"
 #include	"request.h"
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"mxit.h"
 #include	"roster.h"
 #include	"actions.h"
@@ -207,9 +207,9 @@
  *
  *  @param action	The action object
  */
-static void mxit_profile_action( PurplePluginAction* action )
+static void mxit_profile_action( PurpleProtocolAction* action )
 {
-	PurpleConnection*			gc		= (PurpleConnection*) action->context;
+	PurpleConnection*			gc		= action->connection;
 	struct MXitSession*			session	= purple_connection_get_protocol_data( gc );
 	struct MXitProfile*			profile	= session->profile;
 
@@ -382,9 +382,9 @@
  *
  *  @param action	The action object
  */
-static void mxit_change_pin_action( PurplePluginAction* action )
+static void mxit_change_pin_action( PurpleProtocolAction* action )
 {
-	PurpleConnection*			gc		= (PurpleConnection*) action->context;
+	PurpleConnection*			gc		= action->connection;
 
 	PurpleRequestFields*		fields	= NULL;
 	PurpleRequestFieldGroup*	group	= NULL;
@@ -417,9 +417,9 @@
  *
  *  @param action	The action object
  */
-static void mxit_splash_action( PurplePluginAction* action )
+static void mxit_splash_action( PurpleProtocolAction* action )
 {
-	PurpleConnection*		gc		= (PurpleConnection*) action->context;
+	PurpleConnection*		gc		= action->connection;
 	struct MXitSession*		session	= purple_connection_get_protocol_data( gc );
 
 	if ( splash_current( session ) != NULL )
@@ -434,7 +434,7 @@
  *
  *  @param action	The action object
  */
-static void mxit_about_action( PurplePluginAction* action )
+static void mxit_about_action( PurpleProtocolAction* action )
 {
 	char	version[256];
 
@@ -454,9 +454,9 @@
  *
  *  @param action	The action object
  */
-static void mxit_suggested_friends_action( PurplePluginAction* action )
+static void mxit_suggested_friends_action( PurpleProtocolAction* action )
 {
-	PurpleConnection*		gc				= (PurpleConnection*) action->context;
+	PurpleConnection*		gc				= action->connection;
 	struct MXitSession*		session			= purple_connection_get_protocol_data( gc );
 	const char*				profilelist[]	= {
 				CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
@@ -489,9 +489,9 @@
  *
  *  @param action	The action object
  */
-static void mxit_user_search_action( PurplePluginAction* action )
+static void mxit_user_search_action( PurpleProtocolAction* action )
 {
-	PurpleConnection*		gc				= (PurpleConnection*) action->context;
+	PurpleConnection*		gc				= action->connection;
 
 	purple_request_input( gc, _( "Search for user" ),
 		_( "Search for a MXit contact" ),
@@ -507,37 +507,36 @@
 /*------------------------------------------------------------------------
  * Associate actions with the MXit plugin.
  *
- *  @param plugin	The MXit protocol plugin
- *  @param context	The connection context (if available)
+ *  @param gc		The connection
  *  @return			The list of plugin actions
  */
-GList* mxit_actions( PurplePlugin* plugin, gpointer context )
+GList* mxit_get_actions( PurpleConnection *gc )
 {
-	PurplePluginAction*		action	= NULL;
+	PurpleProtocolAction*		action	= NULL;
 	GList*					m		= NULL;
 
 	/* display / change profile */
-	action = purple_plugin_action_new( _( "Change Profile..." ), mxit_profile_action );
+	action = purple_protocol_action_new( _( "Change Profile..." ), mxit_profile_action );
 	m = g_list_append( m, action );
 
 	/* change PIN */
-	action = purple_plugin_action_new( _( "Change PIN..." ), mxit_change_pin_action );
+	action = purple_protocol_action_new( _( "Change PIN..." ), mxit_change_pin_action );
 	m = g_list_append( m, action );
 
 	/* suggested friends */
-	action = purple_plugin_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action );
+	action = purple_protocol_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action );
 	m = g_list_append( m, action );
 
 	/* search for contacts */
-	action = purple_plugin_action_new( _( "Search for contacts..." ), mxit_user_search_action );
+	action = purple_protocol_action_new( _( "Search for contacts..." ), mxit_user_search_action );
 	m = g_list_append( m, action );
 
 	/* display splash-screen */
-	action = purple_plugin_action_new( _( "View Splash..." ), mxit_splash_action );
+	action = purple_protocol_action_new( _( "View Splash..." ), mxit_splash_action );
 	m = g_list_append( m, action );
 
 	/* display plugin version */
-	action = purple_plugin_action_new( _( "About..." ), mxit_about_action );
+	action = purple_protocol_action_new( _( "About..." ), mxit_about_action );
 	m = g_list_append( m, action );
 
 	return m;
--- a/libpurple/protocols/mxit/actions.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/actions.h	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 
 
 /* callbacks */
-GList* mxit_actions( PurplePlugin* plugin, gpointer context );
+GList* mxit_get_actions( PurpleConnection *gc );
 
 
 #endif		/* _MXIT_ACTIONS_H_ */
--- a/libpurple/protocols/mxit/chunk.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/chunk.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 #include	"internal.h"
 #include	"debug.h"
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"mxit.h"
 #include	"chunk.h"
 #include	"filexfer.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/mxit/client.c	Sun Aug 18 01:53:00 2013 +0530
@@ -0,0 +1,2953 @@
+/*
+ *					MXit Protocol libPurple Plugin
+ *
+ *			-- MXit client protocol implementation --
+ *
+ *				Pieter Loubser	<libpurple@mxit.com>
+ *
+ *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
+ *				<http://www.mxitlifestyle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include	"internal.h"
+#include	"debug.h"
+#include	"version.h"
+
+#include	"client.h"
+#include	"mxit.h"
+#include	"roster.h"
+#include	"chunk.h"
+#include	"filexfer.h"
+#include	"markup.h"
+#include	"multimx.h"
+#include	"splashscreen.h"
+#include	"login.h"
+#include	"formcmds.h"
+#include	"http.h"
+#include	"cipher.h"
+#include	"voicevideo.h"
+
+
+#define		MXIT_MS_OFFSET		3
+
+/* configure the right record terminator char to use */
+#define		CP_REC_TERM			( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM )
+
+
+/*------------------------------------------------------------------------
+ * return the current timestamp in milliseconds
+ */
+gint64 mxit_now_milli( void )
+{
+	GTimeVal	now;
+
+	g_get_current_time( &now );
+
+	return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) );
+}
+
+
+/*------------------------------------------------------------------------
+ * Display a notification popup message to the user.
+ *
+ *  @param type			The type of notification:
+ *		- info:		PURPLE_NOTIFY_MSG_INFO
+ *		- warning:	PURPLE_NOTIFY_MSG_WARNING
+ *		- error:	PURPLE_NOTIFY_MSG_ERROR
+ *  @param heading		Heading text
+ *  @param message		Message text
+ */
+void mxit_popup( int type, const char* heading, const char* message )
+{
+	/* (reference: "libpurple/notify.h") */
+	purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL );
+}
+
+
+/*------------------------------------------------------------------------
+ * For compatibility with legacy clients, all usernames are sent from MXit with a domain
+ *  appended.  For MXit contacts, this domain is set to "@m".  This function strips
+ *  those fake domains.
+ *
+ *  @param username		The username of the contact
+ */
+void mxit_strip_domain( char* username )
+{
+	if ( g_str_has_suffix( username, "@m" ) )
+		username[ strlen( username ) - 2 ] = '\0';
+}
+
+
+/*------------------------------------------------------------------------
+ * Dump a byte buffer to the console for debugging purposes.
+ *
+ *  @param buf			The data
+ *  @param len			The data length
+ */
+void dump_bytes( struct MXitSession* session, const char* buf, int len )
+{
+	char*	msg	= g_malloc0( len + 1 );
+	int		i;
+
+	for ( i = 0; i < len; i++ ) {
+		char ch	= buf[i];
+
+		if ( ch == CP_REC_TERM )		/* record terminator */
+			msg[i] = '!';
+		else if ( ch == CP_FLD_TERM )	/* field terminator */
+			msg[i] = '^';
+		else if ( ch == CP_PKT_TERM )	/* packet terminator */
+			msg[i] = '@';
+		else if ( ( ch < 0x20 ) || ( ch > 0x7E ) )		/* non-printable character */
+			msg[i] = '_';
+		else
+			msg[i] = ch;
+	}
+
+	purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg );
+
+	g_free( msg );
+}
+
+
+/*------------------------------------------------------------------------
+ * Determine if we have an active chat with a specific contact
+ *
+ *  @param session		The MXit session object
+ *  @param who			The contact name
+ *  @return				Return true if we have an active chat with the contact
+ */
+gboolean find_active_chat( const GList* chats, const char* who )
+{
+	const GList*	list	= chats;
+	const char*		chat	= NULL;
+
+	while ( list ) {
+		chat = (const char*) list->data;
+
+		if ( strcmp( chat, who ) == 0 )
+			return TRUE;
+
+		list = g_list_next( list );
+	}
+
+	return FALSE;
+}
+
+
+/*========================================================================================================================
+ * Low-level Packet transmission
+ */
+
+/*------------------------------------------------------------------------
+ * Remove next packet from transmission queue.
+ *
+ *  @param session		The MXit session object
+ *  @return				The next packet for transmission (or NULL)
+ */
+static struct tx_packet* pop_tx_packet( struct MXitSession* session )
+{
+	struct tx_packet*	packet	= NULL;
+
+	if ( session->queue.count > 0 ) {
+		/* dequeue the next packet */
+		packet = session->queue.packets[session->queue.rd_i];
+		session->queue.packets[session->queue.rd_i] = NULL;
+		session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE;
+		session->queue.count--;
+	}
+
+	return packet;
+}
+
+
+/*------------------------------------------------------------------------
+ * Add packet to transmission queue.
+ *
+ *  @param session		The MXit session object
+ *  @param packet		The packet to transmit
+ *  @return				Return TRUE if packet was enqueue, or FALSE if queue is full.
+ */
+static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet )
+{
+	if ( session->queue.count < MAX_QUEUE_SIZE ) {
+		/* enqueue packet */
+		session->queue.packets[session->queue.wr_i] = packet;
+		session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE;
+		session->queue.count++;
+		return TRUE;
+	}
+	else
+		return FALSE;		/* queue is full */
+}
+
+
+/*------------------------------------------------------------------------
+ * Deallocate transmission packet.
+ *
+ *  @param packet		The packet to deallocate.
+ */
+static void free_tx_packet( struct tx_packet* packet )
+{
+	g_free( packet->data );
+	g_free( packet );
+	packet = NULL;
+}
+
+
+/*------------------------------------------------------------------------
+ * Flush all the packets from the tx queue and release the resources.
+ *
+ *  @param session		The MXit session object
+ */
+static void flush_queue( struct MXitSession* session )
+{
+	struct tx_packet*	packet;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" );
+
+	while ( (packet = pop_tx_packet( session ) ) != NULL )
+		free_tx_packet( packet );
+}
+
+
+/*------------------------------------------------------------------------
+ * TX Step 3: Write the packet data to the TCP connection.
+ *
+ *  @param fd			The file descriptor
+ *  @param pktdata		The packet data
+ *  @param pktlen		The length of the packet data
+ *  @return				Return -1 on error, otherwise 0
+ */
+static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen )
+{
+	int		written;
+	int		res;
+
+	written = 0;
+	while ( written < pktlen ) {
+		res = write( fd, &pktdata[written], pktlen - written );
+		if ( res <= 0 ) {
+			/* error on socket */
+			if ( errno == EAGAIN )
+				continue;
+
+			purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res );
+			return -1;
+		}
+		written += res;
+	}
+
+	return 0;
+}
+
+
+/**
+ * Callback called for handling a HTTP GET response
+ *
+ * @param http_conn http api object (see http.h)
+ * @param response  http api object (see http.h)
+ * @param _session  The MXit session object
+ */
+static void
+mxit_cb_http_rx(PurpleHttpConnection *http_conn, PurpleHttpResponse *response,
+	gpointer _session)
+{
+	struct MXitSession *session = _session;
+	const gchar *got_data;
+	size_t got_len;
+
+	if (!purple_http_response_is_successful(response)) {
+		purple_debug_error(MXIT_PLUGIN_ID, "HTTP response error (%s)\n",
+			purple_http_response_get_error(response));
+		return;
+	}
+
+	/* convert the HTTP result */
+	got_data = purple_http_response_get_data(response, &got_len);
+	memcpy(session->rx_dbuf, got_data, got_len);
+	session->rx_i = got_len;
+
+	mxit_parse_packet(session);
+}
+
+
+/**
+ * TX Step 3: Write the packet data to the HTTP connection (GET style).
+ *
+ * @param session The MXit session object
+ * @param packet  The packet data
+ */
+static void
+mxit_write_http_get(struct MXitSession* session, struct tx_packet* packet)
+{
+	PurpleHttpRequest *req;
+	char *part = NULL;
+
+	if (packet->datalen > 0) {
+		char *tmp;
+
+		tmp = g_strndup(packet->data, packet->datalen);
+		part = g_strdup(purple_url_encode(tmp));
+		g_free(tmp);
+	}
+
+	req = purple_http_request_new(NULL);
+	purple_http_request_set_url_printf(req, "%s?%s%s", session->http_server,
+		purple_url_encode(packet->header), part ? part : "");
+	purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT);
+	purple_http_connection_set_add(session->async_http_reqs,
+		purple_http_request(session->con, req, mxit_cb_http_rx,
+			session));
+	purple_http_request_unref(req);
+
+	g_free(part);
+}
+
+
+/**
+ * TX Step 3: Write the packet data to the HTTP connection (POST style).
+ *
+ * @param session The MXit session object
+ * @param packet  The packet data
+ */
+static void
+mxit_write_http_post(struct MXitSession* session, struct tx_packet* packet)
+{
+	PurpleHttpRequest *req;
+
+	/* strip off the last '&' from the header */
+	packet->header[packet->headerlen - 1] = '\0';
+	packet->headerlen--;
+
+	req = purple_http_request_new(NULL);
+	purple_http_request_set_url_printf(req, "%s?%s", session->http_server,
+		purple_url_encode(packet->header));
+	purple_http_request_set_method(req, "POST");
+	purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT);
+	purple_http_request_header_set(req, "Content-Type",
+		"application/octet-stream");
+	purple_http_request_set_contents(req, packet->data + MXIT_MS_OFFSET,
+		packet->datalen - MXIT_MS_OFFSET);
+	purple_http_connection_set_add(session->async_http_reqs,
+		purple_http_request(session->con, req, mxit_cb_http_rx,
+			session));
+	purple_http_request_unref(req);
+}
+
+
+/*------------------------------------------------------------------------
+ * TX Step 2: Handle the transmission of the packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param packet		The packet to transmit
+ */
+static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet )
+{
+	int		res;
+
+	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
+		/* we are not connected so ignore all packets to be send */
+		purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" );
+		return;
+	}
+
+	purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen );
+#ifdef	DEBUG_PROTOCOL
+	dump_bytes( session, packet->header, packet->headerlen );
+	dump_bytes( session, packet->data, packet->datalen );
+#endif
+
+	if ( !session->http ) {
+		/* socket connection */
+		char		data[packet->datalen + packet->headerlen];
+		int			datalen;
+
+		/* create raw data buffer */
+		memcpy( data, packet->header, packet->headerlen );
+		memcpy( data + packet->headerlen, packet->data, packet->datalen );
+		datalen = packet->headerlen + packet->datalen;
+
+		res = mxit_write_sock_packet( session->fd, data, datalen );
+		if ( res < 0 ) {
+			/* we must have lost the connection, so terminate it so that we can reconnect */
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "We have lost the connection to MXit. Please reconnect." ) );
+		}
+	}
+	else {
+		/* http connection */
+
+		if ( packet->cmd == CP_CMD_MEDIA ) {
+			/* multimedia packets must be send with a HTTP POST */
+			mxit_write_http_post( session, packet );
+		}
+		else {
+			mxit_write_http_get( session, packet );
+		}
+	}
+
+	/* update the timestamp of the last-transmitted packet */
+	session->last_tx = mxit_now_milli();
+
+	/*
+	 * we need to remember that we are still waiting for the ACK from
+	 * the server on this request
+	 */
+	session->outack = packet->cmd;
+
+	/* free up the packet resources */
+	free_tx_packet( packet );
+}
+
+
+/*------------------------------------------------------------------------
+ * TX Step 1: Create a new Tx packet and queue it for sending.
+ *
+ *  @param session		The MXit session object
+ *  @param data			The packet data (payload)
+ *  @param datalen		The length of the packet data
+ *  @param cmd			The MXit command for this packet
+ */
+static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd )
+{
+	struct tx_packet*	packet;
+	char				header[256];
+	int					hlen;
+
+	/* create a packet for sending */
+	packet = g_new0( struct tx_packet, 1 );
+	packet->data = g_malloc0( datalen );
+	packet->cmd = cmd;
+	packet->headerlen = 0;
+
+	/* create generic packet header */
+	hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM );	/* client mxitid */
+
+	if ( session->http ) {
+		/* http connection only */
+		hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" );
+		if ( session->http_sesid > 0 ) {
+			hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM );	/* http session id */
+		}
+		session->http_seqno++;
+		hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM );		/* http request sequence id */
+	}
+
+	hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); 						/* packet command */
+
+	if ( !session->http ) {
+		/* socket connection only */
+		packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM );		/* packet length */
+	}
+
+	/* copy the header to packet */
+	memcpy( packet->header + packet->headerlen, header, hlen );
+	packet->headerlen += hlen;
+
+	/* copy payload to packet */
+	if ( datalen > 0 )
+		memcpy( packet->data, data, datalen );
+	packet->datalen = datalen;
+
+
+	/* shortcut */
+	if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) {
+		/* the queue is empty and there are no outstanding acks so we can write it directly */
+		mxit_send_packet( session, packet );
+	}
+	else {
+		/* we need to queue this packet */
+
+		if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) {
+			/* we do NOT queue HTTP poll nor socket ping packets */
+			free_tx_packet( packet );
+			return;
+		}
+
+		purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd );
+		if ( !push_tx_packet( session, packet ) ) {
+			/* packet could not be queued for transmission */
+			mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) );
+			free_tx_packet( packet );
+		}
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Manage the packet send queue (send next packet, timeout's, etc).
+ *
+ *  @param session		The MXit session object
+ */
+static void mxit_manage_queue( struct MXitSession* session )
+{
+	struct tx_packet*	packet		= NULL;
+	gint64				now			= mxit_now_milli();
+
+	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
+		/* we are not connected, so ignore the queue */
+		return;
+	}
+	else if ( session->outack > 0 ) {
+		/* we are still waiting for an outstanding ACK from the MXit server */
+		if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
+			/* ack timeout! so we close the connection here */
+			purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Timeout while waiting for a response from the MXit server." ) );
+		}
+		return;
+	}
+
+	/*
+	 * the mxit server has flood detection and it prevents you from sending messages to fast.
+	 * this is a self defense mechanism, a very annoying feature. so the client must ensure that
+	 * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds.
+	 * this is what we are trying to avoid here..
+	 */
+	if ( session->q_fast_timer_id == 0 ) {
+		/* the fast timer has not been set yet */
+		if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) {
+			/* we need to wait a little before sending the next packet, so schedule a wakeup call */
+			gint64 tdiff = now - ( session->last_tx );
+			guint delay = ( MXIT_TX_DELAY - tdiff ) + 9;
+			if ( delay <= 0 )
+				delay = MXIT_TX_DELAY;
+			session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session );
+		}
+		else {
+			/* get the next packet from the queue to send */
+			packet = pop_tx_packet( session );
+			if ( packet != NULL ) {
+				/* there was a packet waiting to be sent to the server, now is the time to do something about it */
+
+				/* send the packet to MXit server */
+				mxit_send_packet( session, packet );
+			}
+		}
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Slow callback to manage the packet send queue.
+ *
+ *  @param session		The MXit session object
+ */
+gboolean mxit_manage_queue_slow( gpointer user_data )
+{
+	struct MXitSession* session		= (struct MXitSession*) user_data;
+
+	mxit_manage_queue( session );
+
+	/* continue running */
+	return TRUE;
+}
+
+
+/*------------------------------------------------------------------------
+ * Fast callback to manage the packet send queue.
+ *
+ *  @param session		The MXit session object
+ */
+gboolean mxit_manage_queue_fast( gpointer user_data )
+{
+	struct MXitSession* session		= (struct MXitSession*) user_data;
+
+	session->q_fast_timer_id = 0;
+	mxit_manage_queue( session );
+
+	/* stop running */
+	return FALSE;
+}
+
+
+/*------------------------------------------------------------------------
+ * Callback to manage HTTP server polling (HTTP connections ONLY)
+ *
+ *  @param session		The MXit session object
+ */
+gboolean mxit_manage_polling( gpointer user_data )
+{
+	struct MXitSession* session		= (struct MXitSession*) user_data;
+	gboolean			poll		= FALSE;
+	gint64				now			= mxit_now_milli();
+	gint64				rxdiff;
+
+	if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
+		/* we only poll if we are actually logged in */
+		return TRUE;
+	}
+
+	/* calculate the time differences */
+	rxdiff = now - session->last_rx;
+
+	if ( rxdiff < MXIT_HTTP_POLL_MIN ) {
+		/* we received some reply a few moments ago, so reset the poll interval */
+		session->http_interval = MXIT_HTTP_POLL_MIN;
+	}
+	else if ( session->http_last_poll < ( now - session->http_interval ) ) {
+		/* time to poll again */
+		poll = TRUE;
+
+		/* back-off some more with the polling */
+		session->http_interval = session->http_interval + ( session->http_interval / 2 );
+		if ( session->http_interval > MXIT_HTTP_POLL_MAX )
+			session->http_interval = MXIT_HTTP_POLL_MAX;
+	}
+
+	/* debugging */
+	//purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i)\n", session->http_interval, rxdiff );
+
+	if ( poll ) {
+		/* send poll request */
+		session->http_last_poll = mxit_now_milli();
+		mxit_send_poll( session );
+	}
+
+	return TRUE;
+}
+
+
+/*========================================================================================================================
+ * Send MXit operations.
+ */
+
+/*------------------------------------------------------------------------
+ * Send a ping/keepalive packet to MXit server.
+ *
+ *  @param session		The MXit session object
+ */
+void mxit_send_ping( struct MXitSession* session )
+{
+	/* queue packet for transmission */
+	mxit_queue_packet( session, NULL, 0, CP_CMD_PING );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a poll request to the HTTP server (HTTP connections ONLY).
+ *
+ *  @param session		The MXit session object
+ */
+void mxit_send_poll( struct MXitSession* session )
+{
+	/* queue packet for transmission */
+	mxit_queue_packet( session, NULL, 0, CP_CMD_POLL );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a logout packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ */
+void mxit_send_logout( struct MXitSession* session )
+{
+	/* queue packet for transmission */
+	mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a register packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ */
+void mxit_send_register( struct MXitSession* session )
+{
+	struct MXitProfile*	profile		= session->profile;
+	const char*			locale;
+	char				data[CP_MAX_PACKET];
+	int					datalen;
+	char*				clientVersion;
+	unsigned int		features	= MXIT_CP_FEATURES;
+
+	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
+
+	/* Voice and Video supported */
+	if ( mxit_audio_enabled() && mxit_video_enabled() )
+		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
+	else if ( mxit_audio_enabled() )
+		features |= MXIT_CF_VOICE;
+
+	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
+	clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i%c%s%c"		/* "ms"=password\1version\1maxreplyLen\1name\1 */
+								"%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,
+								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
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER );
+
+	g_free( clientVersion );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a login packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ */
+void mxit_send_login( struct MXitSession* session )
+{
+	const char*		splashId;
+	const char*		locale;
+	char			data[CP_MAX_PACKET];
+	int				datalen;
+	char*			clientVersion;
+	unsigned int	features	= MXIT_CP_FEATURES;
+
+	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
+
+	/* Voice and Video supported */
+	if ( mxit_audio_enabled() && mxit_video_enabled() )
+		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
+	else if ( mxit_audio_enabled() )
+		features |= MXIT_CF_VOICE;
+
+	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
+	clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i%c"			/* "ms"=password\1version\1getContacts\1 */
+								"%s%c%s%c%i%c"				/* capabilities\1dc\1features\1 */
+								"%s%c%s%c"					/* dialingcode\1locale\1 */
+								"%i%c%i%c%i",				/* maxReplyLen\1protocolVer\1lastRosterUpdate */
+								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
+	);
+
+	/* include "custom resource" information */
+	splashId = splash_current( session );
+	if ( splashId != NULL )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
+
+	g_free( clientVersion );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a chat message packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param to			The username of the recipient
+ *  @param msg			The message text
+ */
+void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command )
+{
+	char		data[CP_MAX_PACKET];
+	char*		markuped_msg;
+	int			datalen;
+	int			msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL );
+
+	/* first we need to convert the markup from libPurple to MXit format */
+	if ( parse_markup )
+		markuped_msg = mxit_convert_markup_tx( msg, &msgtype );
+	else
+		markuped_msg = g_strdup( msg );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i%c%i",		/* "ms"=jid\1msg\1type\1flags */
+								to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
+	);
+
+	/* free the resources */
+	g_free( markuped_msg );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a extended profile request packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param username		Username who's profile is being requested (NULL = our own)
+ *  @param nr_attribs	Number of attributes being requested
+ *  @param attribute	The names of the attributes
+ */
+void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] )
+{
+	char			data[CP_MAX_PACKET];
+	int				datalen;
+	unsigned int	i;
+
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%i",		/* "ms="mxitid\1nr_attributes */
+								( username ? username : "" ), CP_FLD_TERM, nr_attrib
+	);
+
+	/* add attributes */
+	for ( i = 0; i < nr_attrib; i++ )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send an update profile packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param password		The new password to be used for logging in (optional)
+ *	@param nr_attrib	The number of attributes
+ *	@param attributes	String containing the attribute-name, attribute-type and value (seperated by '\01')
+ */
+void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes )
+{
+	char			data[CP_MAX_PACKET];
+	gchar**			parts					= NULL;
+	int				datalen;
+	unsigned int	i;
+
+	if ( attributes )
+		parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%i",	/* "ms"=password\1nr_attibutes  */
+								( password ) ? password : "", CP_FLD_TERM, nr_attrib
+	);
+
+	/* add attributes */
+	for ( i = 1; i < nr_attrib * 3; i+=3 ) {
+		if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) {
+			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib );
+			g_strfreev( parts );
+			return;
+		}
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen,
+								"%c%s%c%s%c%s",		/* \1name\1type\1value  */
+								CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
+	}
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET );
+
+	/* freeup the memory */
+	g_strfreev( parts );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send packet to request list of suggested friends.
+ *
+ *  @param session		The MXit session object
+ *  @param max			Maximum number of results to return
+ *  @param nr_attribs	Number of attributes being requested
+ *  @param attribute	The names of the attributes
+ */
+void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] )
+{
+	char			data[CP_MAX_PACKET];
+	int				datalen;
+	unsigned int	i;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%i%c%s%c%i%c%i%c%i",	/* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
+								CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
+
+	/* add attributes */
+	for ( i = 0; i < nr_attrib; i++ )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send packet to perform a search for users.
+ *
+ *  @param session		The MXit session object
+ *  @param max			Maximum number of results to return
+ *  @param text			The search text
+ *  @param nr_attribs	Number of attributes being requested
+ *  @param attribute	The names of the attributes
+ */
+void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] )
+{
+	char			data[CP_MAX_PACKET];
+	int				datalen;
+	unsigned int	i;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%i%c%s%c%i%c%i%c%i",	/* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
+								CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
+
+	/* add attributes */
+	for ( i = 0; i < nr_attrib; i++ )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a presence update packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param presence		The presence (as per MXit types)
+ *  @param statusmsg	The status message (can be NULL)
+ */
+void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%i%c",					/* "ms"=show\1status */
+								presence, CP_FLD_TERM
+	);
+
+	/* append status message (if one is set) */
+	if ( statusmsg )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a mood update packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param mood			The mood (as per MXit types)
+ */
+void mxit_send_mood( struct MXitSession* session, int mood )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%i",	/* "ms"=mood */
+								mood
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MOOD );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send an invite contact packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The username of the contact being invited
+ *  @param mxitid		Indicates the username is a MXitId.
+ *  @param alias		Our alias for the contact
+ *  @param groupname	Group in which contact should be stored.
+ *  @param message		Invite message
+ */
+void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%s%c%i%c%s%c%i",	/* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
+								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
+								CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
+								( message ? message : "" ), CP_FLD_TERM,
+								( mxitid ? 0 : 1 )
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_INVITE );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a remove contact packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The username of the contact being removed
+ */
+void mxit_send_remove( struct MXitSession* session, const char* username )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s",	/* "ms"=username */
+								username
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send an accept subscription (invite) packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The username of the contact being accepted
+ *  @param alias		Our alias for the contact
+ */
+void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%s",	/* "ms"=username\1group\1alias */
+								username, CP_FLD_TERM, "", CP_FLD_TERM, alias
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send an deny subscription (invite) packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The username of the contact being denied
+ *  @param reason		The message describing the reason for the rejection (can be NULL).
+ */
+void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s",	/* "ms"=username */
+								username
+	);
+
+	/* append reason (if one is set) */
+	if ( reason )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send an update contact packet to the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The username of the contact being denied
+ *  @param alias		Our alias for the contact
+ *  @param groupname	Group in which contact should be stored.
+ */
+void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%s",	/* "ms"=groupname\1username\1alias */
+								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a splash-screen click event packet.
+ *
+ *  @param session		The MXit session object
+ *  @param splashid		The identifier of the splash-screen
+ */
+void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s",	/* "ms"=splashId */
+								splashid
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a message event packet.
+ *
+ *  @param session		The MXit session object
+ *  @param to           The username of the original sender (ie, recipient of the event)
+ *  @param id			The identifier of the event (received in message)
+ *  @param event		Identified the type of event
+ */
+void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i",		/* "ms"=contactAddress \1 id \1 event */
+								to, CP_FLD_TERM, id, CP_FLD_TERM, event
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send packet to create a MultiMX room.
+ *
+ *  @param session		The MXit session object
+ *  @param groupname	Name of the room to create
+ *  @param nr_usernames	Number of users in initial invite
+ *  @param usernames	The usernames of the users in the initial invite
+ */
+void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+	int			i;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%i",	/* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
+								groupname, CP_FLD_TERM, nr_usernames
+	);
+
+	/* add usernames */
+	for ( i = 0; i < nr_usernames; i++ )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send packet to invite users to existing MultiMX room.
+ *
+ *  @param session		The MXit session object
+ *  @param roomid		The unique RoomID for the MultiMx room.
+ *  @param nr_usernames	Number of users being invited
+ *  @param usernames	The usernames of the users being invited
+ */
+void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] )
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+	int			i;
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ),
+								"ms=%s%c%i",	/* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
+								roomid, CP_FLD_TERM, nr_usernames
+	);
+
+	/* add usernames */
+	for ( i = 0; i < nr_usernames; i++ )
+		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a "send file direct" multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The username of the recipient
+ *  @param filename		The name of the file being sent
+ *  @param buf			The content of the file
+ *  @param buflen		The length of the file contents
+ */
+void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
+{
+	char				data[CP_MAX_PACKET];
+	int					datalen		= 0;
+	gchar*				chunk;
+	int					size;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+
+	/* map chunk header over data buffer */
+	chunk = &data[datalen];
+
+	size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
+	if ( size < 0 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
+		return;
+	}
+
+	set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
+	set_chunk_length( chunk, size );
+	datalen += MXIT_CHUNK_HEADER_SIZE + size;
+
+	/* send the byte stream to the mxit server */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a "reject file" multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param fileid		A unique ID that identifies this file
+ */
+void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
+{
+	char				data[CP_MAX_PACKET];
+	int					datalen		= 0;
+	gchar*				chunk;
+	int					size;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+
+	/* map chunk header over data buffer */
+	chunk = &data[datalen];
+
+	size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
+	if ( size < 0 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
+		return;
+	}
+
+	set_chunk_type( chunk, CP_CHUNK_REJECT );
+	set_chunk_length( chunk, size );
+	datalen += MXIT_CHUNK_HEADER_SIZE + size;
+
+	/* send the byte stream to the mxit server */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a "get file" multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param fileid		A unique ID that identifies this file
+ *  @param filesize		The number of bytes to retrieve
+ *  @param offset		Offset in file at which to start retrieving
+ */
+void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset )
+{
+	char				data[CP_MAX_PACKET];
+	int					datalen		= 0;
+	gchar*				chunk;
+	int					size;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+
+	/* map chunk header over data buffer */
+	chunk = &data[datalen];
+
+	size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
+	if ( size < 0 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
+		return;
+	}
+
+	set_chunk_type( chunk, CP_CHUNK_GET );
+	set_chunk_length( chunk, size );
+	datalen += MXIT_CHUNK_HEADER_SIZE + size;
+
+	/* send the byte stream to the mxit server */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a "received file" multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param status		The status of the file-transfer
+ */
+void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status )
+{
+	char				data[CP_MAX_PACKET];
+	int					datalen		= 0;
+	gchar*				chunk;
+	int					size;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+
+	/* map chunk header over data buffer */
+	chunk = &data[datalen];
+
+	size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
+	if ( size < 0 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
+		return;
+	}
+
+	set_chunk_type( chunk, CP_CHUNK_RECEIVED );
+	set_chunk_length( chunk, size );
+	datalen += MXIT_CHUNK_HEADER_SIZE + size;
+
+	/* send the byte stream to the mxit server */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a "set avatar" multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param data			The avatar data
+ *  @param buflen		The length of the avatar data
+ */
+void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
+{
+	char				data[CP_MAX_PACKET];
+	int					datalen		= 0;
+	gchar*				chunk;
+	int					size;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+
+	/* map chunk header over data buffer */
+	chunk = &data[datalen];
+
+	size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
+	if ( size < 0 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
+		return;
+	}
+
+	set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
+	set_chunk_length( chunk, size );
+	datalen += MXIT_CHUNK_HEADER_SIZE + size;
+
+	/* send the byte stream to the mxit server */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+}
+
+
+/*------------------------------------------------------------------------
+ * Send a "get avatar" multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param mxitId		The username who's avatar to request
+ *  @param avatarId		The id of the avatar image (as string)
+ *  @param data			The avatar data
+ *  @param buflen		The length of the avatar data
+ */
+void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId )
+{
+	char				data[CP_MAX_PACKET];
+	int					datalen		= 0;
+	gchar*				chunk;
+	int					size;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
+
+	/* convert the packet to a byte stream */
+	datalen = g_snprintf( data, sizeof( data ), "ms=" );
+
+	/* map chunk header over data buffer */
+	chunk = &data[datalen];
+
+	size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
+	if ( size < 0 ) {
+		purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
+		return;
+	}
+
+	set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
+	set_chunk_length( chunk, size );
+	datalen += MXIT_CHUNK_HEADER_SIZE + size;
+
+	/* send the byte stream to the mxit server */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a login message packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount )
+{
+	PurpleStatus*	status;
+	int				presence;
+	const char*		statusmsg;
+	const char*		profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
+									CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
+									CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP, CP_PROFILE_FLAGS };
+
+	purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
+
+	/* we were not yet logged in so we need to complete the login sequence here */
+	session->flags |= MXIT_FLAG_LOGGEDIN;
+	purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 );
+	purple_connection_set_state( session->con, PURPLE_CONNECTION_CONNECTED );
+
+	/* save extra info if this is a HTTP connection */
+	if ( session->http ) {
+		/* save the http server to use for this session */
+		g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
+
+		/* save the session id */
+		session->http_sesid = atoi( records[0]->fields[0]->data );
+	}
+
+	/* extract UserId (from protocol 5.9) */
+	if ( records[1]->fcount >= 9 )
+		session->uid = g_strdup( records[1]->fields[8]->data );
+
+	/* extract VoIP server (from protocol 6.2) */
+	if ( records[1]->fcount >= 11 )
+		g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) );
+
+	/* display the current splash-screen */
+	if ( splash_popup_enabled( session ) )
+		splash_display( session );
+
+	/* update presence status */
+	status = purple_account_get_active_status( session->acc );
+	presence = mxit_convert_presence( purple_status_get_id( status ) );
+	statusmsg = purple_status_get_attr_string( status, "message" );
+
+	if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) {
+		/* when logging into MXit, your default presence is online. but with the UI, one can change
+		 * the presence to whatever. in the case where its changed to a different presence setting
+		 * we need to send an update to the server, otherwise the user's presence will be out of
+		 * sync between the UI and MXit.
+		 */
+		char* statusmsg1 = purple_markup_strip_html( statusmsg );
+		char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
+
+		mxit_send_presence( session, presence, statusmsg2 );
+
+		g_free( statusmsg1 );
+		g_free( statusmsg2 );
+	}
+
+	/* retrieve our MXit profile */
+	mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist );
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received message packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount )
+{
+	struct RXMsgData*	mx			= NULL;
+	char*				message		= NULL;
+	char*				sender		= NULL;
+	int					msglen		= 0;
+	int					msgflags	= 0;
+	int					msgtype		= 0;
+
+	if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) {
+		/* packet contains no message or an empty message */
+		return;
+	}
+
+	message = records[1]->fields[0]->data;
+	msglen = strlen( message );
+
+	/* strip off dummy domain */
+	sender = records[0]->fields[0]->data;
+	mxit_strip_domain( sender );
+
+#ifdef	DEBUG_PROTOCOL
+	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
+#endif
+
+	/* decode message flags (if any) */
+	if ( records[0]->fcount >= 5 )
+		msgflags = atoi( records[0]->fields[4]->data );
+	msgtype = atoi( records[0]->fields[2]->data );
+
+	if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
+		/* this is a password encrypted message. we do not currently support those so ignore it */
+		PurpleBuddy*	buddy;
+		const char*		name;
+		char			msg[128];
+
+		buddy = purple_blist_find_buddy( session->acc, sender );
+		if ( buddy )
+			name = purple_buddy_get_alias( buddy );
+		else
+			name = sender;
+		g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
+		mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
+		return;
+	}
+	else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
+		/* this is a transport-layer encrypted message. */
+		message = mxit_decrypt_message( session, message );
+		if ( !message ) {
+			/* could not be decrypted */
+			serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
+			return;
+		}
+	}
+
+	if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
+		/* delivery notification is requested */
+		if ( records[0]->fcount >= 4 )
+			mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
+	}
+
+	/* create and initialise new markup struct */
+	mx = g_new0( struct RXMsgData, 1 );
+	mx->msg = g_string_sized_new( msglen );
+	mx->session = session;
+	mx->from = g_strdup( sender );
+	mx->timestamp = atoi( records[0]->fields[1]->data );
+	mx->got_img = FALSE;
+	mx->chatid = -1;
+	mx->img_count = 0;
+
+	/* update list of active chats */
+	if ( !find_active_chat( session->active_chats, mx->from ) ) {
+		session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) );
+	}
+
+	if ( is_multimx_contact( session, mx->from ) ) {
+		/* this is a MultiMx chatroom message */
+		multimx_message_received( mx, message, msglen, msgtype, msgflags );
+	}
+	else {
+		mxit_parse_markup( mx, message, msglen, msgtype, msgflags );
+	}
+
+	/* we are now done parsing the message */
+	mx->converted = TRUE;
+	if ( mx->img_count == 0 ) {
+		/* we have all the data we need for this message to be displayed now. */
+		mxit_show_message( mx );
+	}
+	else {
+		/* this means there are still images outstanding for this message and
+		 * still need to wait for them before we can display the message.
+		 * so the image received callback function will eventually display
+		 * the message. */
+	}
+
+	/* cleanup */
+	if ( msgflags & CP_MSG_TL_ENCRYPTED )
+		g_free( message );
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received subscription request packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount )
+{
+	struct contact*		contact;
+	struct record*		rec;
+	int					i;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount );
+
+	for ( i = 0; i < rcount; i++ ) {
+		rec = records[i];
+
+		if ( rec->fcount < 4 ) {
+			purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount );
+			break;
+		}
+
+		/* build up a new contact info struct */
+		contact = g_new0( struct contact, 1 );
+
+		g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
+		mxit_strip_domain( contact->username );				/* remove dummy domain */
+		g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
+		contact->type = atoi( rec->fields[2]->data );
+
+		if ( rec->fcount >= 5 ) {
+			/* there is a personal invite message attached */
+			if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) )
+				contact->msg = strdup( rec->fields[4]->data );
+		}
+
+		/* handle the subscription */
+		if ( contact-> type == MXIT_TYPE_MULTIMX ) {		/* subscription to a MultiMX room */
+			char* creator = NULL;
+
+			if ( rec->fcount >= 6 )
+				creator = rec->fields[5]->data;
+
+			multimx_invite( session, contact, creator );
+		}
+		else
+			mxit_new_subscription( session, contact );
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Parse the received presence value, and ensure that it is supported.
+ *
+ *  @param value		The received presence value.
+ *  @return				A valid presence value.
+ */
+static short mxit_parse_presence( const char* value )
+{
+	short presence = atoi( value );
+
+	/* ensure that the presence value is valid */
+	switch ( presence ) {
+		case MXIT_PRESENCE_OFFLINE :
+		case MXIT_PRESENCE_ONLINE :
+		case MXIT_PRESENCE_AWAY :
+		case MXIT_PRESENCE_DND :
+			return presence;
+
+		default :
+			return MXIT_PRESENCE_ONLINE;
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received contact update packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount )
+{
+	struct contact*		contact	= NULL;
+	struct record*		rec;
+	int					i;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount );
+
+	for ( i = 0; i < rcount; i++ ) {
+		rec = records[i];
+
+		if ( rec->fcount < 6 ) {
+			purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount );
+			break;
+		}
+
+		/* build up a new contact info struct */
+		contact = g_new0( struct contact, 1 );
+
+		g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
+		g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
+		mxit_strip_domain( contact->username );				/* remove dummy domain */
+		g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
+
+		contact->presence = mxit_parse_presence( rec->fields[3]->data );
+		contact->type = atoi( rec->fields[4]->data );
+		contact->mood = atoi( rec->fields[5]->data );
+
+		if ( rec->fcount > 6 ) {
+			/* added in protocol 5.9 - flags & subtype */
+			contact->flags = atoi( rec->fields[6]->data );
+			contact->subtype = rec->fields[7]->data[0];
+		}
+		if ( rec->fcount > 8 ) {
+			/* added in protocol 6.0 - reject message */
+			contact->msg = g_strdup( rec->fields[8]->data );
+		}
+
+		/* add the contact to the buddy list */
+		if ( contact-> type == MXIT_TYPE_MULTIMX )			/* contact is a MultiMX room */
+			multimx_created( session, contact );
+		else
+			mxit_update_contact( session, contact );
+	}
+
+	if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) {
+		session->flags |= MXIT_FLAG_FIRSTROSTER;
+		mxit_update_blist( session );
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received presence update packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount )
+{
+	int					i;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount );
+
+	for ( i = 0; i < rcount; i++ ) {
+		struct record*	rec		= records[i];
+		int				flags	= 0;
+
+		if ( rec->fcount < 6 ) {
+			purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount );
+			break;
+		}
+
+		/*
+		 * The format of the record is:
+		 * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ]
+		 */
+		mxit_strip_domain( rec->fields[0]->data );		/* contactAddress */
+
+		if ( rec->fcount >= 7 )		/* flags field is included */
+			flags = atoi( rec->fields[6]->data );
+
+		mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
+				rec->fields[3]->data, rec->fields[4]->data, flags );
+		mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received extended profile packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount )
+{
+	const char*				mxitId		= records[0]->fields[0]->data;
+	struct MXitProfile*		profile		= NULL;
+	int						count;
+	int						i;
+	const char*				avatarId	= NULL;
+	char*					statusMsg	= NULL;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
+
+	if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
+		/* No UserId or Our UserId provided, so this must be our own profile information */
+		if ( session->profile == NULL )
+			session->profile = g_new0( struct MXitProfile, 1 );
+		profile = session->profile;
+	}
+	else {
+		/* is a buddy's profile */
+		profile = g_new0( struct MXitProfile, 1 );
+	}
+
+	/* set the count for attributes */
+	count = atoi( records[0]->fields[1]->data );
+
+	for ( i = 0; i < count; i++ ) {
+		char* fname;
+		char* fvalue;
+		char* fstatus;
+		int f = ( i * 3 ) + 2;
+
+		fname = records[0]->fields[f]->data;		/* field name */
+		fvalue = records[0]->fields[f + 1]->data;	/* field value */
+		fstatus = records[0]->fields[f + 2]->data;	/* field status */
+
+		/* first check the status on the returned attribute */
+		if ( fstatus[0] != '0' ) {
+			/* error: attribute requested was NOT found */
+			purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname );
+			continue;
+		}
+
+		if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
+			/* birthdate */
+			if ( records[0]->fields[f + 1]->len > 10 ) {
+				fvalue[10] = '\0';
+				records[0]->fields[f + 1]->len = 10;
+			}
+			memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len );
+		}
+		else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
+			/* gender */
+			profile->male = ( fvalue[0] == '1' );
+		}
+		else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
+			/* nickname */
+			g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
+		}
+		else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
+			/* status message - just keep a reference to the value */
+			statusMsg = g_markup_escape_text( fvalue, -1 );
+		}
+		else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
+			/* avatar id - just keep a reference to the value */
+			avatarId = fvalue;
+		}
+		else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
+			/* title */
+			g_strlcpy( profile->title, fvalue, sizeof( profile->title ) );
+		}
+		else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
+			/* first name */
+			g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
+		}
+		else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
+			/* last name */
+			g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
+		}
+		else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) {
+			/* email address */
+			g_strlcpy( profile->email, fvalue, sizeof( profile->email ) );
+		}
+		else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) {
+			/* mobile number */
+			g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
+		}
+		else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
+			/* registered country */
+			g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
+		}
+		else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
+			/* profile flags */
+			profile->flags = g_ascii_strtoll( fvalue, NULL, 10 );
+		}
+		else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
+			/* last seen online */
+			profile->lastonline = g_ascii_strtoll( fvalue, NULL, 10 );
+		}
+		else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
+			/* where am I */
+			g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
+		}
+		else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) {
+			/* about me */
+			g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) );
+		}
+		else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) {
+			/* relatinship status */
+			profile->relationship = strtol( fvalue, NULL, 10 );
+		}
+		else {
+			/* invalid profile attribute */
+			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
+		}
+	}
+
+	if ( profile != session->profile ) {
+		/* not our own profile */
+		struct contact*		contact		= NULL;
+
+		contact = get_mxit_invite_contact( session, mxitId );
+		if ( contact ) {
+			/* this is an invite, so update its profile info */
+			if ( ( statusMsg ) && ( *statusMsg ) ) {
+				/* update the status message */
+				if ( contact->statusMsg )
+					g_free( contact->statusMsg );
+				contact->statusMsg = strdup( statusMsg );
+			}
+			else
+				contact->statusMsg = NULL;
+			if ( contact->profile )
+				g_free( contact->profile );
+			contact->profile = profile;
+			if ( ( avatarId ) && ( *avatarId ) ) {
+				/* avatar must be requested for this invite before we can display it */
+				mxit_get_avatar( session, mxitId, avatarId );
+				if ( contact->avatarId )
+					g_free( contact->avatarId );
+				contact->avatarId = strdup( avatarId );
+			}
+			else {
+				/* display what we have */
+				contact->avatarId = NULL;
+				mxit_show_profile( session, mxitId, profile );
+			}
+		}
+		else {
+			/* this is a contact */
+			if ( avatarId )
+				mxit_update_buddy_avatar( session, mxitId, avatarId );
+
+			if ( ( statusMsg ) && ( *statusMsg ) ) {
+				/* update the status message */
+				PurpleBuddy*		buddy	= NULL;
+
+				buddy = purple_blist_find_buddy( session->acc, mxitId );
+				if ( buddy ) {
+					contact = purple_buddy_get_protocol_data( buddy );
+					if ( contact ) {
+						if ( contact->statusMsg )
+							g_free( contact->statusMsg );
+						contact->statusMsg = strdup( statusMsg );
+					}
+				}
+			}
+
+			/* show the profile */
+			mxit_show_profile( session, mxitId, profile );
+			g_free( profile );
+		}
+	}
+
+	g_free( statusMsg );
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received suggest-contacts packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount )
+{
+	GList* entries = NULL;
+	int searchType;
+	int maxResults;
+	int count;
+	int i;
+
+	/*
+	 * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0
+	 * userid \1 contactType \1 value0 \1 value1 ... valueN \0
+	 * ...
+	 * userid \1 contactType \1 value0 \1 value1 ... valueN
+	 */
+
+	/* the type of results */
+	searchType = atoi( records[0]->fields[0]->data );
+
+	/* the maximum number of results */
+	maxResults = atoi( records[0]->fields[2]->data );
+
+	/* set the count for attributes */
+	count = atoi( records[0]->fields[3]->data );
+
+	for ( i = 1; i < rcount; i ++ ) {
+		struct record*		rec		= records[i];
+		struct MXitProfile*	profile	= g_new0( struct MXitProfile, 1 );
+		int j;
+
+		g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
+		// TODO: ContactType - User or Service
+
+		for ( j = 0; j < count; j++ ) {
+			char* fname;
+			char* fvalue = "";
+
+			fname = records[0]->fields[4 + j]->data;		/* field name */
+			if ( records[i]->fcount > ( 2 + j ) )
+				fvalue = records[i]->fields[2 + j]->data;	/* field value */
+
+			purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue );
+
+			if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
+				/* birthdate */
+				g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) );
+			}
+			else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
+				/* first name */
+				g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
+			}
+			else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
+				/* last name */
+				g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
+			}
+			else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
+				/* gender */
+				profile->male = ( fvalue[0] == '1' );
+			}
+			else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
+				/* nickname */
+				g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
+			}
+			else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
+				/* where am I */
+				g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
+			}
+			/* ignore other attibutes */
+		}
+
+		entries = g_list_append( entries, profile );
+	}
+
+	/* display */
+	mxit_show_search_results( session, searchType, maxResults, entries );
+
+	/* cleanup */
+	g_list_foreach( entries, (GFunc)g_free, NULL );
+}
+
+/*------------------------------------------------------------------------
+ * Process a received message event packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount )
+{
+	int event;
+
+	/*
+	 * contactAddress \1 dateTime \1 id \1 event
+	 */
+
+	/* strip off dummy domain */
+	mxit_strip_domain( records[0]->fields[0]->data );
+
+	event = atoi( records[0]->fields[3]->data );
+
+	switch ( event ) {
+		case CP_MSGEVENT_TYPING :							/* user is typing */
+		case CP_MSGEVENT_ANGRY :							/* user is typing angrily */
+			serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_IM_TYPING );
+			break;
+
+		case CP_MSGEVENT_STOPPED :							/* user has stopped typing */
+			serv_got_typing_stopped( session->con, records[0]->fields[0]->data );
+			break;
+
+		case CP_MSGEVENT_ERASING :							/* user is erasing text */
+		case CP_MSGEVENT_DELIVERED :						/* message was delivered */
+		case CP_MSGEVENT_DISPLAYED :						/* message was viewed */
+			/* these are currently not supported by libPurple */
+			break;
+
+		default:
+			purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event );
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Return the length of a multimedia chunk
+ *
+ * @return		The actual chunk data length in bytes
+ */
+static int get_chunk_len( const char* chunkdata )
+{
+	int*	sizeptr;
+
+	sizeptr = (int*) &chunkdata[1];		/* we skip the first byte (type field) */
+
+	return ntohl( *sizeptr );
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a received multimedia packet.
+ *
+ *  @param session		The MXit session object
+ *  @param records		The packet's data records
+ *  @param rcount		The number of data records
+ */
+static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
+{
+	char	type;
+	int		size;
+
+	type = records[0]->fields[0]->data[0];
+	size = get_chunk_len( records[0]->fields[0]->data );
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
+
+	/* supported chunked data types */
+	switch ( type ) {
+		case CP_CHUNK_CUSTOM :				/* custom resource */
+			{
+				struct cr_chunk chunk;
+
+				/* decode the chunked data */
+				memset( &chunk, 0, sizeof( struct cr_chunk ) );
+				mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+
+				purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
+
+				/* this is a splash-screen operation */
+				if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
+					if ( chunk.operation == CR_OP_UPDATE ) {		/* update the splash-screen */
+						struct splash_chunk *splash = chunk.resources->data;			// TODO: Fix - assuming 1st resource is splash
+						gboolean clickable = ( g_list_length( chunk.resources ) > 1 );	// TODO: Fix - if 2 resources, then is clickable
+
+						if ( splash != NULL )
+							splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
+					}
+					else if ( chunk.operation == CR_OP_REMOVE )		/* remove the splash-screen */
+						splash_remove( session );
+				}
+
+				/* cleanup custom resources */
+				g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
+
+			}
+			break;
+
+		case CP_CHUNK_OFFER :				/* file offer */
+			{
+				struct offerfile_chunk chunk;
+
+				/* decode the chunked data */
+				memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
+				mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+
+				/* process the offer */
+				mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+			}
+			break;
+
+		case CP_CHUNK_GET :					/* get file response */
+			{
+				struct getfile_chunk chunk;
+
+				/* decode the chunked data */
+				memset( &chunk, 0, sizeof( struct getfile_chunk ) );
+				mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+
+				/* process the getfile */
+				mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+			}
+			break;
+
+		case CP_CHUNK_GET_AVATAR :			/* get avatars */
+			{
+				struct getavatar_chunk chunk;
+				struct contact* contact = NULL;
+
+				/* decode the chunked data */
+				memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
+				mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+
+				/* update avatar image */
+				if ( chunk.data ) {
+					purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
+
+					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_new_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 );
+					}
+				}
+			}
+			break;
+
+		case CP_CHUNK_SET_AVATAR :
+			/* this is a reply packet to a set avatar request. no action is required */
+			break;
+
+		case CP_CHUNK_DIRECT_SND :
+			/* this is a ack for a file send. */
+			{
+				struct sendfile_chunk chunk;
+
+				memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
+				mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+
+				purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+
+				if ( chunk.status != 0 )	/* not success */
+					mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+			}
+			break;
+
+		case CP_CHUNK_RECEIVED :
+			/* this is a ack for a file received. no action is required */
+			break;
+
+		default :
+			purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
+			break;
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Handle a redirect sent from the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param url			The redirect information
+ */
+static void mxit_perform_redirect( struct MXitSession* session, const char* url )
+{
+	gchar**		parts;
+	gchar**		host;
+	int			type;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url );
+
+	/* tokenize the URL string */
+	parts = g_strsplit( url, ";", 0 );
+
+	/* Part 1: protocol://host:port */
+	host = g_strsplit( parts[0], ":", 4 );
+	if ( strcmp( host[0], "socket" ) == 0 ) {
+		/* redirect to a MXit socket proxy */
+		g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
+		session->port = atoi( host[2] );
+	}
+	else {
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) );
+		goto redirect_fail;
+	}
+
+	/* Part 2: type of redirect */
+	type = atoi( parts[1] );
+	if ( type == CP_REDIRECT_PERMANENT ) {
+		/* permanent redirect, so save new MXit server and port */
+		purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
+		purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
+	}
+
+	/* Part 3: message (optional) */
+	if ( parts[2] != NULL )
+		purple_connection_notice( session->con, parts[2] );
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n",
+			( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port );
+
+	/* perform the re-connect to the new MXit server */
+	mxit_reconnect( session );
+
+redirect_fail:
+	g_strfreev( parts );
+	g_strfreev( host );
+}
+
+
+/*------------------------------------------------------------------------
+ * Process a success response received from the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param packet		The received packet
+ */
+static int process_success_response( struct MXitSession* session, struct rx_packet* packet )
+{
+	/* ignore ping/poll packets */
+	if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) )
+		session->last_rx = mxit_now_milli();
+
+	/*
+	 * when we pass the packet records to the next level for parsing
+	 * we minus 3 records because 1) the first record is the packet
+	 * type 2) packet reply status 3) the last record is bogus
+	 */
+
+	/* packet command */
+	switch ( packet->cmd ) {
+
+		case CP_CMD_REGISTER :
+				/* fall through, when registeration successful, MXit will auto login */
+		case CP_CMD_LOGIN :
+				/* login response */
+				if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
+					mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 );
+				}
+				break;
+
+		case CP_CMD_LOGOUT :
+				/* logout response */
+				session->flags &= ~MXIT_FLAG_LOGGEDIN;
+				purple_account_disconnect( session->acc );
+
+				/* note:
+				 * we do not prompt the user here for a reconnect, because this could be the user
+				 * logging in with his phone. so we just disconnect the account otherwise
+				 * mxit will start to bounce between the phone and pidgin. also could be a valid
+				 * disconnect selected by the user.
+				 */
+				return -1;
+
+		case CP_CMD_CONTACT :
+				/* contact update */
+				mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 );
+				break;
+
+		case CP_CMD_PRESENCE :
+				/* presence update */
+				mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 );
+				break;
+
+		case CP_CMD_RX_MSG :
+				/* incoming message (no bogus record) */
+				mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 );
+				break;
+
+		case CP_CMD_NEW_SUB :
+				/* new subscription request */
+				mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 );
+				break;
+
+		case CP_CMD_MEDIA :
+				/* multi-media message */
+				mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 );
+				break;
+
+		case CP_CMD_EXTPROFILE_GET :
+				/* profile update */
+				mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 );
+				break;
+
+		case CP_CMD_SUGGESTCONTACTS :
+				/* suggest contacts */
+				mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 );
+				break;
+
+		case CP_CMD_GOT_MSGEVENT :
+				/* received message event */
+				mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 );
+				break;
+
+		case CP_CMD_MOOD :
+				/* mood update */
+		case CP_CMD_UPDATE :
+				/* update contact information */
+		case CP_CMD_ALLOW :
+				/* allow subscription ack */
+		case CP_CMD_DENY :
+				/* deny subscription ack */
+		case CP_CMD_INVITE :
+				/* invite contact ack */
+		case CP_CMD_REMOVE :
+				/* remove contact ack */
+		case CP_CMD_TX_MSG :
+				/* outgoing message ack */
+		case CP_CMD_STATUS :
+				/* presence update ack */
+		case CP_CMD_GRPCHAT_CREATE :
+				/* create groupchat */
+		case CP_CMD_GRPCHAT_INVITE :
+				/* groupchat invite */
+		case CP_CMD_PING :
+				/* ping reply */
+		case CP_CMD_POLL :
+				/* HTTP poll reply */
+		case CP_CMD_EXTPROFILE_SET :
+				/* profile update */
+				// TODO: Protocol 6.2 indicates status for each attribute, and current value.
+		case CP_CMD_SPLASHCLICK :
+				/* splash-screen clickthrough */
+		case CP_CMD_MSGEVENT :
+				/* event message */
+				break;
+
+		default :
+			/* unknown packet */
+			purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd );
+	}
+
+	return 0;
+}
+
+
+/*------------------------------------------------------------------------
+ * Process an error response received from the MXit server.
+ *
+ *  @param session		The MXit session object
+ *  @param packet		The received packet
+ */
+static int process_error_response( struct MXitSession* session, struct rx_packet* packet )
+{
+	char			errmsg[256];
+	const char*		errdesc;
+
+	/* set the error description to be shown to the user */
+	if ( packet->errmsg )
+		errdesc = packet->errmsg;
+	else
+		errdesc = _( "An internal MXit server error occurred." );
+
+	purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc );
+
+	if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) {
+		/* we are not currently logged in, so we need to reconnect */
+		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( errdesc ) );
+	}
+
+	/* packet command */
+	switch ( packet->cmd ) {
+
+		case CP_CMD_REGISTER :
+		case CP_CMD_LOGIN :
+				if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
+					mxit_perform_redirect( session, packet->errmsg );
+					return 0;
+				}
+				else {
+					g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
+					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg );
+					return -1;
+				}
+		case CP_CMD_LOGOUT :
+				g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
+				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
+				return -1;
+		case CP_CMD_CONTACT :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_RX_MSG :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_TX_MSG :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_STATUS :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_MOOD :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_KICK :
+				/*
+				 * the MXit server sends this packet if we were idle for too long.
+				 * to stop the server from closing this connection we need to resend
+				 * the login packet.
+				 */
+				mxit_send_login( session );
+				break;
+		case CP_CMD_INVITE :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_REMOVE :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_ALLOW :
+		case CP_CMD_DENY :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_UPDATE :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_MEDIA :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_GRPCHAT_CREATE :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) );
+				break;
+		case CP_CMD_GRPCHAT_INVITE :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_EXTPROFILE_GET :
+		case CP_CMD_EXTPROFILE_SET :
+				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
+				break;
+		case CP_CMD_SPLASHCLICK :
+		case CP_CMD_MSGEVENT :
+				/* ignore error */
+				break;
+		case CP_CMD_PING :
+		case CP_CMD_POLL :
+				break;
+		default :
+				mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) );
+				break;
+	}
+
+	return 0;
+}
+
+
+/*========================================================================================================================
+ * Low-level Packet receive
+ */
+
+#ifdef	DEBUG_PROTOCOL
+/*------------------------------------------------------------------------
+ * Dump a received packet structure.
+ *
+ *  @param p			The received packet
+ */
+static void dump_packet( struct rx_packet* p )
+{
+	struct record*		r	= NULL;
+	struct field*		f	= NULL;
+	int					i;
+	int					j;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount );
+
+	for ( i = 0; i < p->rcount; i++ ) {
+		r = p->records[i];
+		purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount );
+
+		for ( j = 0; j < r->fcount; j++ ) {
+			f = r->fields[j];
+			purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
+		}
+	}
+}
+#endif
+
+
+/*------------------------------------------------------------------------
+ * Free up memory used by a packet structure.
+ *
+ *  @param p			The received packet
+ */
+static void free_rx_packet( struct rx_packet* p )
+{
+	struct record*		r	= NULL;
+	struct field*		f	= NULL;
+	int					i;
+	int					j;
+
+	for ( i = 0; i < p->rcount; i++ ) {
+		r = p->records[i];
+
+		for ( j = 0; j < r->fcount; j++ ) {
+			g_free( f );
+		}
+		g_free( r->fields );
+		g_free( r );
+	}
+	g_free( p->records );
+}
+
+
+/*------------------------------------------------------------------------
+ * Add a new field to a record.
+ *
+ *  @param r			Parent record object
+ *  @return				The newly created field
+ */
+static struct field* add_field( struct record* r )
+{
+	struct field*	field;
+
+	field = g_new0( struct field, 1 );
+
+	r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) );
+	r->fields[r->fcount] = field;
+	r->fcount++;
+
+	return field;
+}
+
+
+/*------------------------------------------------------------------------
+ * Add a new record to a packet.
+ *
+ *  @param p			The packet object
+ *  @return				The newly created record
+ */
+static struct record* add_record( struct rx_packet* p )
+{
+	struct record*	rec;
+
+	rec = g_new0( struct record, 1 );
+
+	p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) );
+	p->records[p->rcount] = rec;
+	p->rcount++;
+
+	return rec;
+}
+
+
+/*------------------------------------------------------------------------
+ * Parse the received byte stream into a proper client protocol packet.
+ *
+ *  @param session		The MXit session object
+ *  @return				Success (0) or Failure (!0)
+ */
+int mxit_parse_packet( struct MXitSession* session )
+{
+	struct rx_packet	packet;
+	struct record*		rec;
+	struct field*		field;
+	gboolean			pbreak;
+	unsigned int		i;
+	int					res	= 0;
+
+#ifdef	DEBUG_PROTOCOL
+	purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i );
+	dump_bytes( session, session->rx_dbuf, session->rx_i );
+#endif
+
+	i = 0;
+	while ( i < session->rx_i ) {
+
+		/* create first record and field */
+		rec = NULL;
+		field = NULL;
+		memset( &packet, 0x00, sizeof( struct rx_packet ) );
+		rec = add_record( &packet );
+		pbreak = FALSE;
+
+		/* break up the received packet into fields and records for easy parsing */
+		while ( ( i < session->rx_i ) && ( !pbreak ) ) {
+
+			switch ( session->rx_dbuf[i] ) {
+				case CP_SOCK_REC_TERM :
+						/* new record */
+						if ( packet.rcount == 1 ) {
+							/* packet command */
+							packet.cmd = atoi( packet.records[0]->fields[0]->data );
+						}
+						else if ( packet.rcount == 2 ) {
+							/* special case: binary multimedia packets should not be parsed here */
+							if ( packet.cmd == CP_CMD_MEDIA ) {
+								/* add the chunked to new record */
+								rec = add_record( &packet );
+								field = add_field( rec );
+								field->data = &session->rx_dbuf[i + 1];
+								field->len = session->rx_i - i;
+								/* now skip the binary data */
+								res = get_chunk_len( field->data );
+								/* determine if we have more packets */
+								if ( res + 6 + i < session->rx_i ) {
+									/* we have more than one packet in this stream */
+									i += res + 6;
+									pbreak = TRUE;
+								}
+								else {
+									i = session->rx_i;
+								}
+							}
+						}
+						else if ( !field ) {
+							field = add_field( rec );
+							field->data = &session->rx_dbuf[i];
+						}
+						session->rx_dbuf[i] = '\0';
+						rec = add_record( &packet );
+						field = NULL;
+
+						break;
+				case CP_FLD_TERM :
+						/* new field */
+						session->rx_dbuf[i] = '\0';
+						if ( !field ) {
+							field = add_field( rec );
+							field->data = &session->rx_dbuf[i];
+						}
+						field = NULL;
+						break;
+				case CP_PKT_TERM :
+						/* packet is done! */
+						session->rx_dbuf[i] = '\0';
+						pbreak = TRUE;
+						break;
+				default :
+						/* skip non special characters */
+						if ( !field ) {
+							field = add_field( rec );
+							field->data = &session->rx_dbuf[i];
+						}
+						field->len++;
+						break;
+			}
+
+			i++;
+		}
+
+		if ( packet.rcount < 2 ) {
+			/* bad packet */
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) );
+			free_rx_packet( &packet );
+			continue;
+		}
+
+		session->rx_dbuf[session->rx_i] = '\0';
+		packet.errcode = atoi( packet.records[1]->fields[0]->data );
+
+		purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode );
+#ifdef	DEBUG_PROTOCOL
+		/* debug */
+		dump_packet( &packet );
+#endif
+
+		/* reset the out ack */
+		if ( session->outack == packet.cmd ) {
+			/* outstanding ack received from mxit server */
+			session->outack = 0;
+		}
+
+		/* check packet status */
+		if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) {
+			/* error reply! */
+			if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) )
+				packet.errmsg = packet.records[1]->fields[1]->data;
+			else
+				packet.errmsg = NULL;
+
+			res = process_error_response( session, &packet );
+		}
+		else {
+			/* success reply! */
+			res = process_success_response( session, &packet );
+		}
+
+		/* free up the packet resources */
+		free_rx_packet( &packet );
+	}
+
+	if ( session->outack == 0 )
+			mxit_manage_queue( session );
+
+	return res;
+}
+
+
+/*------------------------------------------------------------------------
+ * Callback when data is received from the MXit server.
+ *
+ *  @param user_data		The MXit session object
+ *  @param source			The file-descriptor on which data was received
+ *  @param cond				Condition which caused the callback (PURPLE_INPUT_READ)
+ */
+void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond )
+{
+	struct MXitSession*	session		= (struct MXitSession*) user_data;
+	char				ch;
+	int					res;
+	int					len;
+
+	if ( session->rx_state == RX_STATE_RLEN ) {
+		/* we are reading in the packet length */
+		len = read( session->fd, &ch, 1 );
+		if ( len < 0 ) {
+			/* connection error */
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
+			return;
+		}
+		else if ( len == 0 ) {
+			/* connection closed */
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
+			return;
+		}
+		else {
+			/* byte read */
+			if ( ch == CP_REC_TERM ) {
+				/* the end of the length record found */
+				session->rx_lbuf[session->rx_i] = '\0';
+				session->rx_res = atoi( &session->rx_lbuf[3] );
+				if ( session->rx_res > CP_MAX_PACKET ) {
+					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
+				}
+				session->rx_state = RX_STATE_DATA;
+				session->rx_i = 0;
+			}
+			else {
+				/* still part of the packet length record */
+				session->rx_lbuf[session->rx_i] = ch;
+				session->rx_i++;
+				if ( session->rx_i >= sizeof( session->rx_lbuf ) ) {
+					/* malformed packet length record (too long) */
+					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
+					return;
+				}
+			}
+		}
+	}
+	else if ( session->rx_state == RX_STATE_DATA ) {
+		/* we are reading in the packet data */
+		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
+		if ( len < 0 ) {
+			/* connection error */
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
+			return;
+		}
+		else if ( len == 0 ) {
+			/* connection closed */
+			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
+			return;
+		}
+		else {
+			/* data read */
+			session->rx_i += len;
+			session->rx_res -= len;
+
+			if ( session->rx_res == 0 ) {
+				/* ok, so now we have read in the whole packet */
+				session->rx_state = RX_STATE_PROC;
+			}
+		}
+	}
+
+	if ( session->rx_state == RX_STATE_PROC ) {
+		/* we have a full packet, which we now need to process */
+		res = mxit_parse_packet( session );
+
+		if ( res == 0 ) {
+			/* we are still logged in */
+			session->rx_state = RX_STATE_RLEN;
+			session->rx_res = 0;
+			session->rx_i = 0;
+		}
+	}
+}
+
+
+/*------------------------------------------------------------------------
+ * Log the user off MXit and close the connection
+ *
+ *  @param session		The MXit session object
+ */
+void mxit_close_connection( struct MXitSession* session )
+{
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" );
+
+	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
+		/* we are already closed */
+		return;
+	}
+	else if ( session->flags & MXIT_FLAG_LOGGEDIN ) {
+		/* we are currently logged in so we need to send a logout packet */
+		if ( !session->http ) {
+			mxit_send_logout( session );
+		}
+		session->flags &= ~MXIT_FLAG_LOGGEDIN;
+	}
+	session->flags &= ~MXIT_FLAG_CONNECTED;
+
+	/* cancel all outstanding async calls */
+	purple_http_connection_set_destroy(session->async_http_reqs);
+	session->async_http_reqs = NULL;
+
+	/* remove the input cb function */
+	if ( session->inpa ) {
+		purple_input_remove( session->inpa );
+		session->inpa = 0;
+	}
+
+	/* remove HTTP poll timer */
+	if ( session->http_timer_id > 0 )
+		purple_timeout_remove( session->http_timer_id );
+
+	/* remove slow queue manager timer */
+	if ( session->q_slow_timer_id > 0 )
+		purple_timeout_remove( session->q_slow_timer_id );
+
+	/* remove fast queue manager timer */
+	if ( session->q_fast_timer_id > 0 )
+		purple_timeout_remove( session->q_fast_timer_id );
+
+	/* remove all groupchat rooms */
+	while ( session->rooms != NULL ) {
+		struct multimx* multimx = (struct multimx *) session->rooms->data;
+
+		session->rooms = g_list_remove( session->rooms, multimx );
+
+		free( multimx );
+	}
+	g_list_free( session->rooms );
+	session->rooms = NULL;
+
+	/* remove all rx chats names */
+	while ( session->active_chats != NULL ) {
+		char* chat = (char*) session->active_chats->data;
+
+		session->active_chats = g_list_remove( session->active_chats, chat );
+
+		g_free( chat );
+	}
+	g_list_free( session->active_chats );
+	session->active_chats = NULL;
+
+	/* clear the internal invites */
+	while ( session->invites != NULL ) {
+		struct contact* contact = (struct contact*) session->invites->data;
+
+		session->invites = g_list_remove( session->invites, contact );
+
+		if ( contact->msg )
+			g_free( contact->msg );
+		if ( contact->statusMsg )
+			g_free( contact->statusMsg );
+		if ( contact->profile )
+			g_free( contact->profile );
+		g_free( contact );
+	}
+	g_list_free( session->invites );
+	session->invites = NULL;
+
+	/* free profile information */
+	if ( session->profile )
+		free( session->profile );
+
+	/* free custom emoticons */
+	mxit_free_emoticon_cache( session );
+
+	/* free allocated memory */
+	if ( session->uid )
+		g_free( session->uid );
+	g_free( session->encpwd );
+	session->encpwd = NULL;
+
+	/* flush all the commands still in the queue */
+	flush_queue( session );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/mxit/client.h	Sun Aug 18 01:53:00 2013 +0530
@@ -0,0 +1,352 @@
+/*
+ *					MXit Protocol libPurple Plugin
+ *
+ *			-- MXit client protocol implementation --
+ *
+ *				Pieter Loubser	<libpurple@mxit.com>
+ *
+ *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
+ *				<http://www.mxitlifestyle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef		_MXIT_PROTO_H_
+#define		_MXIT_PROTO_H_
+
+
+/* Client protocol constants */
+#define		CP_SOCK_REC_TERM		'\x00'				/* socket record terminator */
+#define		CP_HTTP_REC_TERM		'\x26'				/* http record terminator '&' */
+#define		CP_FLD_TERM				'\x01'				/* field terminator */
+#define		CP_PKT_TERM				'\x02'				/* packet terminator */
+
+
+#define		CP_MAX_PACKET			( 1 * 1000 * 1000 )	/* maximum client protocol packet size (1 MB) */
+#define		CP_MAX_FILESIZE			( CP_MAX_PACKET - 1000 )	/* maximum file size (reserve some space for packet headers) */
+#define		MXIT_EMOTICON_SIZE		18					/* icon size for custom emoticons */
+#define		CP_MAX_STATUS_MSG		250					/* maximum status message length (in characters) */
+
+/* Avatars */
+#define		MXIT_AVATAR_SIZE		96					/* default avatar image size 96x96 */
+#define		MXIT_AVATAR_TYPE		"PNG"				/* request avatars in this file type (only a suggestion) */
+#define		MXIT_AVATAR_BITDEPT		24					/* request avatars with this bit depth (only a suggestion) */
+
+/* Protocol error codes */
+#define		MXIT_ERRCODE_SUCCESS	0
+#define		MXIT_ERRCODE_REDIRECT	16
+#define		MXIT_ERRCODE_LOGGEDOUT	42
+
+/* MXit client features */
+#define		MXIT_CF_NONE			0x000000
+#define		MXIT_CF_FORMS			0x000001
+#define		MXIT_CF_FILE_TRANSFER	0x000002
+#define		MXIT_CF_CAMERA			0x000004
+#define		MXIT_CF_COMMANDS		0x000008
+#define		MXIT_CF_SMS				0x000010
+#define		MXIT_CF_FILE_ACCESS		0x000020
+#define		MXIT_CF_MIDP2			0x000040
+#define		MXIT_CF_SKINS			0x000080
+#define		MXIT_CF_AUDIO			0x000100
+#define		MXIT_CF_ENCRYPTION		0x000200
+#define		MXIT_CF_VOICE_REC		0x000400
+#define		MXIT_CF_VECTOR_GFX		0x000800
+#define		MXIT_CF_IMAGES			0x001000
+#define		MXIT_CF_MARKUP			0x002000
+#define		MXIT_CF_VIBES			0x004000
+#define		MXIT_CF_SELECT_CONTACT	0x008000
+#define		MXIT_CF_CUSTOM_EMO		0x010000
+#define		MXIT_CF_ALERT_PROFILES	0x020000
+#define		MXIT_CF_EXT_MARKUP		0x040000
+#define		MXIT_CF_PLAIN_PWD		0x080000
+#define		MXIT_CF_NO_GATEWAYS		0x100000
+#define		MXIT_CF_NO_AVATARS		0x200000
+#define		MXIT_CF_GAMING			0x400000
+#define		MXIT_CF_GAMING_UPDATE	0x800000
+#define		MXIT_CF_VOICE			0x1000000
+#define		MXIT_CF_VIDEO			0x2000000
+#define		MXIT_CF_TOUCHSCREEN		0x4000000
+#define		MXIT_CF_SVC_CONNECTION	0x8000000
+#define		MXIT_CF_MXML			0x10000000
+#define		MXIT_CF_TYPING_NOTIFY	0x20000000
+
+/* 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 | MXIT_CF_TYPING_NOTIFY )
+
+
+#define		MXIT_PING_INTERVAL		( 5 * 60 )				/* ping the server after X seconds of being idle (5 minutes) */
+#define		MXIT_ACK_TIMEOUT		( 30 )					/* timeout after waiting X seconds for an ack from the server (30 seconds) */
+#define		MXIT_TX_DELAY			( 100 )					/* delay between sending consecutive packets (100 ms) */
+
+/* MXit client version */
+#define		MXIT_CP_DISTCODE		'P'						/* client distribution code (magic, do not touch!) */
+#define		MXIT_CP_ARCH			"Y"						/* client architecture series (Y not for Yoda but for PC-client) */
+#define		MXIT_CLIENT_ID			"LP"					/* client ID as specified by MXit */
+#define		MXIT_CP_PLATFORM		"PURPLE"				/* client platform */
+#define		MXIT_CP_PROTO_VESION	63						/* client protocol version */
+
+/* set operating system name */
+#if defined( __APPLE__ )
+#define		MXIT_CP_OS				"apple"
+#elif defined( _WIN32 )
+#define		MXIT_CP_OS				"windows"
+#elif defined( __linux__ )
+#define		MXIT_CP_OS				"linux"
+#else
+#define		MXIT_CP_OS				"unknown"
+#endif
+
+/* Client capabilities */
+#define		MXIT_CP_CAP				"utf8=true;cid="MXIT_CLIENT_ID
+
+/* Client settings */
+#define		MAX_QUEUE_SIZE			( 1 << 5 )				/* tx queue size (32 packets) */
+#define		MXIT_POPUP_WIN_NAME		"MXit Notification"		/* popup window name */
+#define		MXIT_DEFAULT_LOCALE		"en"					/* default locale setting */
+#define		MXIT_DEFAULT_LOC		"planetpurple"			/* the default location for registration */
+
+/* Client protocol commands */
+#define		CP_CMD_LOGIN			0x0001					/* (1) login */
+#define		CP_CMD_LOGOUT			0x0002					/* (2) logout */
+#define		CP_CMD_CONTACT			0x0003					/* (3) get contacts */
+#define		CP_CMD_UPDATE			0x0005					/* (5) update contact information */
+#define		CP_CMD_INVITE			0x0006					/* (6) subscribe to new contact */
+#define		CP_CMD_PRESENCE			0x0007					/* (7) get presence */
+#define		CP_CMD_REMOVE			0x0008					/* (8) remove contact */
+#define		CP_CMD_RX_MSG			0x0009					/* (9) get new messages */
+#define		CP_CMD_TX_MSG			0x000A					/* (10) send new message */
+#define		CP_CMD_REGISTER			0x000B					/* (11) register */
+//#define	CP_CMD_PROFILE_SET		0x000C					/* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */
+#define		CP_CMD_SUGGESTCONTACTS	0x000D					/* (13) suggest contacts */
+#define		CP_CMD_POLL				0x0011					/* (17) poll the HTTP server for an update */
+//#define	CP_CMD_PROFILE_GET		0x001A					/* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */
+#define		CP_CMD_MEDIA			0x001B					/* (27) get multimedia message */
+#define		CP_CMD_SPLASHCLICK		0x001F					/* (31) splash-screen clickthrough */
+#define		CP_CMD_STATUS			0x0020					/* (32) set shown presence & status */
+#define		CP_CMD_MSGEVENT			0x0023					/* (35) Raise message event */
+#define		CP_CMD_GOT_MSGEVENT		0x0024					/* (36) Get message event */
+#define		CP_CMD_MOOD				0x0029					/* (41) set mood */
+#define		CP_CMD_KICK				0x002B					/* (43) login kick */
+#define		CP_CMD_GRPCHAT_CREATE	0x002C					/* (44) create new groupchat */
+#define		CP_CMD_GRPCHAT_INVITE	0x002D					/* (45) add new groupchat member */
+#define		CP_CMD_NEW_SUB			0x0033					/* (51) get new subscription */
+#define		CP_CMD_ALLOW			0x0034					/* (52) allow subscription */
+#define		CP_CMD_DENY				0x0037					/* (55) deny subscription */
+#define		CP_CMD_EXTPROFILE_GET	0x0039					/* (57) get extended profile */
+#define		CP_CMD_EXTPROFILE_SET	0x003A					/* (58) set extended profile */
+#define		CP_CMD_PING				0x03E8					/* (1000) ping (keepalive) */
+
+/* HTTP connection */
+#define		MXIT_HTTP_POLL_MIN		7						/* minimum time between HTTP polls (seconds) */
+#define		MXIT_HTTP_POLL_MAX		( 10 * 60 )				/* maximum time between HTTP polls (seconds) */
+
+/* receiver states */
+#define		RX_STATE_RLEN			0x01					/* reading packet length section */
+#define		RX_STATE_DATA			0x02					/* reading packet data section */
+#define		RX_STATE_PROC			0x03					/* process read data */
+
+/* message flags */
+#define		CP_MSG_NOTIFY_DELIVERY	0x0002					/* request delivery notification */
+#define		CP_MSG_NOTIFY_READ		0x0004					/* request read notification */
+#define		CP_MSG_PWD_ENCRYPTED	0x0010					/* message is password encrypted */
+#define		CP_MSG_TL_ENCRYPTED		0x0020					/* message is transport encrypted */
+#define		CP_MSG_RPLY_PWD_ENCRYPT	0x0040					/* reply should be password encrypted */
+#define		CP_MSG_RPLY_TL_ENCRYPT	0x0080					/* reply should be transport encrypted */
+#define		CP_MSG_MARKUP			0x0200					/* message may contain markup */
+#define		CP_MSG_EMOTICON			0x0400					/* message may contain custom emoticons */
+#define		CP_MSG_FAREWELL			0x0800					/* this is a farewell message */
+
+/* redirect types */
+#define		CP_REDIRECT_PERMANENT	1						/* permanent redirect */
+#define		CP_REDIRECT_TEMPORARY	2						/* temporary redirect */
+
+/* message tx types */
+#define		CP_MSGTYPE_NORMAL		0x01					/* normal message */
+#define		CP_MSGTYPE_CHAT			0x02					/* chat message */
+#define		CP_MSGTYPE_HEADLINE		0x03					/* headline message */
+#define		CP_MSGTYPE_ERROR		0x04					/* error message */
+#define		CP_MSGTYPE_GROUPCHAT	0x05					/* groupchat message */
+#define		CP_MSGTYPE_FORM			0x06					/* mxit custom form */
+#define		CP_MSGTYPE_COMMAND		0x07					/* mxit command */
+
+/* message event types */
+#define		CP_MSGEVENT_DELIVERED	0x02					/* message was delivered */
+#define		CP_MSGEVENT_DISPLAYED	0x04					/* message was viewed */
+#define		CP_MSGEVENT_TYPING		0x10					/* user is typing */
+#define		CP_MSGEVENT_STOPPED		0x20					/* user has stopped typing */
+#define		CP_MSGEVENT_ANGRY		0x40					/* user is typing angrily */
+#define		CP_MSGEVENT_ERASING		0x80					/* user is erasing text */
+
+/* extended profile attribute fields */
+#define		CP_PROFILE_BIRTHDATE	"birthdate"				/* Birthdate (String - ISO 8601 format) */
+#define		CP_PROFILE_GENDER		"gender"				/* Gender (Boolean - 0=female, 1=male) */
+// #define		CP_PROFILE_HIDENUMBER	"hidenumber"			/* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */
+#define		CP_PROFILE_FULLNAME		"fullname"				/* Fullname (UTF8 String) */
+#define		CP_PROFILE_STATUS		"statusmsg"				/* Status Message (UTF8 String) */
+#define		CP_PROFILE_PREVSTATUS	"prevstatusmsgs"		/* Previous Status Messages (UTF8 String) */
+#define		CP_PROFILE_AVATAR		"avatarid"				/* Avatar ID (String) */
+#define		CP_PROFILE_MODIFIED		"lastmodified"			/* Last-Modified timestamp */
+#define		CP_PROFILE_TITLE		"title"					/* Title (UTF8 String) */
+#define		CP_PROFILE_FIRSTNAME	"firstname"				/* First name (UTF8 String) */
+#define		CP_PROFILE_LASTNAME		"lastname"				/* Last name (UTF8 String) */
+#define		CP_PROFILE_EMAIL		"email"					/* Email address (UTF8 String) */
+#define		CP_PROFILE_MOBILENR		"mobilenumber"			/* Mobile Number (UTF8 String) */
+#define		CP_PROFILE_REGCOUNTRY	"registeredcountry"		/* Registered Country Code (UTF8 String) */
+#define		CP_PROFILE_FLAGS		"flags"					/* Profile flags (Bitset) */
+#define		CP_PROFILE_LASTSEEN		"lastseen"				/* Last-Online timestamp */
+#define		CP_PROFILE_WHEREAMI		"whereami"				/* Where am I / Where I live */
+#define		CP_PROFILE_ABOUTME		"aboutme"				/* About me */
+#define		CP_PROFILE_RELATIONSHIP	"relationship"			/* Relationship Status */
+
+/* extended profile field types */
+#define		CP_PROFILE_TYPE_BOOL	0x02					/* boolean (0 or 1) */
+#define		CP_PROFILE_TYPE_SHORT	0x04					/* short (16-bit) */
+#define		CP_PROFILE_TYPE_INT		0x05					/* integer (32-bit) */
+#define		CP_PROFILE_TYPE_LONG	0x06					/* long (64-bit) */
+#define		CP_PROFILE_TYPE_UTF8	0x0A					/* UTF8 string */
+#define		CP_PROFILE_TYPE_DATE	0x0B					/* date-time (ISO 8601 format) */
+
+/* profile flags */
+#define		CP_PROF_NOT_SEARCHABLE	0x02					/* user cannot be searched for */
+#define		CP_PROF_NOT_SUGGESTABLE	0x08					/* user cannot be suggested as friend */
+#define		CP_PROF_DOBLOCKED		0x40					/* date-of-birth cannot be changed */
+
+/* suggestion types */
+#define		CP_SUGGEST_ADDRESSBOOK	0						/* address book search */
+#define		CP_SUGGEST_FRIENDS		1						/* suggested friends */
+#define		CP_SUGGEST_SEARCH		2						/* free-text search */
+#define		CP_SUGGEST_MXITID		3						/* MXitId search */
+
+/* define this to enable protocol debugging (very verbose logging) */
+#define		DEBUG_PROTOCOL
+
+
+/* ======================================================================================= */
+
+struct MXitSession;
+
+/*------------------------------------------*/
+
+struct field {
+	char*				data;
+	int					len;
+};
+
+struct record {
+	struct field**		fields;
+	int					fcount;
+};
+
+struct rx_packet {
+	int					cmd;
+	int					errcode;
+	char*				errmsg;
+	struct record**		records;
+	int					rcount;
+};
+
+struct tx_packet {
+	int					cmd;
+	char				header[256];
+	int					headerlen;
+	char*				data;
+	int					datalen;
+};
+
+/*------------------------------------------*/
+
+
+/*
+ * A received message data object
+ */
+struct RXMsgData {
+	struct MXitSession*		session;					/* MXit session object */
+	char*					from;						/* the sender's name */
+	time_t					timestamp;					/* time at which the message was sent */
+	GString*				msg;						/* newly created message converted to libPurple formatting */
+	gboolean				got_img;					/* flag to say if this message got any images/emoticons embedded */
+	short					img_count;					/* the amount of images/emoticons still outstanding for the message */
+	int						chatid;						/* multimx chatroom id */
+	int						flags;						/* libPurple conversation flags */
+	gboolean				converted;					/* true if the message has been completely parsed and converted to libPurple markup */
+	gboolean				processed;					/* the message has been processed completely and should be freed up */
+};
+
+
+
+/*
+ * The packet transmission queue.
+ */
+struct tx_queue {
+	struct tx_packet*	packets[MAX_QUEUE_SIZE];		/* array of packet pointers */
+	int					count;							/* number of packets queued */
+	int					rd_i;							/* queue current read index (queue offset for reading a packet) */
+	int					wr_i;							/* queue current write index (queue offset for adding new packet) */
+};
+
+
+/* ======================================================================================= */
+
+void mxit_popup( int type, const char* heading, const char* message );
+void mxit_strip_domain( char* username );
+gboolean find_active_chat( const GList* chats, const char* who );
+
+void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond );
+gboolean mxit_manage_queue_slow( gpointer user_data );
+gboolean mxit_manage_queue_fast( gpointer user_data );
+gboolean mxit_manage_polling( gpointer user_data );
+
+void mxit_send_register( struct MXitSession* session );
+void mxit_send_login( struct MXitSession* session );
+void mxit_send_logout( struct MXitSession* session );
+void mxit_send_ping( struct MXitSession* session );
+void mxit_send_poll( struct MXitSession* session );
+
+void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg );
+void mxit_send_mood( struct MXitSession* session, int mood );
+void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command );
+
+void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes );
+void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] );
+
+void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] );
+void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] );
+
+void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message );
+void mxit_send_remove( struct MXitSession* session, const char* username );
+void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias );
+void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason );
+void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname );
+void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
+void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
+
+void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
+void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
+void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset );
+void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
+void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen );
+void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
+
+void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
+void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] );
+
+int mxit_parse_packet( struct MXitSession* session );
+void dump_bytes( struct MXitSession* session, const char* buf, int len );
+void mxit_close_connection( struct MXitSession* session );
+gint64 mxit_now_milli( void );
+
+
+#endif		/* _MXIT_PROTO_H_ */
+
--- a/libpurple/protocols/mxit/filexfer.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/filexfer.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 #include	"internal.h"
 #include	"debug.h"
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"mxit.h"
 #include	"chunk.h"
 #include	"filexfer.h"
--- a/libpurple/protocols/mxit/formcmds.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/formcmds.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "debug.h"
 #include "http.h"
 
-#include "protocol.h"
+#include "client.h"
 #include "mxit.h"
 #include "markup.h"
 #include "formcmds.h"
--- a/libpurple/protocols/mxit/formcmds.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/formcmds.h	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 #ifndef		_MXIT_FORMCMDS_H_
 #define		_MXIT_FORMCMDS_H_
 
-#include	"protocol.h"
+#include	"client.h"
 
 int mxit_parse_command(struct RXMsgData* mx, char* message);
 
--- a/libpurple/protocols/mxit/login.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/login.c	Sun Aug 18 01:53:00 2013 +0530
@@ -29,7 +29,7 @@
 #include	"request.h"
 #include	"version.h"
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"mxit.h"
 #include	"cipher.h"
 #include	"login.h"
--- a/libpurple/protocols/mxit/markup.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/markup.c	Sun Aug 18 01:53:00 2013 +0530
@@ -27,7 +27,7 @@
 #include	"debug.h"
 #include	"http.h"
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"mxit.h"
 #include	"markup.h"
 #include	"chunk.h"
--- a/libpurple/protocols/mxit/multimx.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/multimx.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 #include "internal.h"
 #include "debug.h"
 
-#include "protocol.h"
+#include "client.h"
 #include "mxit.h"
 #include "multimx.h"
 #include "markup.h"
--- a/libpurple/protocols/mxit/mxit.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/mxit.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,10 +26,11 @@
 #include	"internal.h"
 #include	"debug.h"
 #include	"accountopt.h"
+#include	"plugins.h"
 #include	"version.h"
 
 #include	"mxit.h"
-#include	"protocol.h"
+#include	"client.h"
 #include	"login.h"
 #include	"roster.h"
 #include	"chunk.h"
@@ -716,8 +717,10 @@
 
 /*========================================================================================================================*/
 
-static PurplePluginProtocolInfo proto_info = {
-	sizeof( PurplePluginProtocolInfo ),		/* struct_size */
+static PurpleProtocol proto_info = {
+	MXIT_PLUGIN_ID,			/* protocol id (must be unique) */
+	MXIT_PLUGIN_NAME,		/* protocol name (this will be displayed in the UI) */
+	sizeof( PurpleProtocol ),		/* struct_size */
 	OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE,	/* options */
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
@@ -728,6 +731,7 @@
 		CP_MAX_FILESIZE,									/* max filesize */
 		PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY	/* scaling rules */
 	},
+	mxit_get_actions,		/* get_actions				[actions.c] */
 	mxit_list_icon,			/* list_icon */
 	mxit_list_emblem,		/* list_emblem */
 	mxit_status_text,		/* status_text */
@@ -782,7 +786,7 @@
 	mxit_xfer_tx,			/* send_file				[filexfer.c */
 	mxit_xfer_new,			/* new_xfer					[filexfer.c] */
 	mxit_offline_message,	/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
+	NULL,					/* whiteboard_protocol_ops */
 	NULL,					/* send_raw */
 	NULL,					/* roomlist_room_serialize */
 	NULL,					/* unregister_user */
@@ -797,48 +801,37 @@
 };
 
 
-static PurplePluginInfo plugin_info = {
-	PURPLE_PLUGIN_MAGIC,								/* purple magic, this must always be PURPLE_PLUGIN_MAGIC */
-	PURPLE_MAJOR_VERSION,								/* libpurple version */
-	PURPLE_MINOR_VERSION,								/* libpurple version */
-	PURPLE_PLUGIN_PROTOCOL,								/* plugin type (connecting to another network) */
-	NULL,												/* UI requirement (NULL for core plugin) */
-	0,													/* plugin flags (zero is default) */
-	NULL,												/* plugin dependencies (set this value to NULL no matter what) */
-	PURPLE_PRIORITY_DEFAULT,							/* libpurple priority */
-
-	MXIT_PLUGIN_ID,										/* plugin id (must be unique) */
-	MXIT_PLUGIN_NAME,									/* plugin name (this will be displayed in the UI) */
-	DISPLAY_VERSION,									/* version of the plugin */
-
-	MXIT_PLUGIN_SUMMARY,								/* short summary of the plugin */
-	MXIT_PLUGIN_DESC,									/* description of the plugin (can be long) */
-	MXIT_PLUGIN_EMAIL,									/* plugin author name and email address */
-	MXIT_PLUGIN_WWW,									/* plugin website (to find new versions and reporting of bugs) */
-
-	NULL,												/* function pointer for loading the plugin */
-	NULL,												/* function pointer for unloading the plugin */
-	NULL,												/* function pointer for destroying the plugin */
-
-	NULL,												/* pointer to an UI-specific struct */
-	&proto_info,										/* pointer to either a PurplePluginLoaderInfo or PurplePluginProtocolInfo struct */
-	NULL,												/* pointer to a PurplePluginUiInfo struct */
-	mxit_actions,										/* function pointer where you can define plugin-actions */
-
-	/* padding */
-	NULL,												/* pointer reserved for future use */
-	NULL,												/* pointer reserved for future use */
-	NULL,												/* pointer reserved for future use */
-	NULL												/* pointer reserved for future use */
-};
+/*------------------------------------------------------------------------
+ * Querying the MXit plugin.
+ *
+ *  @param error	Query error (if any)
+ */
+static PurplePluginInfo *plugin_query( GError **error )
+{
+	return purple_plugin_info_new(
+		"id",			MXIT_PLUGIN_ID,			/* plugin id (must be unique) */
+		"name",			MXIT_PLUGIN_NAME,		/* plugin name (this will be displayed in the UI) */
+		"version",		DISPLAY_VERSION,		/* version of the plugin */
+		"category",		MXIT_PLUGIN_CATEGORY,	/* category of the plugin */
+		"summary",		MXIT_PLUGIN_SUMMARY,	/* short summary of the plugin */
+		"description",	MXIT_PLUGIN_DESC,		/* description of the plugin (can be long) */
+		"author",		MXIT_PLUGIN_AUTHOR,		/* plugin author name and email address */
+		"website",		MXIT_PLUGIN_WWW,		/* plugin website (to find new versions and reporting of bugs) */
+		"abi-version",	PURPLE_ABI_VERSION,		/* ABI version required by the plugin */
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
 
 /*------------------------------------------------------------------------
- * Initialising the MXit plugin.
+ * Loading the MXit plugin.
  *
  *  @param plugin	The plugin object
+ *  @param error	Load error (if any)
  */
-static void init_plugin( PurplePlugin* plugin )
+static gboolean plugin_load( PurplePlugin* plugin, GError **error )
 {
 	PurpleAccountOption*	option;
 
@@ -853,7 +846,25 @@
 
 	option = purple_account_option_bool_new( _( "Enable splash-screen popup" ), MXIT_CONFIG_SPLASHPOPUP, FALSE );
 	proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
+
+	purple_protocols_add( &proto_info );
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN( mxit, init_plugin, plugin_info );
 
+/*------------------------------------------------------------------------
+ * Unloading the MXit plugin.
+ *
+ *  @param plugin	The plugin object
+ *  @param error	Unload error (if any)
+ */
+static gboolean plugin_unload( PurplePlugin* plugin, GError **error )
+{
+	purple_protocols_remove( &proto_info );
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT( mxit, plugin_query, plugin_load, plugin_unload );
+
--- a/libpurple/protocols/mxit/mxit.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/mxit.h	Sun Aug 18 01:53:00 2013 +0530
@@ -57,14 +57,15 @@
 #endif
 
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"profile.h"
 
 
 /* Plugin details */
 #define		MXIT_PLUGIN_ID				"prpl-loubserp-mxit"
 #define		MXIT_PLUGIN_NAME			"MXit"
-#define		MXIT_PLUGIN_EMAIL			"Pieter Loubser <libpurple@mxit.com>"
+#define		MXIT_PLUGIN_CATEGORY		"Protocol"
+#define		MXIT_PLUGIN_AUTHOR			"Pieter Loubser <libpurple@mxit.com>"
 #define		MXIT_PLUGIN_WWW				"http://www.mxit.com"
 #define		MXIT_PLUGIN_SUMMARY			"MXit Protocol Plugin"
 #define		MXIT_PLUGIN_DESC			"MXit"
--- a/libpurple/protocols/mxit/protocol.c	Sun Aug 18 01:52:32 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2953 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- MXit client protocol implementation --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include	"internal.h"
-#include	"debug.h"
-#include	"version.h"
-
-#include	"protocol.h"
-#include	"mxit.h"
-#include	"roster.h"
-#include	"chunk.h"
-#include	"filexfer.h"
-#include	"markup.h"
-#include	"multimx.h"
-#include	"splashscreen.h"
-#include	"login.h"
-#include	"formcmds.h"
-#include	"http.h"
-#include	"cipher.h"
-#include	"voicevideo.h"
-
-
-#define		MXIT_MS_OFFSET		3
-
-/* configure the right record terminator char to use */
-#define		CP_REC_TERM			( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM )
-
-
-/*------------------------------------------------------------------------
- * return the current timestamp in milliseconds
- */
-gint64 mxit_now_milli( void )
-{
-	GTimeVal	now;
-
-	g_get_current_time( &now );
-
-	return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) );
-}
-
-
-/*------------------------------------------------------------------------
- * Display a notification popup message to the user.
- *
- *  @param type			The type of notification:
- *		- info:		PURPLE_NOTIFY_MSG_INFO
- *		- warning:	PURPLE_NOTIFY_MSG_WARNING
- *		- error:	PURPLE_NOTIFY_MSG_ERROR
- *  @param heading		Heading text
- *  @param message		Message text
- */
-void mxit_popup( int type, const char* heading, const char* message )
-{
-	/* (reference: "libpurple/notify.h") */
-	purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL );
-}
-
-
-/*------------------------------------------------------------------------
- * For compatibility with legacy clients, all usernames are sent from MXit with a domain
- *  appended.  For MXit contacts, this domain is set to "@m".  This function strips
- *  those fake domains.
- *
- *  @param username		The username of the contact
- */
-void mxit_strip_domain( char* username )
-{
-	if ( g_str_has_suffix( username, "@m" ) )
-		username[ strlen( username ) - 2 ] = '\0';
-}
-
-
-/*------------------------------------------------------------------------
- * Dump a byte buffer to the console for debugging purposes.
- *
- *  @param buf			The data
- *  @param len			The data length
- */
-void dump_bytes( struct MXitSession* session, const char* buf, int len )
-{
-	char*	msg	= g_malloc0( len + 1 );
-	int		i;
-
-	for ( i = 0; i < len; i++ ) {
-		char ch	= buf[i];
-
-		if ( ch == CP_REC_TERM )		/* record terminator */
-			msg[i] = '!';
-		else if ( ch == CP_FLD_TERM )	/* field terminator */
-			msg[i] = '^';
-		else if ( ch == CP_PKT_TERM )	/* packet terminator */
-			msg[i] = '@';
-		else if ( ( ch < 0x20 ) || ( ch > 0x7E ) )		/* non-printable character */
-			msg[i] = '_';
-		else
-			msg[i] = ch;
-	}
-
-	purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg );
-
-	g_free( msg );
-}
-
-
-/*------------------------------------------------------------------------
- * Determine if we have an active chat with a specific contact
- *
- *  @param session		The MXit session object
- *  @param who			The contact name
- *  @return				Return true if we have an active chat with the contact
- */
-gboolean find_active_chat( const GList* chats, const char* who )
-{
-	const GList*	list	= chats;
-	const char*		chat	= NULL;
-
-	while ( list ) {
-		chat = (const char*) list->data;
-
-		if ( strcmp( chat, who ) == 0 )
-			return TRUE;
-
-		list = g_list_next( list );
-	}
-
-	return FALSE;
-}
-
-
-/*========================================================================================================================
- * Low-level Packet transmission
- */
-
-/*------------------------------------------------------------------------
- * Remove next packet from transmission queue.
- *
- *  @param session		The MXit session object
- *  @return				The next packet for transmission (or NULL)
- */
-static struct tx_packet* pop_tx_packet( struct MXitSession* session )
-{
-	struct tx_packet*	packet	= NULL;
-
-	if ( session->queue.count > 0 ) {
-		/* dequeue the next packet */
-		packet = session->queue.packets[session->queue.rd_i];
-		session->queue.packets[session->queue.rd_i] = NULL;
-		session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE;
-		session->queue.count--;
-	}
-
-	return packet;
-}
-
-
-/*------------------------------------------------------------------------
- * Add packet to transmission queue.
- *
- *  @param session		The MXit session object
- *  @param packet		The packet to transmit
- *  @return				Return TRUE if packet was enqueue, or FALSE if queue is full.
- */
-static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet )
-{
-	if ( session->queue.count < MAX_QUEUE_SIZE ) {
-		/* enqueue packet */
-		session->queue.packets[session->queue.wr_i] = packet;
-		session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE;
-		session->queue.count++;
-		return TRUE;
-	}
-	else
-		return FALSE;		/* queue is full */
-}
-
-
-/*------------------------------------------------------------------------
- * Deallocate transmission packet.
- *
- *  @param packet		The packet to deallocate.
- */
-static void free_tx_packet( struct tx_packet* packet )
-{
-	g_free( packet->data );
-	g_free( packet );
-	packet = NULL;
-}
-
-
-/*------------------------------------------------------------------------
- * Flush all the packets from the tx queue and release the resources.
- *
- *  @param session		The MXit session object
- */
-static void flush_queue( struct MXitSession* session )
-{
-	struct tx_packet*	packet;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" );
-
-	while ( (packet = pop_tx_packet( session ) ) != NULL )
-		free_tx_packet( packet );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 3: Write the packet data to the TCP connection.
- *
- *  @param fd			The file descriptor
- *  @param pktdata		The packet data
- *  @param pktlen		The length of the packet data
- *  @return				Return -1 on error, otherwise 0
- */
-static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen )
-{
-	int		written;
-	int		res;
-
-	written = 0;
-	while ( written < pktlen ) {
-		res = write( fd, &pktdata[written], pktlen - written );
-		if ( res <= 0 ) {
-			/* error on socket */
-			if ( errno == EAGAIN )
-				continue;
-
-			purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res );
-			return -1;
-		}
-		written += res;
-	}
-
-	return 0;
-}
-
-
-/**
- * Callback called for handling a HTTP GET response
- *
- * @param http_conn http api object (see http.h)
- * @param response  http api object (see http.h)
- * @param _session  The MXit session object
- */
-static void
-mxit_cb_http_rx(PurpleHttpConnection *http_conn, PurpleHttpResponse *response,
-	gpointer _session)
-{
-	struct MXitSession *session = _session;
-	const gchar *got_data;
-	size_t got_len;
-
-	if (!purple_http_response_is_successful(response)) {
-		purple_debug_error(MXIT_PLUGIN_ID, "HTTP response error (%s)\n",
-			purple_http_response_get_error(response));
-		return;
-	}
-
-	/* convert the HTTP result */
-	got_data = purple_http_response_get_data(response, &got_len);
-	memcpy(session->rx_dbuf, got_data, got_len);
-	session->rx_i = got_len;
-
-	mxit_parse_packet(session);
-}
-
-
-/**
- * TX Step 3: Write the packet data to the HTTP connection (GET style).
- *
- * @param session The MXit session object
- * @param packet  The packet data
- */
-static void
-mxit_write_http_get(struct MXitSession* session, struct tx_packet* packet)
-{
-	PurpleHttpRequest *req;
-	char *part = NULL;
-
-	if (packet->datalen > 0) {
-		char *tmp;
-
-		tmp = g_strndup(packet->data, packet->datalen);
-		part = g_strdup(purple_url_encode(tmp));
-		g_free(tmp);
-	}
-
-	req = purple_http_request_new(NULL);
-	purple_http_request_set_url_printf(req, "%s?%s%s", session->http_server,
-		purple_url_encode(packet->header), part ? part : "");
-	purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT);
-	purple_http_connection_set_add(session->async_http_reqs,
-		purple_http_request(session->con, req, mxit_cb_http_rx,
-			session));
-	purple_http_request_unref(req);
-
-	g_free(part);
-}
-
-
-/**
- * TX Step 3: Write the packet data to the HTTP connection (POST style).
- *
- * @param session The MXit session object
- * @param packet  The packet data
- */
-static void
-mxit_write_http_post(struct MXitSession* session, struct tx_packet* packet)
-{
-	PurpleHttpRequest *req;
-
-	/* strip off the last '&' from the header */
-	packet->header[packet->headerlen - 1] = '\0';
-	packet->headerlen--;
-
-	req = purple_http_request_new(NULL);
-	purple_http_request_set_url_printf(req, "%s?%s", session->http_server,
-		purple_url_encode(packet->header));
-	purple_http_request_set_method(req, "POST");
-	purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT);
-	purple_http_request_header_set(req, "Content-Type",
-		"application/octet-stream");
-	purple_http_request_set_contents(req, packet->data + MXIT_MS_OFFSET,
-		packet->datalen - MXIT_MS_OFFSET);
-	purple_http_connection_set_add(session->async_http_reqs,
-		purple_http_request(session->con, req, mxit_cb_http_rx,
-			session));
-	purple_http_request_unref(req);
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 2: Handle the transmission of the packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param packet		The packet to transmit
- */
-static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet )
-{
-	int		res;
-
-	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-		/* we are not connected so ignore all packets to be send */
-		purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" );
-		return;
-	}
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen );
-#ifdef	DEBUG_PROTOCOL
-	dump_bytes( session, packet->header, packet->headerlen );
-	dump_bytes( session, packet->data, packet->datalen );
-#endif
-
-	if ( !session->http ) {
-		/* socket connection */
-		char		data[packet->datalen + packet->headerlen];
-		int			datalen;
-
-		/* create raw data buffer */
-		memcpy( data, packet->header, packet->headerlen );
-		memcpy( data + packet->headerlen, packet->data, packet->datalen );
-		datalen = packet->headerlen + packet->datalen;
-
-		res = mxit_write_sock_packet( session->fd, data, datalen );
-		if ( res < 0 ) {
-			/* we must have lost the connection, so terminate it so that we can reconnect */
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "We have lost the connection to MXit. Please reconnect." ) );
-		}
-	}
-	else {
-		/* http connection */
-
-		if ( packet->cmd == CP_CMD_MEDIA ) {
-			/* multimedia packets must be send with a HTTP POST */
-			mxit_write_http_post( session, packet );
-		}
-		else {
-			mxit_write_http_get( session, packet );
-		}
-	}
-
-	/* update the timestamp of the last-transmitted packet */
-	session->last_tx = mxit_now_milli();
-
-	/*
-	 * we need to remember that we are still waiting for the ACK from
-	 * the server on this request
-	 */
-	session->outack = packet->cmd;
-
-	/* free up the packet resources */
-	free_tx_packet( packet );
-}
-
-
-/*------------------------------------------------------------------------
- * TX Step 1: Create a new Tx packet and queue it for sending.
- *
- *  @param session		The MXit session object
- *  @param data			The packet data (payload)
- *  @param datalen		The length of the packet data
- *  @param cmd			The MXit command for this packet
- */
-static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd )
-{
-	struct tx_packet*	packet;
-	char				header[256];
-	int					hlen;
-
-	/* create a packet for sending */
-	packet = g_new0( struct tx_packet, 1 );
-	packet->data = g_malloc0( datalen );
-	packet->cmd = cmd;
-	packet->headerlen = 0;
-
-	/* create generic packet header */
-	hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM );	/* client mxitid */
-
-	if ( session->http ) {
-		/* http connection only */
-		hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" );
-		if ( session->http_sesid > 0 ) {
-			hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM );	/* http session id */
-		}
-		session->http_seqno++;
-		hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM );		/* http request sequence id */
-	}
-
-	hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); 						/* packet command */
-
-	if ( !session->http ) {
-		/* socket connection only */
-		packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM );		/* packet length */
-	}
-
-	/* copy the header to packet */
-	memcpy( packet->header + packet->headerlen, header, hlen );
-	packet->headerlen += hlen;
-
-	/* copy payload to packet */
-	if ( datalen > 0 )
-		memcpy( packet->data, data, datalen );
-	packet->datalen = datalen;
-
-
-	/* shortcut */
-	if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) {
-		/* the queue is empty and there are no outstanding acks so we can write it directly */
-		mxit_send_packet( session, packet );
-	}
-	else {
-		/* we need to queue this packet */
-
-		if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) {
-			/* we do NOT queue HTTP poll nor socket ping packets */
-			free_tx_packet( packet );
-			return;
-		}
-
-		purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd );
-		if ( !push_tx_packet( session, packet ) ) {
-			/* packet could not be queued for transmission */
-			mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) );
-			free_tx_packet( packet );
-		}
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Manage the packet send queue (send next packet, timeout's, etc).
- *
- *  @param session		The MXit session object
- */
-static void mxit_manage_queue( struct MXitSession* session )
-{
-	struct tx_packet*	packet		= NULL;
-	gint64				now			= mxit_now_milli();
-
-	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-		/* we are not connected, so ignore the queue */
-		return;
-	}
-	else if ( session->outack > 0 ) {
-		/* we are still waiting for an outstanding ACK from the MXit server */
-		if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
-			/* ack timeout! so we close the connection here */
-			purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Timeout while waiting for a response from the MXit server." ) );
-		}
-		return;
-	}
-
-	/*
-	 * the mxit server has flood detection and it prevents you from sending messages to fast.
-	 * this is a self defense mechanism, a very annoying feature. so the client must ensure that
-	 * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds.
-	 * this is what we are trying to avoid here..
-	 */
-	if ( session->q_fast_timer_id == 0 ) {
-		/* the fast timer has not been set yet */
-		if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) {
-			/* we need to wait a little before sending the next packet, so schedule a wakeup call */
-			gint64 tdiff = now - ( session->last_tx );
-			guint delay = ( MXIT_TX_DELAY - tdiff ) + 9;
-			if ( delay <= 0 )
-				delay = MXIT_TX_DELAY;
-			session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session );
-		}
-		else {
-			/* get the next packet from the queue to send */
-			packet = pop_tx_packet( session );
-			if ( packet != NULL ) {
-				/* there was a packet waiting to be sent to the server, now is the time to do something about it */
-
-				/* send the packet to MXit server */
-				mxit_send_packet( session, packet );
-			}
-		}
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Slow callback to manage the packet send queue.
- *
- *  @param session		The MXit session object
- */
-gboolean mxit_manage_queue_slow( gpointer user_data )
-{
-	struct MXitSession* session		= (struct MXitSession*) user_data;
-
-	mxit_manage_queue( session );
-
-	/* continue running */
-	return TRUE;
-}
-
-
-/*------------------------------------------------------------------------
- * Fast callback to manage the packet send queue.
- *
- *  @param session		The MXit session object
- */
-gboolean mxit_manage_queue_fast( gpointer user_data )
-{
-	struct MXitSession* session		= (struct MXitSession*) user_data;
-
-	session->q_fast_timer_id = 0;
-	mxit_manage_queue( session );
-
-	/* stop running */
-	return FALSE;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback to manage HTTP server polling (HTTP connections ONLY)
- *
- *  @param session		The MXit session object
- */
-gboolean mxit_manage_polling( gpointer user_data )
-{
-	struct MXitSession* session		= (struct MXitSession*) user_data;
-	gboolean			poll		= FALSE;
-	gint64				now			= mxit_now_milli();
-	gint64				rxdiff;
-
-	if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
-		/* we only poll if we are actually logged in */
-		return TRUE;
-	}
-
-	/* calculate the time differences */
-	rxdiff = now - session->last_rx;
-
-	if ( rxdiff < MXIT_HTTP_POLL_MIN ) {
-		/* we received some reply a few moments ago, so reset the poll interval */
-		session->http_interval = MXIT_HTTP_POLL_MIN;
-	}
-	else if ( session->http_last_poll < ( now - session->http_interval ) ) {
-		/* time to poll again */
-		poll = TRUE;
-
-		/* back-off some more with the polling */
-		session->http_interval = session->http_interval + ( session->http_interval / 2 );
-		if ( session->http_interval > MXIT_HTTP_POLL_MAX )
-			session->http_interval = MXIT_HTTP_POLL_MAX;
-	}
-
-	/* debugging */
-	//purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i)\n", session->http_interval, rxdiff );
-
-	if ( poll ) {
-		/* send poll request */
-		session->http_last_poll = mxit_now_milli();
-		mxit_send_poll( session );
-	}
-
-	return TRUE;
-}
-
-
-/*========================================================================================================================
- * Send MXit operations.
- */
-
-/*------------------------------------------------------------------------
- * Send a ping/keepalive packet to MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_ping( struct MXitSession* session )
-{
-	/* queue packet for transmission */
-	mxit_queue_packet( session, NULL, 0, CP_CMD_PING );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a poll request to the HTTP server (HTTP connections ONLY).
- *
- *  @param session		The MXit session object
- */
-void mxit_send_poll( struct MXitSession* session )
-{
-	/* queue packet for transmission */
-	mxit_queue_packet( session, NULL, 0, CP_CMD_POLL );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a logout packet to the MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_logout( struct MXitSession* session )
-{
-	/* queue packet for transmission */
-	mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a register packet to the MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_register( struct MXitSession* session )
-{
-	struct MXitProfile*	profile		= session->profile;
-	const char*			locale;
-	char				data[CP_MAX_PACKET];
-	int					datalen;
-	char*				clientVersion;
-	unsigned int		features	= MXIT_CP_FEATURES;
-
-	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
-
-	/* Voice and Video supported */
-	if ( mxit_audio_enabled() && mxit_video_enabled() )
-		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
-	else if ( mxit_audio_enabled() )
-		features |= MXIT_CF_VOICE;
-
-	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
-	clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i%c%s%c"		/* "ms"=password\1version\1maxreplyLen\1name\1 */
-								"%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,
-								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
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER );
-
-	g_free( clientVersion );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a login packet to the MXit server.
- *
- *  @param session		The MXit session object
- */
-void mxit_send_login( struct MXitSession* session )
-{
-	const char*		splashId;
-	const char*		locale;
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	char*			clientVersion;
-	unsigned int	features	= MXIT_CP_FEATURES;
-
-	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
-
-	/* Voice and Video supported */
-	if ( mxit_audio_enabled() && mxit_video_enabled() )
-		features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO );
-	else if ( mxit_audio_enabled() )
-		features |= MXIT_CF_VOICE;
-
-	/* generate client version string (eg, P-2.7.10-Y-PURPLE) */
-	clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i%c"			/* "ms"=password\1version\1getContacts\1 */
-								"%s%c%s%c%i%c"				/* capabilities\1dc\1features\1 */
-								"%s%c%s%c"					/* dialingcode\1locale\1 */
-								"%i%c%i%c%i",				/* maxReplyLen\1protocolVer\1lastRosterUpdate */
-								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
-	);
-
-	/* include "custom resource" information */
-	splashId = splash_current( session );
-	if ( splashId != NULL )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
-
-	g_free( clientVersion );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a chat message packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param to			The username of the recipient
- *  @param msg			The message text
- */
-void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command )
-{
-	char		data[CP_MAX_PACKET];
-	char*		markuped_msg;
-	int			datalen;
-	int			msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL );
-
-	/* first we need to convert the markup from libPurple to MXit format */
-	if ( parse_markup )
-		markuped_msg = mxit_convert_markup_tx( msg, &msgtype );
-	else
-		markuped_msg = g_strdup( msg );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i%c%i",		/* "ms"=jid\1msg\1type\1flags */
-								to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
-	);
-
-	/* free the resources */
-	g_free( markuped_msg );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a extended profile request packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		Username who's profile is being requested (NULL = our own)
- *  @param nr_attribs	Number of attributes being requested
- *  @param attribute	The names of the attributes
- */
-void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] )
-{
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	unsigned int	i;
-
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%i",		/* "ms="mxitid\1nr_attributes */
-								( username ? username : "" ), CP_FLD_TERM, nr_attrib
-	);
-
-	/* add attributes */
-	for ( i = 0; i < nr_attrib; i++ )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an update profile packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param password		The new password to be used for logging in (optional)
- *	@param nr_attrib	The number of attributes
- *	@param attributes	String containing the attribute-name, attribute-type and value (seperated by '\01')
- */
-void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes )
-{
-	char			data[CP_MAX_PACKET];
-	gchar**			parts					= NULL;
-	int				datalen;
-	unsigned int	i;
-
-	if ( attributes )
-		parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%i",	/* "ms"=password\1nr_attibutes  */
-								( password ) ? password : "", CP_FLD_TERM, nr_attrib
-	);
-
-	/* add attributes */
-	for ( i = 1; i < nr_attrib * 3; i+=3 ) {
-		if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib );
-			g_strfreev( parts );
-			return;
-		}
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen,
-								"%c%s%c%s%c%s",		/* \1name\1type\1value  */
-								CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
-	}
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET );
-
-	/* freeup the memory */
-	g_strfreev( parts );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to request list of suggested friends.
- *
- *  @param session		The MXit session object
- *  @param max			Maximum number of results to return
- *  @param nr_attribs	Number of attributes being requested
- *  @param attribute	The names of the attributes
- */
-void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] )
-{
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	unsigned int	i;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%i%c%s%c%i%c%i%c%i",	/* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
-								CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
-
-	/* add attributes */
-	for ( i = 0; i < nr_attrib; i++ )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to perform a search for users.
- *
- *  @param session		The MXit session object
- *  @param max			Maximum number of results to return
- *  @param text			The search text
- *  @param nr_attribs	Number of attributes being requested
- *  @param attribute	The names of the attributes
- */
-void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] )
-{
-	char			data[CP_MAX_PACKET];
-	int				datalen;
-	unsigned int	i;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%i%c%s%c%i%c%i%c%i",	/* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
-								CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
-
-	/* add attributes */
-	for ( i = 0; i < nr_attrib; i++ )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a presence update packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param presence		The presence (as per MXit types)
- *  @param statusmsg	The status message (can be NULL)
- */
-void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%i%c",					/* "ms"=show\1status */
-								presence, CP_FLD_TERM
-	);
-
-	/* append status message (if one is set) */
-	if ( statusmsg )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a mood update packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param mood			The mood (as per MXit types)
- */
-void mxit_send_mood( struct MXitSession* session, int mood )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%i",	/* "ms"=mood */
-								mood
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MOOD );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an invite contact packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being invited
- *  @param mxitid		Indicates the username is a MXitId.
- *  @param alias		Our alias for the contact
- *  @param groupname	Group in which contact should be stored.
- *  @param message		Invite message
- */
-void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%s%c%i%c%s%c%i",	/* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
-								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
-								CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
-								( message ? message : "" ), CP_FLD_TERM,
-								( mxitid ? 0 : 1 )
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_INVITE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a remove contact packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being removed
- */
-void mxit_send_remove( struct MXitSession* session, const char* username )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s",	/* "ms"=username */
-								username
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an accept subscription (invite) packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being accepted
- *  @param alias		Our alias for the contact
- */
-void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%s",	/* "ms"=username\1group\1alias */
-								username, CP_FLD_TERM, "", CP_FLD_TERM, alias
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an deny subscription (invite) packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being denied
- *  @param reason		The message describing the reason for the rejection (can be NULL).
- */
-void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s",	/* "ms"=username */
-								username
-	);
-
-	/* append reason (if one is set) */
-	if ( reason )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
-}
-
-
-/*------------------------------------------------------------------------
- * Send an update contact packet to the MXit server.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the contact being denied
- *  @param alias		Our alias for the contact
- *  @param groupname	Group in which contact should be stored.
- */
-void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%s",	/* "ms"=groupname\1username\1alias */
-								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a splash-screen click event packet.
- *
- *  @param session		The MXit session object
- *  @param splashid		The identifier of the splash-screen
- */
-void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s",	/* "ms"=splashId */
-								splashid
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a message event packet.
- *
- *  @param session		The MXit session object
- *  @param to           The username of the original sender (ie, recipient of the event)
- *  @param id			The identifier of the event (received in message)
- *  @param event		Identified the type of event
- */
-void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%s%c%i",		/* "ms"=contactAddress \1 id \1 event */
-								to, CP_FLD_TERM, id, CP_FLD_TERM, event
-	);
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to create a MultiMX room.
- *
- *  @param session		The MXit session object
- *  @param groupname	Name of the room to create
- *  @param nr_usernames	Number of users in initial invite
- *  @param usernames	The usernames of the users in the initial invite
- */
-void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-	int			i;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%i",	/* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
-								groupname, CP_FLD_TERM, nr_usernames
-	);
-
-	/* add usernames */
-	for ( i = 0; i < nr_usernames; i++ )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send packet to invite users to existing MultiMX room.
- *
- *  @param session		The MXit session object
- *  @param roomid		The unique RoomID for the MultiMx room.
- *  @param nr_usernames	Number of users being invited
- *  @param usernames	The usernames of the users being invited
- */
-void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] )
-{
-	char		data[CP_MAX_PACKET];
-	int			datalen;
-	int			i;
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ),
-								"ms=%s%c%i",	/* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
-								roomid, CP_FLD_TERM, nr_usernames
-	);
-
-	/* add usernames */
-	for ( i = 0; i < nr_usernames; i++ )
-		datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
-
-	/* queue packet for transmission */
-	mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "send file direct" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param username		The username of the recipient
- *  @param filename		The name of the file being sent
- *  @param buf			The content of the file
- *  @param buflen		The length of the file contents
- */
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
-	if ( size < 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
-		return;
-	}
-
-	set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
-	set_chunk_length( chunk, size );
-	datalen += MXIT_CHUNK_HEADER_SIZE + size;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "reject file" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param fileid		A unique ID that identifies this file
- */
-void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
-	if ( size < 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
-		return;
-	}
-
-	set_chunk_type( chunk, CP_CHUNK_REJECT );
-	set_chunk_length( chunk, size );
-	datalen += MXIT_CHUNK_HEADER_SIZE + size;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "get file" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param fileid		A unique ID that identifies this file
- *  @param filesize		The number of bytes to retrieve
- *  @param offset		Offset in file at which to start retrieving
- */
-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
-	if ( size < 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
-		return;
-	}
-
-	set_chunk_type( chunk, CP_CHUNK_GET );
-	set_chunk_length( chunk, size );
-	datalen += MXIT_CHUNK_HEADER_SIZE + size;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "received file" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param status		The status of the file-transfer
- */
-void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
-	if ( size < 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
-		return;
-	}
-
-	set_chunk_type( chunk, CP_CHUNK_RECEIVED );
-	set_chunk_length( chunk, size );
-	datalen += MXIT_CHUNK_HEADER_SIZE + size;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "set avatar" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param data			The avatar data
- *  @param buflen		The length of the avatar data
- */
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
-	if ( size < 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
-		return;
-	}
-
-	set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
-	set_chunk_length( chunk, size );
-	datalen += MXIT_CHUNK_HEADER_SIZE + size;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Send a "get avatar" multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param mxitId		The username who's avatar to request
- *  @param avatarId		The id of the avatar image (as string)
- *  @param data			The avatar data
- *  @param buflen		The length of the avatar data
- */
-void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId )
-{
-	char				data[CP_MAX_PACKET];
-	int					datalen		= 0;
-	gchar*				chunk;
-	int					size;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
-
-	/* convert the packet to a byte stream */
-	datalen = g_snprintf( data, sizeof( data ), "ms=" );
-
-	/* map chunk header over data buffer */
-	chunk = &data[datalen];
-
-	size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
-	if ( size < 0 ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
-		return;
-	}
-
-	set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
-	set_chunk_length( chunk, size );
-	datalen += MXIT_CHUNK_HEADER_SIZE + size;
-
-	/* send the byte stream to the mxit server */
-	mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a login message packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount )
-{
-	PurpleStatus*	status;
-	int				presence;
-	const char*		statusmsg;
-	const char*		profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
-									CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
-									CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP, CP_PROFILE_FLAGS };
-
-	purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-
-	/* we were not yet logged in so we need to complete the login sequence here */
-	session->flags |= MXIT_FLAG_LOGGEDIN;
-	purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 );
-	purple_connection_set_state( session->con, PURPLE_CONNECTION_CONNECTED );
-
-	/* save extra info if this is a HTTP connection */
-	if ( session->http ) {
-		/* save the http server to use for this session */
-		g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
-
-		/* save the session id */
-		session->http_sesid = atoi( records[0]->fields[0]->data );
-	}
-
-	/* extract UserId (from protocol 5.9) */
-	if ( records[1]->fcount >= 9 )
-		session->uid = g_strdup( records[1]->fields[8]->data );
-
-	/* extract VoIP server (from protocol 6.2) */
-	if ( records[1]->fcount >= 11 )
-		g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) );
-
-	/* display the current splash-screen */
-	if ( splash_popup_enabled( session ) )
-		splash_display( session );
-
-	/* update presence status */
-	status = purple_account_get_active_status( session->acc );
-	presence = mxit_convert_presence( purple_status_get_id( status ) );
-	statusmsg = purple_status_get_attr_string( status, "message" );
-
-	if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) {
-		/* when logging into MXit, your default presence is online. but with the UI, one can change
-		 * the presence to whatever. in the case where its changed to a different presence setting
-		 * we need to send an update to the server, otherwise the user's presence will be out of
-		 * sync between the UI and MXit.
-		 */
-		char* statusmsg1 = purple_markup_strip_html( statusmsg );
-		char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
-
-		mxit_send_presence( session, presence, statusmsg2 );
-
-		g_free( statusmsg1 );
-		g_free( statusmsg2 );
-	}
-
-	/* retrieve our MXit profile */
-	mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received message packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount )
-{
-	struct RXMsgData*	mx			= NULL;
-	char*				message		= NULL;
-	char*				sender		= NULL;
-	int					msglen		= 0;
-	int					msgflags	= 0;
-	int					msgtype		= 0;
-
-	if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) {
-		/* packet contains no message or an empty message */
-		return;
-	}
-
-	message = records[1]->fields[0]->data;
-	msglen = strlen( message );
-
-	/* strip off dummy domain */
-	sender = records[0]->fields[0]->data;
-	mxit_strip_domain( sender );
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
-#endif
-
-	/* decode message flags (if any) */
-	if ( records[0]->fcount >= 5 )
-		msgflags = atoi( records[0]->fields[4]->data );
-	msgtype = atoi( records[0]->fields[2]->data );
-
-	if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
-		/* this is a password encrypted message. we do not currently support those so ignore it */
-		PurpleBuddy*	buddy;
-		const char*		name;
-		char			msg[128];
-
-		buddy = purple_blist_find_buddy( session->acc, sender );
-		if ( buddy )
-			name = purple_buddy_get_alias( buddy );
-		else
-			name = sender;
-		g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
-		mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
-		return;
-	}
-	else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
-		/* this is a transport-layer encrypted message. */
-		message = mxit_decrypt_message( session, message );
-		if ( !message ) {
-			/* could not be decrypted */
-			serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
-			return;
-		}
-	}
-
-	if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
-		/* delivery notification is requested */
-		if ( records[0]->fcount >= 4 )
-			mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
-	}
-
-	/* create and initialise new markup struct */
-	mx = g_new0( struct RXMsgData, 1 );
-	mx->msg = g_string_sized_new( msglen );
-	mx->session = session;
-	mx->from = g_strdup( sender );
-	mx->timestamp = atoi( records[0]->fields[1]->data );
-	mx->got_img = FALSE;
-	mx->chatid = -1;
-	mx->img_count = 0;
-
-	/* update list of active chats */
-	if ( !find_active_chat( session->active_chats, mx->from ) ) {
-		session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) );
-	}
-
-	if ( is_multimx_contact( session, mx->from ) ) {
-		/* this is a MultiMx chatroom message */
-		multimx_message_received( mx, message, msglen, msgtype, msgflags );
-	}
-	else {
-		mxit_parse_markup( mx, message, msglen, msgtype, msgflags );
-	}
-
-	/* we are now done parsing the message */
-	mx->converted = TRUE;
-	if ( mx->img_count == 0 ) {
-		/* we have all the data we need for this message to be displayed now. */
-		mxit_show_message( mx );
-	}
-	else {
-		/* this means there are still images outstanding for this message and
-		 * still need to wait for them before we can display the message.
-		 * so the image received callback function will eventually display
-		 * the message. */
-	}
-
-	/* cleanup */
-	if ( msgflags & CP_MSG_TL_ENCRYPTED )
-		g_free( message );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received subscription request packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount )
-{
-	struct contact*		contact;
-	struct record*		rec;
-	int					i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount );
-
-	for ( i = 0; i < rcount; i++ ) {
-		rec = records[i];
-
-		if ( rec->fcount < 4 ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount );
-			break;
-		}
-
-		/* build up a new contact info struct */
-		contact = g_new0( struct contact, 1 );
-
-		g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
-		mxit_strip_domain( contact->username );				/* remove dummy domain */
-		g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
-		contact->type = atoi( rec->fields[2]->data );
-
-		if ( rec->fcount >= 5 ) {
-			/* there is a personal invite message attached */
-			if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) )
-				contact->msg = strdup( rec->fields[4]->data );
-		}
-
-		/* handle the subscription */
-		if ( contact-> type == MXIT_TYPE_MULTIMX ) {		/* subscription to a MultiMX room */
-			char* creator = NULL;
-
-			if ( rec->fcount >= 6 )
-				creator = rec->fields[5]->data;
-
-			multimx_invite( session, contact, creator );
-		}
-		else
-			mxit_new_subscription( session, contact );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Parse the received presence value, and ensure that it is supported.
- *
- *  @param value		The received presence value.
- *  @return				A valid presence value.
- */
-static short mxit_parse_presence( const char* value )
-{
-	short presence = atoi( value );
-
-	/* ensure that the presence value is valid */
-	switch ( presence ) {
-		case MXIT_PRESENCE_OFFLINE :
-		case MXIT_PRESENCE_ONLINE :
-		case MXIT_PRESENCE_AWAY :
-		case MXIT_PRESENCE_DND :
-			return presence;
-
-		default :
-			return MXIT_PRESENCE_ONLINE;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received contact update packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount )
-{
-	struct contact*		contact	= NULL;
-	struct record*		rec;
-	int					i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount );
-
-	for ( i = 0; i < rcount; i++ ) {
-		rec = records[i];
-
-		if ( rec->fcount < 6 ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount );
-			break;
-		}
-
-		/* build up a new contact info struct */
-		contact = g_new0( struct contact, 1 );
-
-		g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
-		g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
-		mxit_strip_domain( contact->username );				/* remove dummy domain */
-		g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
-
-		contact->presence = mxit_parse_presence( rec->fields[3]->data );
-		contact->type = atoi( rec->fields[4]->data );
-		contact->mood = atoi( rec->fields[5]->data );
-
-		if ( rec->fcount > 6 ) {
-			/* added in protocol 5.9 - flags & subtype */
-			contact->flags = atoi( rec->fields[6]->data );
-			contact->subtype = rec->fields[7]->data[0];
-		}
-		if ( rec->fcount > 8 ) {
-			/* added in protocol 6.0 - reject message */
-			contact->msg = g_strdup( rec->fields[8]->data );
-		}
-
-		/* add the contact to the buddy list */
-		if ( contact-> type == MXIT_TYPE_MULTIMX )			/* contact is a MultiMX room */
-			multimx_created( session, contact );
-		else
-			mxit_update_contact( session, contact );
-	}
-
-	if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) {
-		session->flags |= MXIT_FLAG_FIRSTROSTER;
-		mxit_update_blist( session );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received presence update packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount )
-{
-	int					i;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount );
-
-	for ( i = 0; i < rcount; i++ ) {
-		struct record*	rec		= records[i];
-		int				flags	= 0;
-
-		if ( rec->fcount < 6 ) {
-			purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount );
-			break;
-		}
-
-		/*
-		 * The format of the record is:
-		 * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ]
-		 */
-		mxit_strip_domain( rec->fields[0]->data );		/* contactAddress */
-
-		if ( rec->fcount >= 7 )		/* flags field is included */
-			flags = atoi( rec->fields[6]->data );
-
-		mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
-				rec->fields[3]->data, rec->fields[4]->data, flags );
-		mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received extended profile packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount )
-{
-	const char*				mxitId		= records[0]->fields[0]->data;
-	struct MXitProfile*		profile		= NULL;
-	int						count;
-	int						i;
-	const char*				avatarId	= NULL;
-	char*					statusMsg	= NULL;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
-
-	if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
-		/* No UserId or Our UserId provided, so this must be our own profile information */
-		if ( session->profile == NULL )
-			session->profile = g_new0( struct MXitProfile, 1 );
-		profile = session->profile;
-	}
-	else {
-		/* is a buddy's profile */
-		profile = g_new0( struct MXitProfile, 1 );
-	}
-
-	/* set the count for attributes */
-	count = atoi( records[0]->fields[1]->data );
-
-	for ( i = 0; i < count; i++ ) {
-		char* fname;
-		char* fvalue;
-		char* fstatus;
-		int f = ( i * 3 ) + 2;
-
-		fname = records[0]->fields[f]->data;		/* field name */
-		fvalue = records[0]->fields[f + 1]->data;	/* field value */
-		fstatus = records[0]->fields[f + 2]->data;	/* field status */
-
-		/* first check the status on the returned attribute */
-		if ( fstatus[0] != '0' ) {
-			/* error: attribute requested was NOT found */
-			purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname );
-			continue;
-		}
-
-		if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
-			/* birthdate */
-			if ( records[0]->fields[f + 1]->len > 10 ) {
-				fvalue[10] = '\0';
-				records[0]->fields[f + 1]->len = 10;
-			}
-			memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len );
-		}
-		else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
-			/* gender */
-			profile->male = ( fvalue[0] == '1' );
-		}
-		else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
-			/* nickname */
-			g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
-		}
-		else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
-			/* status message - just keep a reference to the value */
-			statusMsg = g_markup_escape_text( fvalue, -1 );
-		}
-		else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
-			/* avatar id - just keep a reference to the value */
-			avatarId = fvalue;
-		}
-		else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
-			/* title */
-			g_strlcpy( profile->title, fvalue, sizeof( profile->title ) );
-		}
-		else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
-			/* first name */
-			g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
-		}
-		else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
-			/* last name */
-			g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
-		}
-		else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) {
-			/* email address */
-			g_strlcpy( profile->email, fvalue, sizeof( profile->email ) );
-		}
-		else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) {
-			/* mobile number */
-			g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
-		}
-		else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
-			/* registered country */
-			g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
-		}
-		else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
-			/* profile flags */
-			profile->flags = g_ascii_strtoll( fvalue, NULL, 10 );
-		}
-		else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
-			/* last seen online */
-			profile->lastonline = g_ascii_strtoll( fvalue, NULL, 10 );
-		}
-		else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
-			/* where am I */
-			g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
-		}
-		else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) {
-			/* about me */
-			g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) );
-		}
-		else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) {
-			/* relatinship status */
-			profile->relationship = strtol( fvalue, NULL, 10 );
-		}
-		else {
-			/* invalid profile attribute */
-			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
-		}
-	}
-
-	if ( profile != session->profile ) {
-		/* not our own profile */
-		struct contact*		contact		= NULL;
-
-		contact = get_mxit_invite_contact( session, mxitId );
-		if ( contact ) {
-			/* this is an invite, so update its profile info */
-			if ( ( statusMsg ) && ( *statusMsg ) ) {
-				/* update the status message */
-				if ( contact->statusMsg )
-					g_free( contact->statusMsg );
-				contact->statusMsg = strdup( statusMsg );
-			}
-			else
-				contact->statusMsg = NULL;
-			if ( contact->profile )
-				g_free( contact->profile );
-			contact->profile = profile;
-			if ( ( avatarId ) && ( *avatarId ) ) {
-				/* avatar must be requested for this invite before we can display it */
-				mxit_get_avatar( session, mxitId, avatarId );
-				if ( contact->avatarId )
-					g_free( contact->avatarId );
-				contact->avatarId = strdup( avatarId );
-			}
-			else {
-				/* display what we have */
-				contact->avatarId = NULL;
-				mxit_show_profile( session, mxitId, profile );
-			}
-		}
-		else {
-			/* this is a contact */
-			if ( avatarId )
-				mxit_update_buddy_avatar( session, mxitId, avatarId );
-
-			if ( ( statusMsg ) && ( *statusMsg ) ) {
-				/* update the status message */
-				PurpleBuddy*		buddy	= NULL;
-
-				buddy = purple_blist_find_buddy( session->acc, mxitId );
-				if ( buddy ) {
-					contact = purple_buddy_get_protocol_data( buddy );
-					if ( contact ) {
-						if ( contact->statusMsg )
-							g_free( contact->statusMsg );
-						contact->statusMsg = strdup( statusMsg );
-					}
-				}
-			}
-
-			/* show the profile */
-			mxit_show_profile( session, mxitId, profile );
-			g_free( profile );
-		}
-	}
-
-	g_free( statusMsg );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received suggest-contacts packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount )
-{
-	GList* entries = NULL;
-	int searchType;
-	int maxResults;
-	int count;
-	int i;
-
-	/*
-	 * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0
-	 * userid \1 contactType \1 value0 \1 value1 ... valueN \0
-	 * ...
-	 * userid \1 contactType \1 value0 \1 value1 ... valueN
-	 */
-
-	/* the type of results */
-	searchType = atoi( records[0]->fields[0]->data );
-
-	/* the maximum number of results */
-	maxResults = atoi( records[0]->fields[2]->data );
-
-	/* set the count for attributes */
-	count = atoi( records[0]->fields[3]->data );
-
-	for ( i = 1; i < rcount; i ++ ) {
-		struct record*		rec		= records[i];
-		struct MXitProfile*	profile	= g_new0( struct MXitProfile, 1 );
-		int j;
-
-		g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
-		// TODO: ContactType - User or Service
-
-		for ( j = 0; j < count; j++ ) {
-			char* fname;
-			char* fvalue = "";
-
-			fname = records[0]->fields[4 + j]->data;		/* field name */
-			if ( records[i]->fcount > ( 2 + j ) )
-				fvalue = records[i]->fields[2 + j]->data;	/* field value */
-
-			purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue );
-
-			if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
-				/* birthdate */
-				g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) );
-			}
-			else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
-				/* first name */
-				g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
-			}
-			else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
-				/* last name */
-				g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
-			}
-			else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
-				/* gender */
-				profile->male = ( fvalue[0] == '1' );
-			}
-			else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
-				/* nickname */
-				g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
-			}
-			else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
-				/* where am I */
-				g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
-			}
-			/* ignore other attibutes */
-		}
-
-		entries = g_list_append( entries, profile );
-	}
-
-	/* display */
-	mxit_show_search_results( session, searchType, maxResults, entries );
-
-	/* cleanup */
-	g_list_foreach( entries, (GFunc)g_free, NULL );
-}
-
-/*------------------------------------------------------------------------
- * Process a received message event packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount )
-{
-	int event;
-
-	/*
-	 * contactAddress \1 dateTime \1 id \1 event
-	 */
-
-	/* strip off dummy domain */
-	mxit_strip_domain( records[0]->fields[0]->data );
-
-	event = atoi( records[0]->fields[3]->data );
-
-	switch ( event ) {
-		case CP_MSGEVENT_TYPING :							/* user is typing */
-		case CP_MSGEVENT_ANGRY :							/* user is typing angrily */
-			serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_IM_TYPING );
-			break;
-
-		case CP_MSGEVENT_STOPPED :							/* user has stopped typing */
-			serv_got_typing_stopped( session->con, records[0]->fields[0]->data );
-			break;
-
-		case CP_MSGEVENT_ERASING :							/* user is erasing text */
-		case CP_MSGEVENT_DELIVERED :						/* message was delivered */
-		case CP_MSGEVENT_DISPLAYED :						/* message was viewed */
-			/* these are currently not supported by libPurple */
-			break;
-
-		default:
-			purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event );
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Return the length of a multimedia chunk
- *
- * @return		The actual chunk data length in bytes
- */
-static int get_chunk_len( const char* chunkdata )
-{
-	int*	sizeptr;
-
-	sizeptr = (int*) &chunkdata[1];		/* we skip the first byte (type field) */
-
-	return ntohl( *sizeptr );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a received multimedia packet.
- *
- *  @param session		The MXit session object
- *  @param records		The packet's data records
- *  @param rcount		The number of data records
- */
-static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
-{
-	char	type;
-	int		size;
-
-	type = records[0]->fields[0]->data[0];
-	size = get_chunk_len( records[0]->fields[0]->data );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
-
-	/* supported chunked data types */
-	switch ( type ) {
-		case CP_CHUNK_CUSTOM :				/* custom resource */
-			{
-				struct cr_chunk chunk;
-
-				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct cr_chunk ) );
-				mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
-
-				/* this is a splash-screen operation */
-				if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
-					if ( chunk.operation == CR_OP_UPDATE ) {		/* update the splash-screen */
-						struct splash_chunk *splash = chunk.resources->data;			// TODO: Fix - assuming 1st resource is splash
-						gboolean clickable = ( g_list_length( chunk.resources ) > 1 );	// TODO: Fix - if 2 resources, then is clickable
-
-						if ( splash != NULL )
-							splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
-					}
-					else if ( chunk.operation == CR_OP_REMOVE )		/* remove the splash-screen */
-						splash_remove( session );
-				}
-
-				/* cleanup custom resources */
-				g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
-
-			}
-			break;
-
-		case CP_CHUNK_OFFER :				/* file offer */
-			{
-				struct offerfile_chunk chunk;
-
-				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
-				mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				/* process the offer */
-				mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
-			}
-			break;
-
-		case CP_CHUNK_GET :					/* get file response */
-			{
-				struct getfile_chunk chunk;
-
-				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct getfile_chunk ) );
-				mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				/* process the getfile */
-				mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
-			}
-			break;
-
-		case CP_CHUNK_GET_AVATAR :			/* get avatars */
-			{
-				struct getavatar_chunk chunk;
-				struct contact* contact = NULL;
-
-				/* decode the chunked data */
-				memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
-				mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				/* update avatar image */
-				if ( chunk.data ) {
-					purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
-
-					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_new_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 );
-					}
-				}
-			}
-			break;
-
-		case CP_CHUNK_SET_AVATAR :
-			/* this is a reply packet to a set avatar request. no action is required */
-			break;
-
-		case CP_CHUNK_DIRECT_SND :
-			/* this is a ack for a file send. */
-			{
-				struct sendfile_chunk chunk;
-
-				memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
-				mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
-
-				purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
-
-				if ( chunk.status != 0 )	/* not success */
-					mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
-			}
-			break;
-
-		case CP_CHUNK_RECEIVED :
-			/* this is a ack for a file received. no action is required */
-			break;
-
-		default :
-			purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
-			break;
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Handle a redirect sent from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param url			The redirect information
- */
-static void mxit_perform_redirect( struct MXitSession* session, const char* url )
-{
-	gchar**		parts;
-	gchar**		host;
-	int			type;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url );
-
-	/* tokenize the URL string */
-	parts = g_strsplit( url, ";", 0 );
-
-	/* Part 1: protocol://host:port */
-	host = g_strsplit( parts[0], ":", 4 );
-	if ( strcmp( host[0], "socket" ) == 0 ) {
-		/* redirect to a MXit socket proxy */
-		g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
-		session->port = atoi( host[2] );
-	}
-	else {
-		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) );
-		goto redirect_fail;
-	}
-
-	/* Part 2: type of redirect */
-	type = atoi( parts[1] );
-	if ( type == CP_REDIRECT_PERMANENT ) {
-		/* permanent redirect, so save new MXit server and port */
-		purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
-		purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
-	}
-
-	/* Part 3: message (optional) */
-	if ( parts[2] != NULL )
-		purple_connection_notice( session->con, parts[2] );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n",
-			( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port );
-
-	/* perform the re-connect to the new MXit server */
-	mxit_reconnect( session );
-
-redirect_fail:
-	g_strfreev( parts );
-	g_strfreev( host );
-}
-
-
-/*------------------------------------------------------------------------
- * Process a success response received from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param packet		The received packet
- */
-static int process_success_response( struct MXitSession* session, struct rx_packet* packet )
-{
-	/* ignore ping/poll packets */
-	if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) )
-		session->last_rx = mxit_now_milli();
-
-	/*
-	 * when we pass the packet records to the next level for parsing
-	 * we minus 3 records because 1) the first record is the packet
-	 * type 2) packet reply status 3) the last record is bogus
-	 */
-
-	/* packet command */
-	switch ( packet->cmd ) {
-
-		case CP_CMD_REGISTER :
-				/* fall through, when registeration successful, MXit will auto login */
-		case CP_CMD_LOGIN :
-				/* login response */
-				if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
-					mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 );
-				}
-				break;
-
-		case CP_CMD_LOGOUT :
-				/* logout response */
-				session->flags &= ~MXIT_FLAG_LOGGEDIN;
-				purple_account_disconnect( session->acc );
-
-				/* note:
-				 * we do not prompt the user here for a reconnect, because this could be the user
-				 * logging in with his phone. so we just disconnect the account otherwise
-				 * mxit will start to bounce between the phone and pidgin. also could be a valid
-				 * disconnect selected by the user.
-				 */
-				return -1;
-
-		case CP_CMD_CONTACT :
-				/* contact update */
-				mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 );
-				break;
-
-		case CP_CMD_PRESENCE :
-				/* presence update */
-				mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 );
-				break;
-
-		case CP_CMD_RX_MSG :
-				/* incoming message (no bogus record) */
-				mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_NEW_SUB :
-				/* new subscription request */
-				mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 );
-				break;
-
-		case CP_CMD_MEDIA :
-				/* multi-media message */
-				mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_EXTPROFILE_GET :
-				/* profile update */
-				mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_SUGGESTCONTACTS :
-				/* suggest contacts */
-				mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_GOT_MSGEVENT :
-				/* received message event */
-				mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 );
-				break;
-
-		case CP_CMD_MOOD :
-				/* mood update */
-		case CP_CMD_UPDATE :
-				/* update contact information */
-		case CP_CMD_ALLOW :
-				/* allow subscription ack */
-		case CP_CMD_DENY :
-				/* deny subscription ack */
-		case CP_CMD_INVITE :
-				/* invite contact ack */
-		case CP_CMD_REMOVE :
-				/* remove contact ack */
-		case CP_CMD_TX_MSG :
-				/* outgoing message ack */
-		case CP_CMD_STATUS :
-				/* presence update ack */
-		case CP_CMD_GRPCHAT_CREATE :
-				/* create groupchat */
-		case CP_CMD_GRPCHAT_INVITE :
-				/* groupchat invite */
-		case CP_CMD_PING :
-				/* ping reply */
-		case CP_CMD_POLL :
-				/* HTTP poll reply */
-		case CP_CMD_EXTPROFILE_SET :
-				/* profile update */
-				// TODO: Protocol 6.2 indicates status for each attribute, and current value.
-		case CP_CMD_SPLASHCLICK :
-				/* splash-screen clickthrough */
-		case CP_CMD_MSGEVENT :
-				/* event message */
-				break;
-
-		default :
-			/* unknown packet */
-			purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd );
-	}
-
-	return 0;
-}
-
-
-/*------------------------------------------------------------------------
- * Process an error response received from the MXit server.
- *
- *  @param session		The MXit session object
- *  @param packet		The received packet
- */
-static int process_error_response( struct MXitSession* session, struct rx_packet* packet )
-{
-	char			errmsg[256];
-	const char*		errdesc;
-
-	/* set the error description to be shown to the user */
-	if ( packet->errmsg )
-		errdesc = packet->errmsg;
-	else
-		errdesc = _( "An internal MXit server error occurred." );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc );
-
-	if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) {
-		/* we are not currently logged in, so we need to reconnect */
-		purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( errdesc ) );
-	}
-
-	/* packet command */
-	switch ( packet->cmd ) {
-
-		case CP_CMD_REGISTER :
-		case CP_CMD_LOGIN :
-				if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
-					mxit_perform_redirect( session, packet->errmsg );
-					return 0;
-				}
-				else {
-					g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
-					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg );
-					return -1;
-				}
-		case CP_CMD_LOGOUT :
-				g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
-				purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
-				return -1;
-		case CP_CMD_CONTACT :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_RX_MSG :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_TX_MSG :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_STATUS :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_MOOD :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_KICK :
-				/*
-				 * the MXit server sends this packet if we were idle for too long.
-				 * to stop the server from closing this connection we need to resend
-				 * the login packet.
-				 */
-				mxit_send_login( session );
-				break;
-		case CP_CMD_INVITE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_REMOVE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_ALLOW :
-		case CP_CMD_DENY :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_UPDATE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_MEDIA :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_GRPCHAT_CREATE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) );
-				break;
-		case CP_CMD_GRPCHAT_INVITE :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_EXTPROFILE_GET :
-		case CP_CMD_EXTPROFILE_SET :
-				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
-				break;
-		case CP_CMD_SPLASHCLICK :
-		case CP_CMD_MSGEVENT :
-				/* ignore error */
-				break;
-		case CP_CMD_PING :
-		case CP_CMD_POLL :
-				break;
-		default :
-				mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) );
-				break;
-	}
-
-	return 0;
-}
-
-
-/*========================================================================================================================
- * Low-level Packet receive
- */
-
-#ifdef	DEBUG_PROTOCOL
-/*------------------------------------------------------------------------
- * Dump a received packet structure.
- *
- *  @param p			The received packet
- */
-static void dump_packet( struct rx_packet* p )
-{
-	struct record*		r	= NULL;
-	struct field*		f	= NULL;
-	int					i;
-	int					j;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount );
-
-	for ( i = 0; i < p->rcount; i++ ) {
-		r = p->records[i];
-		purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount );
-
-		for ( j = 0; j < r->fcount; j++ ) {
-			f = r->fields[j];
-			purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
-		}
-	}
-}
-#endif
-
-
-/*------------------------------------------------------------------------
- * Free up memory used by a packet structure.
- *
- *  @param p			The received packet
- */
-static void free_rx_packet( struct rx_packet* p )
-{
-	struct record*		r	= NULL;
-	struct field*		f	= NULL;
-	int					i;
-	int					j;
-
-	for ( i = 0; i < p->rcount; i++ ) {
-		r = p->records[i];
-
-		for ( j = 0; j < r->fcount; j++ ) {
-			g_free( f );
-		}
-		g_free( r->fields );
-		g_free( r );
-	}
-	g_free( p->records );
-}
-
-
-/*------------------------------------------------------------------------
- * Add a new field to a record.
- *
- *  @param r			Parent record object
- *  @return				The newly created field
- */
-static struct field* add_field( struct record* r )
-{
-	struct field*	field;
-
-	field = g_new0( struct field, 1 );
-
-	r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) );
-	r->fields[r->fcount] = field;
-	r->fcount++;
-
-	return field;
-}
-
-
-/*------------------------------------------------------------------------
- * Add a new record to a packet.
- *
- *  @param p			The packet object
- *  @return				The newly created record
- */
-static struct record* add_record( struct rx_packet* p )
-{
-	struct record*	rec;
-
-	rec = g_new0( struct record, 1 );
-
-	p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) );
-	p->records[p->rcount] = rec;
-	p->rcount++;
-
-	return rec;
-}
-
-
-/*------------------------------------------------------------------------
- * Parse the received byte stream into a proper client protocol packet.
- *
- *  @param session		The MXit session object
- *  @return				Success (0) or Failure (!0)
- */
-int mxit_parse_packet( struct MXitSession* session )
-{
-	struct rx_packet	packet;
-	struct record*		rec;
-	struct field*		field;
-	gboolean			pbreak;
-	unsigned int		i;
-	int					res	= 0;
-
-#ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i );
-	dump_bytes( session, session->rx_dbuf, session->rx_i );
-#endif
-
-	i = 0;
-	while ( i < session->rx_i ) {
-
-		/* create first record and field */
-		rec = NULL;
-		field = NULL;
-		memset( &packet, 0x00, sizeof( struct rx_packet ) );
-		rec = add_record( &packet );
-		pbreak = FALSE;
-
-		/* break up the received packet into fields and records for easy parsing */
-		while ( ( i < session->rx_i ) && ( !pbreak ) ) {
-
-			switch ( session->rx_dbuf[i] ) {
-				case CP_SOCK_REC_TERM :
-						/* new record */
-						if ( packet.rcount == 1 ) {
-							/* packet command */
-							packet.cmd = atoi( packet.records[0]->fields[0]->data );
-						}
-						else if ( packet.rcount == 2 ) {
-							/* special case: binary multimedia packets should not be parsed here */
-							if ( packet.cmd == CP_CMD_MEDIA ) {
-								/* add the chunked to new record */
-								rec = add_record( &packet );
-								field = add_field( rec );
-								field->data = &session->rx_dbuf[i + 1];
-								field->len = session->rx_i - i;
-								/* now skip the binary data */
-								res = get_chunk_len( field->data );
-								/* determine if we have more packets */
-								if ( res + 6 + i < session->rx_i ) {
-									/* we have more than one packet in this stream */
-									i += res + 6;
-									pbreak = TRUE;
-								}
-								else {
-									i = session->rx_i;
-								}
-							}
-						}
-						else if ( !field ) {
-							field = add_field( rec );
-							field->data = &session->rx_dbuf[i];
-						}
-						session->rx_dbuf[i] = '\0';
-						rec = add_record( &packet );
-						field = NULL;
-
-						break;
-				case CP_FLD_TERM :
-						/* new field */
-						session->rx_dbuf[i] = '\0';
-						if ( !field ) {
-							field = add_field( rec );
-							field->data = &session->rx_dbuf[i];
-						}
-						field = NULL;
-						break;
-				case CP_PKT_TERM :
-						/* packet is done! */
-						session->rx_dbuf[i] = '\0';
-						pbreak = TRUE;
-						break;
-				default :
-						/* skip non special characters */
-						if ( !field ) {
-							field = add_field( rec );
-							field->data = &session->rx_dbuf[i];
-						}
-						field->len++;
-						break;
-			}
-
-			i++;
-		}
-
-		if ( packet.rcount < 2 ) {
-			/* bad packet */
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) );
-			free_rx_packet( &packet );
-			continue;
-		}
-
-		session->rx_dbuf[session->rx_i] = '\0';
-		packet.errcode = atoi( packet.records[1]->fields[0]->data );
-
-		purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode );
-#ifdef	DEBUG_PROTOCOL
-		/* debug */
-		dump_packet( &packet );
-#endif
-
-		/* reset the out ack */
-		if ( session->outack == packet.cmd ) {
-			/* outstanding ack received from mxit server */
-			session->outack = 0;
-		}
-
-		/* check packet status */
-		if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) {
-			/* error reply! */
-			if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) )
-				packet.errmsg = packet.records[1]->fields[1]->data;
-			else
-				packet.errmsg = NULL;
-
-			res = process_error_response( session, &packet );
-		}
-		else {
-			/* success reply! */
-			res = process_success_response( session, &packet );
-		}
-
-		/* free up the packet resources */
-		free_rx_packet( &packet );
-	}
-
-	if ( session->outack == 0 )
-			mxit_manage_queue( session );
-
-	return res;
-}
-
-
-/*------------------------------------------------------------------------
- * Callback when data is received from the MXit server.
- *
- *  @param user_data		The MXit session object
- *  @param source			The file-descriptor on which data was received
- *  @param cond				Condition which caused the callback (PURPLE_INPUT_READ)
- */
-void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond )
-{
-	struct MXitSession*	session		= (struct MXitSession*) user_data;
-	char				ch;
-	int					res;
-	int					len;
-
-	if ( session->rx_state == RX_STATE_RLEN ) {
-		/* we are reading in the packet length */
-		len = read( session->fd, &ch, 1 );
-		if ( len < 0 ) {
-			/* connection error */
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
-			return;
-		}
-		else if ( len == 0 ) {
-			/* connection closed */
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
-			return;
-		}
-		else {
-			/* byte read */
-			if ( ch == CP_REC_TERM ) {
-				/* the end of the length record found */
-				session->rx_lbuf[session->rx_i] = '\0';
-				session->rx_res = atoi( &session->rx_lbuf[3] );
-				if ( session->rx_res > CP_MAX_PACKET ) {
-					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
-				}
-				session->rx_state = RX_STATE_DATA;
-				session->rx_i = 0;
-			}
-			else {
-				/* still part of the packet length record */
-				session->rx_lbuf[session->rx_i] = ch;
-				session->rx_i++;
-				if ( session->rx_i >= sizeof( session->rx_lbuf ) ) {
-					/* malformed packet length record (too long) */
-					purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
-					return;
-				}
-			}
-		}
-	}
-	else if ( session->rx_state == RX_STATE_DATA ) {
-		/* we are reading in the packet data */
-		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
-		if ( len < 0 ) {
-			/* connection error */
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
-			return;
-		}
-		else if ( len == 0 ) {
-			/* connection closed */
-			purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
-			return;
-		}
-		else {
-			/* data read */
-			session->rx_i += len;
-			session->rx_res -= len;
-
-			if ( session->rx_res == 0 ) {
-				/* ok, so now we have read in the whole packet */
-				session->rx_state = RX_STATE_PROC;
-			}
-		}
-	}
-
-	if ( session->rx_state == RX_STATE_PROC ) {
-		/* we have a full packet, which we now need to process */
-		res = mxit_parse_packet( session );
-
-		if ( res == 0 ) {
-			/* we are still logged in */
-			session->rx_state = RX_STATE_RLEN;
-			session->rx_res = 0;
-			session->rx_i = 0;
-		}
-	}
-}
-
-
-/*------------------------------------------------------------------------
- * Log the user off MXit and close the connection
- *
- *  @param session		The MXit session object
- */
-void mxit_close_connection( struct MXitSession* session )
-{
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" );
-
-	if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-		/* we are already closed */
-		return;
-	}
-	else if ( session->flags & MXIT_FLAG_LOGGEDIN ) {
-		/* we are currently logged in so we need to send a logout packet */
-		if ( !session->http ) {
-			mxit_send_logout( session );
-		}
-		session->flags &= ~MXIT_FLAG_LOGGEDIN;
-	}
-	session->flags &= ~MXIT_FLAG_CONNECTED;
-
-	/* cancel all outstanding async calls */
-	purple_http_connection_set_destroy(session->async_http_reqs);
-	session->async_http_reqs = NULL;
-
-	/* remove the input cb function */
-	if ( session->inpa ) {
-		purple_input_remove( session->inpa );
-		session->inpa = 0;
-	}
-
-	/* remove HTTP poll timer */
-	if ( session->http_timer_id > 0 )
-		purple_timeout_remove( session->http_timer_id );
-
-	/* remove slow queue manager timer */
-	if ( session->q_slow_timer_id > 0 )
-		purple_timeout_remove( session->q_slow_timer_id );
-
-	/* remove fast queue manager timer */
-	if ( session->q_fast_timer_id > 0 )
-		purple_timeout_remove( session->q_fast_timer_id );
-
-	/* remove all groupchat rooms */
-	while ( session->rooms != NULL ) {
-		struct multimx* multimx = (struct multimx *) session->rooms->data;
-
-		session->rooms = g_list_remove( session->rooms, multimx );
-
-		free( multimx );
-	}
-	g_list_free( session->rooms );
-	session->rooms = NULL;
-
-	/* remove all rx chats names */
-	while ( session->active_chats != NULL ) {
-		char* chat = (char*) session->active_chats->data;
-
-		session->active_chats = g_list_remove( session->active_chats, chat );
-
-		g_free( chat );
-	}
-	g_list_free( session->active_chats );
-	session->active_chats = NULL;
-
-	/* clear the internal invites */
-	while ( session->invites != NULL ) {
-		struct contact* contact = (struct contact*) session->invites->data;
-
-		session->invites = g_list_remove( session->invites, contact );
-
-		if ( contact->msg )
-			g_free( contact->msg );
-		if ( contact->statusMsg )
-			g_free( contact->statusMsg );
-		if ( contact->profile )
-			g_free( contact->profile );
-		g_free( contact );
-	}
-	g_list_free( session->invites );
-	session->invites = NULL;
-
-	/* free profile information */
-	if ( session->profile )
-		free( session->profile );
-
-	/* free custom emoticons */
-	mxit_free_emoticon_cache( session );
-
-	/* free allocated memory */
-	if ( session->uid )
-		g_free( session->uid );
-	g_free( session->encpwd );
-	session->encpwd = NULL;
-
-	/* flush all the commands still in the queue */
-	flush_queue( session );
-}
-
--- a/libpurple/protocols/mxit/protocol.h	Sun Aug 18 01:52:32 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- *					MXit Protocol libPurple Plugin
- *
- *			-- MXit client protocol implementation --
- *
- *				Pieter Loubser	<libpurple@mxit.com>
- *
- *			(C) Copyright 2009	MXit Lifestyle (Pty) Ltd.
- *				<http://www.mxitlifestyle.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef		_MXIT_PROTO_H_
-#define		_MXIT_PROTO_H_
-
-
-/* Client protocol constants */
-#define		CP_SOCK_REC_TERM		'\x00'				/* socket record terminator */
-#define		CP_HTTP_REC_TERM		'\x26'				/* http record terminator '&' */
-#define		CP_FLD_TERM				'\x01'				/* field terminator */
-#define		CP_PKT_TERM				'\x02'				/* packet terminator */
-
-
-#define		CP_MAX_PACKET			( 1 * 1000 * 1000 )	/* maximum client protocol packet size (1 MB) */
-#define		CP_MAX_FILESIZE			( CP_MAX_PACKET - 1000 )	/* maximum file size (reserve some space for packet headers) */
-#define		MXIT_EMOTICON_SIZE		18					/* icon size for custom emoticons */
-#define		CP_MAX_STATUS_MSG		250					/* maximum status message length (in characters) */
-
-/* Avatars */
-#define		MXIT_AVATAR_SIZE		96					/* default avatar image size 96x96 */
-#define		MXIT_AVATAR_TYPE		"PNG"				/* request avatars in this file type (only a suggestion) */
-#define		MXIT_AVATAR_BITDEPT		24					/* request avatars with this bit depth (only a suggestion) */
-
-/* Protocol error codes */
-#define		MXIT_ERRCODE_SUCCESS	0
-#define		MXIT_ERRCODE_REDIRECT	16
-#define		MXIT_ERRCODE_LOGGEDOUT	42
-
-/* MXit client features */
-#define		MXIT_CF_NONE			0x000000
-#define		MXIT_CF_FORMS			0x000001
-#define		MXIT_CF_FILE_TRANSFER	0x000002
-#define		MXIT_CF_CAMERA			0x000004
-#define		MXIT_CF_COMMANDS		0x000008
-#define		MXIT_CF_SMS				0x000010
-#define		MXIT_CF_FILE_ACCESS		0x000020
-#define		MXIT_CF_MIDP2			0x000040
-#define		MXIT_CF_SKINS			0x000080
-#define		MXIT_CF_AUDIO			0x000100
-#define		MXIT_CF_ENCRYPTION		0x000200
-#define		MXIT_CF_VOICE_REC		0x000400
-#define		MXIT_CF_VECTOR_GFX		0x000800
-#define		MXIT_CF_IMAGES			0x001000
-#define		MXIT_CF_MARKUP			0x002000
-#define		MXIT_CF_VIBES			0x004000
-#define		MXIT_CF_SELECT_CONTACT	0x008000
-#define		MXIT_CF_CUSTOM_EMO		0x010000
-#define		MXIT_CF_ALERT_PROFILES	0x020000
-#define		MXIT_CF_EXT_MARKUP		0x040000
-#define		MXIT_CF_PLAIN_PWD		0x080000
-#define		MXIT_CF_NO_GATEWAYS		0x100000
-#define		MXIT_CF_NO_AVATARS		0x200000
-#define		MXIT_CF_GAMING			0x400000
-#define		MXIT_CF_GAMING_UPDATE	0x800000
-#define		MXIT_CF_VOICE			0x1000000
-#define		MXIT_CF_VIDEO			0x2000000
-#define		MXIT_CF_TOUCHSCREEN		0x4000000
-#define		MXIT_CF_SVC_CONNECTION	0x8000000
-#define		MXIT_CF_MXML			0x10000000
-#define		MXIT_CF_TYPING_NOTIFY	0x20000000
-
-/* 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 | MXIT_CF_TYPING_NOTIFY )
-
-
-#define		MXIT_PING_INTERVAL		( 5 * 60 )				/* ping the server after X seconds of being idle (5 minutes) */
-#define		MXIT_ACK_TIMEOUT		( 30 )					/* timeout after waiting X seconds for an ack from the server (30 seconds) */
-#define		MXIT_TX_DELAY			( 100 )					/* delay between sending consecutive packets (100 ms) */
-
-/* MXit client version */
-#define		MXIT_CP_DISTCODE		'P'						/* client distribution code (magic, do not touch!) */
-#define		MXIT_CP_ARCH			"Y"						/* client architecture series (Y not for Yoda but for PC-client) */
-#define		MXIT_CLIENT_ID			"LP"					/* client ID as specified by MXit */
-#define		MXIT_CP_PLATFORM		"PURPLE"				/* client platform */
-#define		MXIT_CP_PROTO_VESION	63						/* client protocol version */
-
-/* set operating system name */
-#if defined( __APPLE__ )
-#define		MXIT_CP_OS				"apple"
-#elif defined( _WIN32 )
-#define		MXIT_CP_OS				"windows"
-#elif defined( __linux__ )
-#define		MXIT_CP_OS				"linux"
-#else
-#define		MXIT_CP_OS				"unknown"
-#endif
-
-/* Client capabilities */
-#define		MXIT_CP_CAP				"utf8=true;cid="MXIT_CLIENT_ID
-
-/* Client settings */
-#define		MAX_QUEUE_SIZE			( 1 << 5 )				/* tx queue size (32 packets) */
-#define		MXIT_POPUP_WIN_NAME		"MXit Notification"		/* popup window name */
-#define		MXIT_DEFAULT_LOCALE		"en"					/* default locale setting */
-#define		MXIT_DEFAULT_LOC		"planetpurple"			/* the default location for registration */
-
-/* Client protocol commands */
-#define		CP_CMD_LOGIN			0x0001					/* (1) login */
-#define		CP_CMD_LOGOUT			0x0002					/* (2) logout */
-#define		CP_CMD_CONTACT			0x0003					/* (3) get contacts */
-#define		CP_CMD_UPDATE			0x0005					/* (5) update contact information */
-#define		CP_CMD_INVITE			0x0006					/* (6) subscribe to new contact */
-#define		CP_CMD_PRESENCE			0x0007					/* (7) get presence */
-#define		CP_CMD_REMOVE			0x0008					/* (8) remove contact */
-#define		CP_CMD_RX_MSG			0x0009					/* (9) get new messages */
-#define		CP_CMD_TX_MSG			0x000A					/* (10) send new message */
-#define		CP_CMD_REGISTER			0x000B					/* (11) register */
-//#define	CP_CMD_PROFILE_SET		0x000C					/* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */
-#define		CP_CMD_SUGGESTCONTACTS	0x000D					/* (13) suggest contacts */
-#define		CP_CMD_POLL				0x0011					/* (17) poll the HTTP server for an update */
-//#define	CP_CMD_PROFILE_GET		0x001A					/* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */
-#define		CP_CMD_MEDIA			0x001B					/* (27) get multimedia message */
-#define		CP_CMD_SPLASHCLICK		0x001F					/* (31) splash-screen clickthrough */
-#define		CP_CMD_STATUS			0x0020					/* (32) set shown presence & status */
-#define		CP_CMD_MSGEVENT			0x0023					/* (35) Raise message event */
-#define		CP_CMD_GOT_MSGEVENT		0x0024					/* (36) Get message event */
-#define		CP_CMD_MOOD				0x0029					/* (41) set mood */
-#define		CP_CMD_KICK				0x002B					/* (43) login kick */
-#define		CP_CMD_GRPCHAT_CREATE	0x002C					/* (44) create new groupchat */
-#define		CP_CMD_GRPCHAT_INVITE	0x002D					/* (45) add new groupchat member */
-#define		CP_CMD_NEW_SUB			0x0033					/* (51) get new subscription */
-#define		CP_CMD_ALLOW			0x0034					/* (52) allow subscription */
-#define		CP_CMD_DENY				0x0037					/* (55) deny subscription */
-#define		CP_CMD_EXTPROFILE_GET	0x0039					/* (57) get extended profile */
-#define		CP_CMD_EXTPROFILE_SET	0x003A					/* (58) set extended profile */
-#define		CP_CMD_PING				0x03E8					/* (1000) ping (keepalive) */
-
-/* HTTP connection */
-#define		MXIT_HTTP_POLL_MIN		7						/* minimum time between HTTP polls (seconds) */
-#define		MXIT_HTTP_POLL_MAX		( 10 * 60 )				/* maximum time between HTTP polls (seconds) */
-
-/* receiver states */
-#define		RX_STATE_RLEN			0x01					/* reading packet length section */
-#define		RX_STATE_DATA			0x02					/* reading packet data section */
-#define		RX_STATE_PROC			0x03					/* process read data */
-
-/* message flags */
-#define		CP_MSG_NOTIFY_DELIVERY	0x0002					/* request delivery notification */
-#define		CP_MSG_NOTIFY_READ		0x0004					/* request read notification */
-#define		CP_MSG_PWD_ENCRYPTED	0x0010					/* message is password encrypted */
-#define		CP_MSG_TL_ENCRYPTED		0x0020					/* message is transport encrypted */
-#define		CP_MSG_RPLY_PWD_ENCRYPT	0x0040					/* reply should be password encrypted */
-#define		CP_MSG_RPLY_TL_ENCRYPT	0x0080					/* reply should be transport encrypted */
-#define		CP_MSG_MARKUP			0x0200					/* message may contain markup */
-#define		CP_MSG_EMOTICON			0x0400					/* message may contain custom emoticons */
-#define		CP_MSG_FAREWELL			0x0800					/* this is a farewell message */
-
-/* redirect types */
-#define		CP_REDIRECT_PERMANENT	1						/* permanent redirect */
-#define		CP_REDIRECT_TEMPORARY	2						/* temporary redirect */
-
-/* message tx types */
-#define		CP_MSGTYPE_NORMAL		0x01					/* normal message */
-#define		CP_MSGTYPE_CHAT			0x02					/* chat message */
-#define		CP_MSGTYPE_HEADLINE		0x03					/* headline message */
-#define		CP_MSGTYPE_ERROR		0x04					/* error message */
-#define		CP_MSGTYPE_GROUPCHAT	0x05					/* groupchat message */
-#define		CP_MSGTYPE_FORM			0x06					/* mxit custom form */
-#define		CP_MSGTYPE_COMMAND		0x07					/* mxit command */
-
-/* message event types */
-#define		CP_MSGEVENT_DELIVERED	0x02					/* message was delivered */
-#define		CP_MSGEVENT_DISPLAYED	0x04					/* message was viewed */
-#define		CP_MSGEVENT_TYPING		0x10					/* user is typing */
-#define		CP_MSGEVENT_STOPPED		0x20					/* user has stopped typing */
-#define		CP_MSGEVENT_ANGRY		0x40					/* user is typing angrily */
-#define		CP_MSGEVENT_ERASING		0x80					/* user is erasing text */
-
-/* extended profile attribute fields */
-#define		CP_PROFILE_BIRTHDATE	"birthdate"				/* Birthdate (String - ISO 8601 format) */
-#define		CP_PROFILE_GENDER		"gender"				/* Gender (Boolean - 0=female, 1=male) */
-// #define		CP_PROFILE_HIDENUMBER	"hidenumber"			/* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */
-#define		CP_PROFILE_FULLNAME		"fullname"				/* Fullname (UTF8 String) */
-#define		CP_PROFILE_STATUS		"statusmsg"				/* Status Message (UTF8 String) */
-#define		CP_PROFILE_PREVSTATUS	"prevstatusmsgs"		/* Previous Status Messages (UTF8 String) */
-#define		CP_PROFILE_AVATAR		"avatarid"				/* Avatar ID (String) */
-#define		CP_PROFILE_MODIFIED		"lastmodified"			/* Last-Modified timestamp */
-#define		CP_PROFILE_TITLE		"title"					/* Title (UTF8 String) */
-#define		CP_PROFILE_FIRSTNAME	"firstname"				/* First name (UTF8 String) */
-#define		CP_PROFILE_LASTNAME		"lastname"				/* Last name (UTF8 String) */
-#define		CP_PROFILE_EMAIL		"email"					/* Email address (UTF8 String) */
-#define		CP_PROFILE_MOBILENR		"mobilenumber"			/* Mobile Number (UTF8 String) */
-#define		CP_PROFILE_REGCOUNTRY	"registeredcountry"		/* Registered Country Code (UTF8 String) */
-#define		CP_PROFILE_FLAGS		"flags"					/* Profile flags (Bitset) */
-#define		CP_PROFILE_LASTSEEN		"lastseen"				/* Last-Online timestamp */
-#define		CP_PROFILE_WHEREAMI		"whereami"				/* Where am I / Where I live */
-#define		CP_PROFILE_ABOUTME		"aboutme"				/* About me */
-#define		CP_PROFILE_RELATIONSHIP	"relationship"			/* Relationship Status */
-
-/* extended profile field types */
-#define		CP_PROFILE_TYPE_BOOL	0x02					/* boolean (0 or 1) */
-#define		CP_PROFILE_TYPE_SHORT	0x04					/* short (16-bit) */
-#define		CP_PROFILE_TYPE_INT		0x05					/* integer (32-bit) */
-#define		CP_PROFILE_TYPE_LONG	0x06					/* long (64-bit) */
-#define		CP_PROFILE_TYPE_UTF8	0x0A					/* UTF8 string */
-#define		CP_PROFILE_TYPE_DATE	0x0B					/* date-time (ISO 8601 format) */
-
-/* profile flags */
-#define		CP_PROF_NOT_SEARCHABLE	0x02					/* user cannot be searched for */
-#define		CP_PROF_NOT_SUGGESTABLE	0x08					/* user cannot be suggested as friend */
-#define		CP_PROF_DOBLOCKED		0x40					/* date-of-birth cannot be changed */
-
-/* suggestion types */
-#define		CP_SUGGEST_ADDRESSBOOK	0						/* address book search */
-#define		CP_SUGGEST_FRIENDS		1						/* suggested friends */
-#define		CP_SUGGEST_SEARCH		2						/* free-text search */
-#define		CP_SUGGEST_MXITID		3						/* MXitId search */
-
-/* define this to enable protocol debugging (very verbose logging) */
-#define		DEBUG_PROTOCOL
-
-
-/* ======================================================================================= */
-
-struct MXitSession;
-
-/*------------------------------------------*/
-
-struct field {
-	char*				data;
-	int					len;
-};
-
-struct record {
-	struct field**		fields;
-	int					fcount;
-};
-
-struct rx_packet {
-	int					cmd;
-	int					errcode;
-	char*				errmsg;
-	struct record**		records;
-	int					rcount;
-};
-
-struct tx_packet {
-	int					cmd;
-	char				header[256];
-	int					headerlen;
-	char*				data;
-	int					datalen;
-};
-
-/*------------------------------------------*/
-
-
-/*
- * A received message data object
- */
-struct RXMsgData {
-	struct MXitSession*		session;					/* MXit session object */
-	char*					from;						/* the sender's name */
-	time_t					timestamp;					/* time at which the message was sent */
-	GString*				msg;						/* newly created message converted to libPurple formatting */
-	gboolean				got_img;					/* flag to say if this message got any images/emoticons embedded */
-	short					img_count;					/* the amount of images/emoticons still outstanding for the message */
-	int						chatid;						/* multimx chatroom id */
-	int						flags;						/* libPurple conversation flags */
-	gboolean				converted;					/* true if the message has been completely parsed and converted to libPurple markup */
-	gboolean				processed;					/* the message has been processed completely and should be freed up */
-};
-
-
-
-/*
- * The packet transmission queue.
- */
-struct tx_queue {
-	struct tx_packet*	packets[MAX_QUEUE_SIZE];		/* array of packet pointers */
-	int					count;							/* number of packets queued */
-	int					rd_i;							/* queue current read index (queue offset for reading a packet) */
-	int					wr_i;							/* queue current write index (queue offset for adding new packet) */
-};
-
-
-/* ======================================================================================= */
-
-void mxit_popup( int type, const char* heading, const char* message );
-void mxit_strip_domain( char* username );
-gboolean find_active_chat( const GList* chats, const char* who );
-
-void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond );
-gboolean mxit_manage_queue_slow( gpointer user_data );
-gboolean mxit_manage_queue_fast( gpointer user_data );
-gboolean mxit_manage_polling( gpointer user_data );
-
-void mxit_send_register( struct MXitSession* session );
-void mxit_send_login( struct MXitSession* session );
-void mxit_send_logout( struct MXitSession* session );
-void mxit_send_ping( struct MXitSession* session );
-void mxit_send_poll( struct MXitSession* session );
-
-void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg );
-void mxit_send_mood( struct MXitSession* session, int mood );
-void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command );
-
-void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes );
-void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] );
-
-void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] );
-void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] );
-
-void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message );
-void mxit_send_remove( struct MXitSession* session, const char* username );
-void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias );
-void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason );
-void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname );
-void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
-void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
-
-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
-void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset );
-void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen );
-void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
-
-void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
-void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] );
-
-int mxit_parse_packet( struct MXitSession* session );
-void dump_bytes( struct MXitSession* session, const char* buf, int len );
-void mxit_close_connection( struct MXitSession* session );
-gint64 mxit_now_milli( void );
-
-
-#endif		/* _MXIT_PROTO_H_ */
-
--- a/libpurple/protocols/mxit/roster.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/roster.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 #include	"internal.h"
 #include	"debug.h"
 
-#include	"protocol.h"
+#include	"client.h"
 #include	"mxit.h"
 #include	"roster.h"
 
@@ -325,17 +325,17 @@
 		/* now re-instate his presence again */
 		if ( contact ) {
 
-			/* update the buddy's status (reference: "libpurple/prpl.h") */
+			/* update the buddy's status (reference: "libpurple/protocol.h") */
 			if ( contact->statusMsg )
-				purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
+				purple_protocol_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
 			else
-				purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL );
+				purple_protocol_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL );
 
 			/* update the buddy's mood */
 			if ( contact->mood == MXIT_MOOD_NONE )
-				purple_prpl_got_user_status_deactive( session->acc, newbuddy->name, "mood" );
+				purple_protocol_got_user_status_deactive( session->acc, newbuddy->name, "mood" );
 			else
-				purple_prpl_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+				purple_protocol_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
 
 			/* update avatar */
 			if ( contact->avatarId ) {
@@ -422,14 +422,14 @@
 	else
 		contact->avatarId = NULL;
 
-	/* update the buddy's status (reference: "libpurple/prpl.h") */
-	purple_prpl_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL );
+	/* update the buddy's status (reference: "libpurple/protocol.h") */
+	purple_protocol_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL );
 
 	/* update the buddy's mood */
 	if ( contact->mood == MXIT_MOOD_NONE )
-		purple_prpl_got_user_status_deactive( session->acc, contact->username, "mood" );
+		purple_protocol_got_user_status_deactive( session->acc, contact->username, "mood" );
 	else
-		purple_prpl_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+		purple_protocol_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
 }
 
 
@@ -488,17 +488,17 @@
 	if ( ( statusMsg ) && ( statusMsg[0] != '\0' ) )
 		contact->statusMsg = g_markup_escape_text( statusMsg, -1 );
 
-	/* update the buddy's status (reference: "libpurple/prpl.h") */
+	/* update the buddy's status (reference: "libpurple/protocol.h") */
 	if ( contact->statusMsg )
-		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
+		purple_protocol_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
 	else
-		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
+		purple_protocol_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
 
 	/* update the buddy's mood */
 	if ( contact->mood == MXIT_MOOD_NONE )
-		purple_prpl_got_user_status_deactive( session->acc, username, "mood" );
+		purple_protocol_got_user_status_deactive( session->acc, username, "mood" );
 	else
-		purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+		purple_protocol_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
 }
 
 
--- a/libpurple/protocols/mxit/splashscreen.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/mxit/splashscreen.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "imgstore.h"
 #include "request.h"
 
-#include "protocol.h"
+#include "client.h"
 #include "mxit.h"
 #include "splashscreen.h"
 
--- a/libpurple/protocols/myspace/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/myspace/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -41,4 +41,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/myspace/myspace.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/myspace/myspace.c	Sun Aug 18 01:53:00 2013 +0530
@@ -32,8 +32,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
-#define PURPLE_PLUGIN
-
+#include "plugins.h"
 #include "myspace.h"
 
 static void msim_set_status(PurpleAccount *account, PurpleStatus *status);
@@ -1301,7 +1300,7 @@
 			PURPLE_MAJOR_VERSION,
 			PURPLE_MINOR_VERSION,
 			PURPLE_MICRO_VERSION,
-			MSIM_PRPL_VERSION_STRING);
+			MSIM_PROTOCOL_VERSION_STRING);
 
 	ret = msim_send_bm(session, username, our_info, MSIM_BM_UNOFFICIAL_CLIENT);
 
@@ -1440,14 +1439,14 @@
 			g_free(unrecognized_msg);
 	}
 
-	purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
+	purple_protocol_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
 
 	if (status_code == MSIM_STATUS_CODE_IDLE) {
 		purple_debug_info("msim", "msim_status: got idle: %s\n", username);
-		purple_prpl_got_user_idle(session->account, username, TRUE, 0);
+		purple_protocol_got_user_idle(session->account, username, TRUE, 0);
 	} else {
 		/* All other statuses indicate going back to non-idle. */
-		purple_prpl_got_user_idle(session->account, username, FALSE, 0);
+		purple_protocol_got_user_idle(session->account, username, FALSE, 0);
 	}
 
 #ifdef MSIM_SEND_CLIENT_VERSION
@@ -2919,7 +2918,7 @@
 /**
  * Send raw data to the server, possibly with embedded NULs.
  *
- * Used in prpl_info struct, so that plugins can have the most possible
+ * Used in protocol struct, so that plugins can have the most possible
  * control of what is sent over the connection. Inside this prpl,
  * msim_send_raw() is used, since it sends NUL-terminated strings (easier).
  *
@@ -3000,10 +2999,100 @@
 }
 
 /**
+ * Called when friends have been imported to buddy list on server.
+ */
+static void
+msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data)
+{
+	MsimMessage *body;
+	gchar *completed;
+
+	/* Check if the friends were imported successfully. */
+	body = msim_msg_get_dictionary(reply, "body");
+	g_return_if_fail(body != NULL);
+	completed = msim_msg_get_string(body, "Completed");
+	msim_msg_free(body);
+	g_return_if_fail(completed != NULL);
+	if (!g_str_equal(completed, "True"))
+	{
+		purple_debug_info("msim_import_friends_cb",
+				"failed to import friends: %s", completed);
+		purple_notify_error(session->account, _("Add friends from MySpace.com"),
+				_("Importing friends failed"), NULL);
+		g_free(completed);
+		return;
+	}
+	g_free(completed);
+
+	purple_debug_info("msim_import_friends_cb",
+			"added friends to server-side buddy list, requesting new contacts from server");
+
+	msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS);
+
+	/* TODO: show, X friends have been added */
+}
+
+/**
+ * Import friends from myspace.com.
+ */
+static void msim_import_friends(PurpleProtocolAction *action)
+{
+	PurpleConnection *gc;
+	MsimSession *session;
+	gchar *group_name;
+
+	gc = action->connection;
+	session = purple_connection_get_protocol_data(gc);
+
+	group_name = "MySpace Friends";
+
+	g_return_if_fail(msim_send(session,
+			"persist", MSIM_TYPE_INTEGER, 1,
+			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
+			"dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN,
+			"lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID,
+			"uid", MSIM_TYPE_INTEGER, session->userid,
+			"rid", MSIM_TYPE_INTEGER,
+				msim_new_reply_callback(session, msim_import_friends_cb, NULL),
+			"body", MSIM_TYPE_STRING,
+				g_strdup_printf("GroupName=%s", group_name),
+			NULL));
+}
+
+/**
+ * Actions menu for account.
+ */
+static GList *
+msim_get_actions(PurpleConnection *gc)
+{
+	GList *menu;
+	PurpleProtocolAction *act;
+
+	menu = NULL;
+
+#if 0
+	/* TODO: find out how */
+	act = purple_protocol_action_new(_("Find people..."), msim_);
+	menu = g_list_append(menu, act);
+
+	act = purple_protocol_action_new(_("Change IM name..."), NULL);
+	menu = g_list_append(menu, act);
+#endif
+
+	act = purple_protocol_action_new(_("Add friends from MySpace.com"), msim_import_friends);
+	menu = g_list_append(menu, act);
+
+	return menu;
+}
+
+/**
  * Callbacks called by Purple, to access this plugin.
  */
-static PurplePluginProtocolInfo prpl_info = {
-	sizeof(PurplePluginProtocolInfo), /* struct_size */
+static PurpleProtocol protocol = {
+	"prpl-myspace",    /* id */
+	"MySpaceIM",       /* name */
+	sizeof(PurpleProtocol), /* struct_size */
 	/* options */
 	  OPT_PROTO_USE_POINTSIZE        /* specify font size in sane point size */
 	| OPT_PROTO_MAIL_CHECK,
@@ -3012,6 +3101,7 @@
 	NULL,              /* user_splits */
 	NULL,              /* protocol_options */
 	NO_BUDDY_ICONS,    /* icon_spec - TODO: eventually should add this */
+	msim_get_actions,  /* get_actions */
 	msim_list_icon,    /* list_icon */
 	NULL,              /* list_emblems */
 	msim_status_text,  /* status_text */
@@ -3066,7 +3156,7 @@
 	NULL,              /* send_file */
 	NULL,              /* new_xfer */
 	msim_offline_message,  /* offline_message */
-	NULL,              /* whiteboard_prpl_ops */
+	NULL,              /* whiteboard_protocol_ops */
 	msim_send_really_raw,  /* send_raw */
 	NULL,                  /* roomlist_room_serialize */
 	NULL,                  /* unregister_user */
@@ -3080,139 +3170,6 @@
 	NULL                    /* get_public_alias */
 };
 
-/**
- * Load the plugin.
- */
-static gboolean
-msim_load(PurplePlugin *plugin)
-{
-	return TRUE;
-}
-
-/**
- * Called when friends have been imported to buddy list on server.
- */
-static void
-msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data)
-{
-	MsimMessage *body;
-	gchar *completed;
-
-	/* Check if the friends were imported successfully. */
-	body = msim_msg_get_dictionary(reply, "body");
-	g_return_if_fail(body != NULL);
-	completed = msim_msg_get_string(body, "Completed");
-	msim_msg_free(body);
-	g_return_if_fail(completed != NULL);
-	if (!g_str_equal(completed, "True"))
-	{
-		purple_debug_info("msim_import_friends_cb",
-				"failed to import friends: %s", completed);
-		purple_notify_error(session->account, _("Add friends from MySpace.com"),
-				_("Importing friends failed"), NULL);
-		g_free(completed);
-		return;
-	}
-	g_free(completed);
-
-	purple_debug_info("msim_import_friends_cb",
-			"added friends to server-side buddy list, requesting new contacts from server");
-
-	msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS);
-
-	/* TODO: show, X friends have been added */
-}
-
-/**
- * Import friends from myspace.com.
- */
-static void msim_import_friends(PurplePluginAction *action)
-{
-	PurpleConnection *gc;
-	MsimSession *session;
-	gchar *group_name;
-
-	gc = (PurpleConnection *)action->context;
-	session = purple_connection_get_protocol_data(gc);
-
-	group_name = "MySpace Friends";
-
-	g_return_if_fail(msim_send(session,
-			"persist", MSIM_TYPE_INTEGER, 1,
-			"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-			"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
-			"dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN,
-			"lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID,
-			"uid", MSIM_TYPE_INTEGER, session->userid,
-			"rid", MSIM_TYPE_INTEGER,
-				msim_new_reply_callback(session, msim_import_friends_cb, NULL),
-			"body", MSIM_TYPE_STRING,
-				g_strdup_printf("GroupName=%s", group_name),
-			NULL));
-}
-
-/**
- * Actions menu for account.
- */
-static GList *
-msim_actions(PurplePlugin *plugin, gpointer context /* PurpleConnection* */)
-{
-	GList *menu;
-	PurplePluginAction *act;
-
-	menu = NULL;
-
-#if 0
-	/* TODO: find out how */
-	act = purple_plugin_action_new(_("Find people..."), msim_);
-	menu = g_list_append(menu, act);
-
-	act = purple_plugin_action_new(_("Change IM name..."), NULL);
-	menu = g_list_append(menu, act);
-#endif
-
-	act = purple_plugin_action_new(_("Add friends from MySpace.com"), msim_import_friends);
-	menu = g_list_append(menu, act);
-
-	return menu;
-}
-
-/**
- * Based on MSN's plugin info comments.
- */
-static PurplePluginInfo info = {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                           /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                          /**< priority       */
-
-	"prpl-myspace",                                   /**< id             */
-	"MySpaceIM",                                      /**< name           */
-	MSIM_PRPL_VERSION_STRING,                         /**< version        */
-	                                                  /**  summary        */
-	"MySpaceIM Protocol Plugin",
-	                                                  /**  description    */
-	"MySpaceIM Protocol Plugin",
-	"Jeff Connelly <jeff2@soc.pidgin.im>",            /**< author         */
-	"https://developer.pidgin.im/wiki/MySpaceIM/",    /**< homepage       */
-
-	msim_load,                                        /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	msim_actions,                                     /**< msim_actions   */
-	NULL,                                             /**< reserved1      */
-	NULL,                                             /**< reserved2      */
-	NULL,                                             /**< reserved3      */
-	NULL                                              /**< reserved4      */
-};
-
 #ifdef MSIM_SELF_TEST
 /*
  * Test functions.
@@ -3502,10 +3459,32 @@
 }
 
 /**
- * Initialize plugin.
+ * Query the plugin
  */
-static void
-init_plugin(PurplePlugin *plugin)
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-myspace",
+		"name",         "MySpaceIM",
+		"version",      MSIM_PROTOCOL_VERSION_STRING,
+		"category",     "Protocol",
+		"summary",      "MySpaceIM Protocol Plugin",
+		"description",  "MySpaceIM Protocol Plugin",
+		"author",       "Jeff Connelly <jeff2@soc.pidgin.im>",
+		"website",      "https://developer.pidgin.im/wiki/MySpaceIM/",
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
+/**
+ * Load the plugin.
+ */
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 #ifdef MSIM_SELF_TEST
 	msim_test_all();
@@ -3513,45 +3492,53 @@
 #endif /* MSIM_SELF_TEST */
 
 	PurpleAccountOption *option;
-	static gboolean initialized = FALSE;
 
 	/* TODO: default to automatically try different ports. Make the user be
 	 * able to set the first port to try (like LastConnectedPort in Windows client).  */
 	option = purple_account_option_string_new(_("Connect server"), "server", MSIM_SERVER);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_int_new(_("Connect port"), "port", MSIM_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 #ifdef MSIM_USER_WANTS_TO_CONFIGURE_STATUS_TEXT
 	option = purple_account_option_bool_new(_("Show display name in status text"), "show_display_name", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Show headline in status text"), "show_headline", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 #endif
 
 #ifdef MSIM_USER_WANTS_TO_DISABLE_EMOTICONS
 	option = purple_account_option_bool_new(_("Send emoticons"), "emoticons", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 #endif
 
 #ifdef MSIM_USER_REALLY_CARES_ABOUT_PRECISE_FONT_SIZES
 	option = purple_account_option_int_new(_("Screen resolution (dots per inch)"), "dpi", MSIM_DEFAULT_DPI);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_int_new(_("Base font size (points)"), "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 #endif
 
-	/* Code below only runs once. Based on oscar.c's oscar_init(). */
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	purple_signal_connect(purple_get_core(), "uri-handler", &initialized,
+	purple_signal_connect(purple_get_core(), "uri-handler", &protocol,
 			PURPLE_CALLBACK(msim_uri_handler), NULL);
+
+	purple_protocols_add(&protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(myspace, init_plugin, info);
+/**
+ * Unload the plugin.
+ */
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(&protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(myspace, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/myspace/myspace.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/myspace/myspace.h	Sun Aug 18 01:53:00 2013 +0530
@@ -39,7 +39,7 @@
 #endif
 
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "accountopt.h"
 #include "version.h"
 #include "util.h"       /* for base64 */
@@ -103,7 +103,7 @@
 #define MSIM_LANGUAGE_NAME_ENGLISH  "ENGLISH"
 
 /* msimprpl version string of this plugin */
-#define MSIM_PRPL_VERSION_STRING    "0.18"
+#define MSIM_PROTOCOL_VERSION_STRING    "0.18"
 
 /* Default server */
 #define MSIM_SERVER                 "im.myspace.akadns.net"
--- a/libpurple/protocols/myspace/user.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/myspace/user.c	Sun Aug 18 01:53:00 2013 +0530
@@ -256,7 +256,7 @@
  * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
  *
  * This function is useful because it lets you set the artist or title
- * individually, which purple_prpl_got_user_status() doesn't do.
+ * individually, which purple_protocol_got_user_status() doesn't do.
  */
 static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
 {
@@ -281,7 +281,7 @@
 	name = purple_buddy_get_name(user->buddy);
 
 	if (!new_artist && !new_title) {
-		purple_prpl_got_user_status_deactive(account, name, "tune");
+		purple_protocol_got_user_status_deactive(account, name, "tune");
 		return;
 	}
 
@@ -301,7 +301,7 @@
 	if (!new_title)
 		new_title = prev_title;
 
-	purple_prpl_got_user_status(account, name, "tune",
+	purple_protocol_got_user_status(account, name, "tune",
 			PURPLE_TUNE_TITLE, new_title,
 			PURPLE_TUNE_ARTIST, new_artist,
 			NULL);
--- a/libpurple/protocols/myspace/zap.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/myspace/zap.c	Sun Aug 18 01:53:00 2013 +0530
@@ -179,7 +179,7 @@
 
 	zap = GPOINTER_TO_INT(zap_num_ptr);
 
-	purple_prpl_send_attention(session->gc, purple_buddy_get_name(buddy), zap);
+	purple_protocol_send_attention(session->gc, purple_buddy_get_name(buddy), zap);
 }
 
 /** Return menu, if any, for a buddy list node. */
@@ -237,7 +237,7 @@
 
 	zap = CLAMP(zap, 0, 9);
 
-	purple_prpl_got_attention(session->gc, username, zap);
+	purple_protocol_got_attention(session->gc, username, zap);
 
 	g_free(msg_text);
 	g_free(username);
--- a/libpurple/protocols/novell/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/novell/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -50,4 +50,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(DEBUG_CFLAGS) \
-	$(GLIB_CFLAGS)
+	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS)
--- a/libpurple/protocols/novell/novell.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/novell/novell.c	Sun Aug 18 01:53:00 2013 +0530
@@ -21,7 +21,8 @@
 #include "internal.h"
 #include "accountopt.h"
 #include "debug.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "server.h"
 #include "nmuser.h"
 #include "notify.h"
@@ -43,7 +44,7 @@
 #define NOVELL_STATUS_TYPE_IDLE "idle"
 #define NOVELL_STATUS_TYPE_APPEAR_OFFLINE "appearoffline"
 
-static PurplePlugin *my_protocol = NULL;
+static PurpleProtocol *my_protocol = NULL;
 
 static gboolean
 _is_disconnect_error(NMERR_T err);
@@ -1216,9 +1217,9 @@
 		}
 	}
 
-	purple_prpl_got_user_status(account, name, status_id,
+	purple_protocol_got_user_status(account, name, status_id,
 							  "message", text, NULL);
-	purple_prpl_got_user_idle(account, name,
+	purple_protocol_got_user_idle(account, name,
 							(novellstatus == NM_STATUS_AWAY_IDLE), idle);
 }
 
@@ -3475,14 +3476,17 @@
 	_check_for_disconnect(user, rc);
 }
 
-static PurplePluginProtocolInfo prpl_info = {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+static PurpleProtocol protocol = {
+	"prpl-novell",				/* id */
+	"GroupWise",				/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	0,
 	NULL,						/* user_splits */
 	NULL,						/* protocol_options */
 	NO_BUDDY_ICONS,				/* icon_spec */
+	NULL,						/* get_actions */
 	novell_list_icon,			/* list_icon */
-	NULL,				/* list_emblems */
+	NULL,						/* list_emblems */
 	novell_status_text,			/* status_text */
 	novell_tooltip_text,		/* tooltip_text */
 	novell_status_types,		/* status_types */
@@ -3535,7 +3539,7 @@
 	NULL,						/* send_file */
 	NULL,						/* new_xfer */
 	NULL,						/* offline_message */
-	NULL,						/* whiteboard_prpl_ops */
+	NULL,						/* whiteboard_protocol_ops */
 	NULL,						/* send_raw */
 	NULL,						/* roomlist_room_serialize */
 	NULL,						/* unregister_user */
@@ -3549,55 +3553,49 @@
 	NULL						/* get_public_alias */
 };
 
-static PurplePluginInfo info = {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,			/**< type           */
-	NULL,					/**< ui_requirement */
-	0,					/**< flags          */
-	NULL,					/**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,			/**< priority       */
-	"prpl-novell",				/**< id             */
-	"GroupWise",				/**< name           */
-	DISPLAY_VERSION,			/**< version        */
-	/**  summary        */
-	N_("Novell GroupWise Messenger Protocol Plugin"),
-	/**  description    */
-	N_("Novell GroupWise Messenger Protocol Plugin"),
-	NULL,					/**< author         */
-	PURPLE_WEBSITE,				/**< homepage       */
-
-	NULL,					/**< load           */
-	NULL,					/**< unload         */
-	NULL,					/**< destroy        */
-
-	NULL,					/**< ui_info        */
-	&prpl_info,				/**< extra_info     */
-	NULL,
-	NULL,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin * plugin)
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-novell",
+		"name",         "GroupWise",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Novell GroupWise Messenger Protocol Plugin"),
+		"description",  N_("Novell GroupWise Messenger Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 
 	option = purple_account_option_string_new(_("Server address"), "server", NULL);
-	prpl_info.protocol_options =
-		g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options =
+		g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_int_new(_("Server port"), "port", DEFAULT_PORT);
-	prpl_info.protocol_options =
-		g_list_append(prpl_info.protocol_options, option);
-
-	my_protocol = plugin;
+	protocol.protocol_options =
+		g_list_append(protocol.protocol_options, option);
+
+	my_protocol = &protocol;
+	purple_protocols_add(my_protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(novell, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(my_protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(novell, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/null/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/null/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -20,4 +20,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/null/nullprpl.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/null/nullprpl.c	Sun Aug 18 01:53:00 2013 +0530
@@ -60,15 +60,15 @@
 #include "connection.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "roomlist.h"
 #include "status.h"
 #include "util.h"
 #include "version.h"
 
-
 #define NULLPRPL_ID "prpl-null"
-static PurplePlugin *_null_protocol = NULL;
+static PurpleProtocol *_null_protocol = NULL;
 
 #define NULL_STATUS_ONLINE   "online"
 #define NULL_STATUS_AWAY     "away"
@@ -86,7 +86,7 @@
 
 /*
  * stores offline messages that haven't been delivered yet. maps username
- * (char *) to GList * of GOfflineMessages. initialized in nullprpl_init.
+ * (char *) to GList * of GOfflineMessages. initialized in plugin_load.
  */
 GHashTable* goffline_messages = NULL;
 
@@ -171,7 +171,7 @@
         !strcmp(status_id, NULL_STATUS_OFFLINE)) {
       purple_debug_info("nullprpl", "%s sees that %s is %s: %s\n",
                         from_username, to_username, status_id, message);
-      purple_prpl_got_user_status(purple_connection_get_account(from), to_username, status_id,
+      purple_protocol_got_user_status(purple_connection_get_account(from), to_username, status_id,
                                   (message) ? "message" : NULL, message, NULL);
     } else {
       purple_debug_error("nullprpl",
@@ -192,9 +192,9 @@
 /*
  * UI callbacks
  */
-static void nullprpl_input_user_info(PurplePluginAction *action)
+static void nullprpl_input_user_info(PurpleProtocolAction *action)
 {
-  PurpleConnection *gc = (PurpleConnection *)action->context;
+  PurpleConnection *gc = action->connection;
   PurpleAccount *acct = purple_connection_get_account(gc);
   purple_debug_info("nullprpl", "showing 'Set User Info' dialog for %s\n",
                     purple_account_get_username(acct));
@@ -202,20 +202,16 @@
   purple_account_request_change_user_info(acct);
 }
 
-/* this is set to the actions member of the PurplePluginInfo struct at the
- * bottom.
+/*
+ * prpl functions
  */
-static GList *nullprpl_actions(PurplePlugin *plugin, gpointer context)
+static GList *nullprpl_get_actions(PurpleConnection *gc)
 {
-  PurplePluginAction *action = purple_plugin_action_new(
+  PurpleProtocolAction *action = purple_protocol_action_new(
     _("Set User Info..."), nullprpl_input_user_info);
   return g_list_append(NULL, action);
 }
 
-
-/*
- * prpl functions
- */
 static const char *nullprpl_list_icon(PurpleAccount *acct, PurpleBuddy *buddy)
 {
   return "null";
@@ -337,7 +333,7 @@
 }
 
 static GList *nullprpl_chat_info(PurpleConnection *gc) {
-  struct proto_chat_entry *pce; /* defined in prpl.h */
+  struct proto_chat_entry *pce; /* defined in protocol.h */
 
   purple_debug_info("nullprpl", "returning chat setting 'room'\n");
 
@@ -1054,15 +1050,17 @@
 
 
 /*
- * prpl stuff. see prpl.h for more information.
+ * Protocol stuff. see protocol.h for more information.
  */
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-  sizeof(PurplePluginProtocolInfo),    /* struct_size */
+  NULLPRPL_ID,                         /* id */
+  "Null - Testing protocol",           /* name */
+  sizeof(PurpleProtocol),    /* 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() */
+  NULL,               /* user_splits, initialized in plugin_load() */
+  NULL,               /* protocol_options, initialized in plugin_load() */
   {   /* icon_spec, a PurpleBuddyIconSpec */
       "png,jpg,gif",                   /* format */
       0,                               /* min_width */
@@ -1072,6 +1070,7 @@
       10000,                           /* max_filesize */
       PURPLE_ICON_SCALE_DISPLAY,       /* scale_rules */
   },
+  nullprpl_get_actions,                /* get_actions */
   nullprpl_list_icon,                  /* list_icon */
   NULL,                                /* list_emblem */
   nullprpl_status_text,                /* status_text */
@@ -1126,7 +1125,7 @@
   NULL,                                /* send_file */
   NULL,                                /* new_xfer */
   nullprpl_offline_message,            /* offline_message */
-  NULL,                                /* whiteboard_prpl_ops */
+  NULL,                                /* whiteboard_protocol_ops */
   NULL,                                /* send_raw */
   NULL,                                /* roomlist_room_serialize */
   NULL,                                /* unregister_user */
@@ -1140,7 +1139,29 @@
   NULL                                 /* get_public_alias */
 };
 
-static void nullprpl_init(PurplePlugin *plugin)
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+  return purple_plugin_info_new(
+    "id",           NULLPRPL_ID,
+    "name",         "Null - Testing Plugin",
+    "version",      DISPLAY_VERSION,
+    "category",     N_("Protocol"),
+    "summary",      N_("Null Protocol Plugin"),
+    "description",  N_("Null Protocol Plugin"),
+    "website",      PURPLE_WEBSITE,
+    "abi-version",  PURPLE_ABI_VERSION,
+
+    /* If you're using this as the basis of a protocol plugin that will be
+     * distributed separately from libpurple, do not include these flags.*/
+    "flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+                    GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+    NULL
+  );
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
   /* see accountopt.h for information about user splits and protocol options */
   PurpleAccountUserSplit *split = purple_account_user_split_new(
@@ -1154,8 +1175,8 @@
 
   purple_debug_info("nullprpl", "starting up\n");
 
-  prpl_info.user_splits = g_list_append(NULL, split);
-  prpl_info.protocol_options = g_list_append(NULL, option);
+  protocol.user_splits = g_list_append(NULL, split);
+  protocol.protocol_options = g_list_append(NULL, option);
 
   /* register whisper chat command, /msg */
   purple_cmd_register("msg",
@@ -1173,42 +1194,20 @@
                                             g_free,      /* key free fn */
                                             NULL);       /* value free fn */
 
-  _null_protocol = plugin;
-}
+  _null_protocol = &protocol;
+  purple_protocols_add(_null_protocol);
 
-static void nullprpl_destroy(PurplePlugin *plugin) {
-  purple_debug_info("nullprpl", "shutting down\n");
+  return TRUE;
 }
 
-
-static PurplePluginInfo info =
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
 {
-  PURPLE_PLUGIN_MAGIC,                                     /* magic */
-  PURPLE_MAJOR_VERSION,                                    /* major_version */
-  PURPLE_MINOR_VERSION,                                    /* minor_version */
-  PURPLE_PLUGIN_PROTOCOL,                                  /* type */
-  NULL,                                                    /* ui_requirement */
-  0,                                                       /* flags */
-  NULL,                                                    /* dependencies */
-  PURPLE_PRIORITY_DEFAULT,                                 /* priority */
-  NULLPRPL_ID,                                             /* id */
-  "Null - Testing Plugin",                                 /* name */
-  DISPLAY_VERSION,                                         /* version */
-  N_("Null Protocol Plugin"),                              /* summary */
-  N_("Null Protocol Plugin"),                              /* description */
-  NULL,                                                    /* author */
-  PURPLE_WEBSITE,                                          /* homepage */
-  NULL,                                                    /* load */
-  NULL,                                                    /* unload */
-  nullprpl_destroy,                                        /* destroy */
-  NULL,                                                    /* ui_info */
-  &prpl_info,                                              /* extra_info */
-  NULL,                                                    /* prefs_info */
-  nullprpl_actions,                                        /* actions */
-  NULL,                                                    /* padding... */
-  NULL,
-  NULL,
-  NULL,
-};
+  purple_debug_info("nullprpl", "shutting down\n");
+
+  purple_protocols_remove(_null_protocol);
 
-PURPLE_INIT_PLUGIN(null, nullprpl_init, info);
+  return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(null, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/oscar/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -78,4 +78,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/oscar/authorization.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/authorization.c	Sun Aug 18 01:53:00 2013 +0530
@@ -55,10 +55,10 @@
 
 			/* Mobile users should always be online */
 			if (bname[0] == '+') {
-				purple_prpl_got_user_status(account,
+				purple_protocol_got_user_status(account,
 						purple_buddy_get_name(buddy),
 						OSCAR_STATUS_ID_AVAILABLE, NULL);
-				purple_prpl_got_user_status(account,
+				purple_protocol_got_user_status(account,
 						purple_buddy_get_name(buddy),
 						OSCAR_STATUS_ID_MOBILE, NULL);
 			}
--- a/libpurple/protocols/oscar/family_icbm.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/family_icbm.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1727,7 +1727,7 @@
 						presence = purple_buddy_get_presence(buddy);
 						status = purple_presence_get_status(presence, "mood");
 						if (status) {
-							purple_prpl_got_user_status(account, bn,
+							purple_protocol_got_user_status(account, bn,
 									"mood",
 									PURPLE_MOOD_NAME, purple_status_get_attr_string(status, PURPLE_MOOD_NAME),
 									PURPLE_MOOD_COMMENT, unescaped_xstatus, NULL);
--- a/libpurple/protocols/oscar/family_icq.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/family_icq.c	Sun Aug 18 01:53:00 2013 +0530
@@ -628,7 +628,7 @@
 				presence = purple_buddy_get_presence(buddy);
 				status = purple_presence_get_active_status(presence);
 
-				purple_prpl_got_user_status(account, uin,
+				purple_protocol_got_user_status(account, uin,
 						purple_status_get_id(status),
 						"message", NULL, NULL);
 
--- a/libpurple/protocols/oscar/family_locate.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/family_locate.c	Sun Aug 18 01:53:00 2013 +0530
@@ -929,11 +929,11 @@
 
 			mood = aim_receive_custom_icon(od, bs, length);
 			if (mood)
-				purple_prpl_got_user_status(account, outinfo->bn, "mood",
+				purple_protocol_got_user_status(account, outinfo->bn, "mood",
 						PURPLE_MOOD_NAME, mood,
 						NULL);
 			else
-				purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
+				purple_protocol_got_user_status_deactive(account, outinfo->bn, "mood");
 
 		} else if (type == 0x000e) {
 			/*
@@ -1093,11 +1093,11 @@
 						g_free(icqmood);
 
 						if (mood)
-							purple_prpl_got_user_status(account, outinfo->bn, "mood",
+							purple_protocol_got_user_status(account, outinfo->bn, "mood",
 									PURPLE_MOOD_NAME, mood,
 									NULL);
 						else
-							purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
+							purple_protocol_got_user_status_deactive(account, outinfo->bn, "mood");
 					} break;
 				}
 
@@ -1415,11 +1415,11 @@
 
 		mood = aim_receive_custom_icon(od, &cbs, tlv->length);
 		if (mood)
-			purple_prpl_got_user_status(account, userinfo->bn, "mood",
+			purple_protocol_got_user_status(account, userinfo->bn, "mood",
 					PURPLE_MOOD_NAME, mood,
 					NULL);
 		else
-			purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood");
+			purple_protocol_got_user_status_deactive(account, userinfo->bn, "mood");
 	}
 	aim_tlvlist_free(tlvlist);
 
--- a/libpurple/protocols/oscar/libaim.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/libaim.c	Sun Aug 18 01:53:00 2013 +0530
@@ -24,17 +24,22 @@
  * which contains all the shared implementation code with libicq
  */
 
+#include "plugins.h"
+
 #include "oscarcommon.h"
 #include "oscar.h"
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-aim",				/* id */
+	"AIM",					/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
 	{"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-	oscar_list_icon_aim,		/* list_icon */
+	oscar_get_actions,		/* get_actions */
+	oscar_list_icon_aim,	/* list_icon */
 	oscar_list_emblem,		/* list_emblems */
 	oscar_status_text,		/* status_text */
 	oscar_tooltip_text,		/* tooltip_text */
@@ -88,7 +93,7 @@
 	oscar_send_file,		/* send_file */
 	oscar_new_xfer,			/* new_xfer */
 	oscar_offline_message,	/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
+	NULL,					/* whiteboard_protocol_ops */
 	NULL,					/* send_raw */
 	NULL,					/* roomlist_room_serialize */
 	NULL,					/* unregister_user */
@@ -102,47 +107,39 @@
 	NULL					/* get_public_alias */
 };
 
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	"prpl-aim",                                       /**< id             */
-	"AIM",                                            /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("AIM Protocol Plugin"),
-	                                                  /**  description    */
-	N_("AIM Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	oscar_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	oscar_init(plugin, FALSE);
+	return purple_plugin_info_new(
+		"id",           "prpl-aim",
+		"name",         "AIM",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("AIM Protocol Plugin"),
+		"description",  N_("AIM Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
 }
 
-PURPLE_INIT_PLUGIN(aim, init_plugin, info);
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
+{
+	oscar_init(&protocol, FALSE);
+	purple_protocols_add(&protocol);
+
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(&protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(aim, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/oscar/libicq.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/libicq.c	Sun Aug 18 01:53:00 2013 +0530
@@ -24,6 +24,7 @@
  * which contains all the shared implementation code with libaim
  */
 
+#include "plugins.h"
 
 #include "oscarcommon.h"
 
@@ -36,14 +37,17 @@
 	return table;
 }
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-icq",				/* id */
+	"ICQ",					/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
 	{"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-	oscar_list_icon_icq,		/* list_icon */
+	oscar_get_actions,		/* get_actions */
+	oscar_list_icon_icq,	/* list_icon */
 	oscar_list_emblem,		/* list_emblems */
 	oscar_status_text,		/* status_text */
 	oscar_tooltip_text,		/* tooltip_text */
@@ -97,7 +101,7 @@
 	oscar_send_file,		/* send_file */
 	oscar_new_xfer,			/* new_xfer */
 	oscar_offline_message,	/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
+	NULL,					/* whiteboard_protocol_ops */
 	NULL,					/* send_raw */
 	NULL,					/* roomlist_room_serialize */
 	NULL,					/* unregister_user */
@@ -111,52 +115,45 @@
 	NULL					/* get_public_alias */
 };
 
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
+	return purple_plugin_info_new(
+		"id",           "prpl-icq",
+		"name",         "ICQ",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("ICQ Protocol Plugin"),
+		"description",  N_("ICQ Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-	"prpl-icq",                                     /**< id             */
-	"ICQ",                                        /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("ICQ Protocol Plugin"),
-	                                                  /**  description    */
-	N_("ICQ Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	oscar_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 
-	oscar_init(plugin, TRUE);
+	oscar_init(&protocol, TRUE);
 
 	option = purple_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
+
+	purple_protocols_add(&protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(icq, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(&protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(icq, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/oscar/oscar.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/oscar.c	Sun Aug 18 01:53:00 2013 +0530
@@ -41,7 +41,7 @@
 #include "imgstore.h"
 #include "network.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "proxy.h"
 #include "request.h"
 #include "util.h"
@@ -745,8 +745,8 @@
 	od->use_ssl = purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0;
 
 	/* Connect to core Purple signals */
-	purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc);
-	purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc);
+	purple_prefs_connect_callback(purple_connection_get_protocol_info(gc), "/purple/away/idle_reporting", idle_reporting_pref_cb, gc);
+	purple_prefs_connect_callback(purple_connection_get_protocol_info(gc), "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc);
 
 	/*
 	 * On 2008-03-05 AOL released some documentation on the OSCAR protocol
@@ -1244,9 +1244,9 @@
 	}
 
 	if (info->flags & AIM_FLAG_WIRELESS) {
-		purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL);
+		purple_protocol_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL);
 	} else {
-		purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
+		purple_protocol_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
 	}
 
 	message = (info->status && info->status_len > 0)
@@ -1262,10 +1262,10 @@
 			itmsurl = g_strdup(purple_status_get_attr_string(previous_status, "itmsurl"));
 		}
 		purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s', itmsurl = '%s'\n", status_id, info->bn, message ? message : "(null)", itmsurl ? itmsurl : "(null)");
-		purple_prpl_got_user_status(account, info->bn, status_id, "message", message, "itmsurl", itmsurl, NULL);
+		purple_protocol_got_user_status(account, info->bn, status_id, "message", message, "itmsurl", itmsurl, NULL);
 	} else {
 		purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s'\n", status_id, info->bn, message ? message : "(null)");
-		purple_prpl_got_user_status(account, info->bn, status_id, "message", message, NULL);
+		purple_protocol_got_user_status(account, info->bn, status_id, "message", message, NULL);
 	}
 
 	g_free(message);
@@ -1276,7 +1276,7 @@
 		signon = info->onlinesince;
 	else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
 		signon = time(NULL) - info->sessionlen;
-	purple_prpl_got_user_login_time(account, info->bn, signon);
+	purple_protocol_got_user_login_time(account, info->bn, signon);
 
 	/* Idle time stuff */
 	/* info->idletime is the number of minutes that this user has been idle */
@@ -1284,9 +1284,9 @@
 		time_idle = time(NULL) - info->idletime * 60;
 
 	if (time_idle > 0)
-		purple_prpl_got_user_idle(account, info->bn, TRUE, time_idle);
+		purple_protocol_got_user_idle(account, info->bn, TRUE, time_idle);
 	else
-		purple_prpl_got_user_idle(account, info->bn, FALSE, 0);
+		purple_protocol_got_user_idle(account, info->bn, FALSE, 0);
 
 	/* Server stored icon stuff */
 	bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, info->bn));
@@ -1337,8 +1337,8 @@
 	info = va_arg(ap, aim_userinfo_t *);
 	va_end(ap);
 
-	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);
+	purple_protocol_got_user_status(account, info->bn, OSCAR_STATUS_ID_OFFLINE, NULL);
+	purple_protocol_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
 	g_hash_table_remove(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), info->bn));
 
 	return 1;
@@ -3516,9 +3516,9 @@
 
 			/* Mobile users should always be online */
 			if (bname[0] == '+') {
-				purple_prpl_got_user_status(account, bname,
+				purple_protocol_got_user_status(account, bname,
 						OSCAR_STATUS_ID_AVAILABLE, NULL);
-				purple_prpl_got_user_status(account, bname,
+				purple_protocol_got_user_status(account, bname,
 						OSCAR_STATUS_ID_MOBILE, NULL);
 			}
 		} else if (aim_ssi_waitingforauth(&od->ssi.local,
@@ -3835,10 +3835,10 @@
 
 					/* Mobile users should always be online */
 					if (curitem->name[0] == '+') {
-						purple_prpl_got_user_status(account,
+						purple_protocol_got_user_status(account,
 								purple_buddy_get_name(b),
 								OSCAR_STATUS_ID_AVAILABLE, NULL);
-						purple_prpl_got_user_status(account,
+						purple_protocol_got_user_status(account,
 								purple_buddy_get_name(b),
 								OSCAR_STATUS_ID_MOBILE, NULL);
 					}
@@ -4049,9 +4049,9 @@
 
 		/* Mobile users should always be online */
 		if (name[0] == '+') {
-			purple_prpl_got_user_status(account,
+			purple_protocol_got_user_status(account,
 					name, OSCAR_STATUS_ID_AVAILABLE, NULL);
-			purple_prpl_got_user_status(account,
+			purple_protocol_got_user_status(account,
 					name, OSCAR_STATUS_ID_MOBILE, NULL);
 		}
 
@@ -4989,9 +4989,9 @@
 }
 
 static void
-oscar_show_icq_privacy_opts(PurplePluginAction *action)
+oscar_show_icq_privacy_opts(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *g;
@@ -5021,13 +5021,13 @@
 						gc);
 }
 
-static void oscar_confirm_account(PurplePluginAction *action)
+static void oscar_confirm_account(PurpleProtocolAction *action)
 {
 	PurpleConnection *gc;
 	OscarData *od;
 	FlapConnection *conn;
 
-	gc = (PurpleConnection *)action->context;
+	gc = action->connection;
 	od = purple_connection_get_protocol_data(gc);
 
 	conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
@@ -5039,9 +5039,9 @@
 	}
 }
 
-static void oscar_show_email(PurplePluginAction *action)
+static void oscar_show_email(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	OscarData *od = purple_connection_get_protocol_data(gc);
 	FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
 
@@ -5067,9 +5067,9 @@
 	}
 }
 
-static void oscar_show_change_email(PurplePluginAction *action)
+static void oscar_show_change_email(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_request_input(gc, NULL, _("Change Address To:"), NULL, NULL,
 					   FALSE, FALSE, NULL,
 					   _("_OK"), G_CALLBACK(oscar_change_email),
@@ -5078,9 +5078,9 @@
 					   gc);
 }
 
-static void oscar_show_awaitingauth(PurplePluginAction *action)
+static void oscar_show_awaitingauth(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	OscarData *od = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	GSList *buddies, *filtered_buddies, *cur;
@@ -5121,9 +5121,9 @@
 	aim_search_address(od, email);
 }
 
-static void oscar_show_find_email(PurplePluginAction *action)
+static void oscar_show_find_email(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_request_input(gc, _("Find Buddy by Email"),
 					   _("Search for a buddy by email address"),
 					   _("Type the email address of the buddy you are "
@@ -5135,39 +5135,39 @@
 					   gc);
 }
 
-static void oscar_show_set_info(PurplePluginAction *action)
+static void oscar_show_set_info(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_account_request_change_user_info(purple_connection_get_account(gc));
 }
 
-static void oscar_show_set_info_icqurl(PurplePluginAction *action)
+static void oscar_show_set_info_icqurl(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_notify_uri(gc, "http://www.icq.com/whitepages/user_details.php");
 }
 
-static void oscar_change_pass(PurplePluginAction *action)
+static void oscar_change_pass(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_account_request_change_password(purple_connection_get_account(gc));
 }
 
 /**
  * Only used when connecting with the old-style BUCP login.
  */
-static void oscar_show_chpassurl(PurplePluginAction *action)
+static void oscar_show_chpassurl(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	OscarData *od = purple_connection_get_protocol_data(gc);
 	gchar *substituted = purple_strreplace(od->authinfo->chpassurl, "%s", purple_account_get_username(purple_connection_get_account(gc)));
 	purple_notify_uri(gc, substituted);
 	g_free(substituted);
 }
 
-static void oscar_show_imforwardingurl(PurplePluginAction *action)
+static void oscar_show_imforwardingurl(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1");
 }
 
@@ -5274,39 +5274,38 @@
 }
 
 GList *
-oscar_actions(PurplePlugin *plugin, gpointer context)
+oscar_get_actions(PurpleConnection *gc)
 {
-	PurpleConnection *gc = (PurpleConnection *) context;
 	OscarData *od = purple_connection_get_protocol_data(gc);
 	GList *menu = NULL;
-	PurplePluginAction *act;
-
-	act = purple_plugin_action_new(_("Set User Info..."),
+	PurpleProtocolAction *act;
+
+	act = purple_protocol_action_new(_("Set User Info..."),
 			oscar_show_set_info);
 	menu = g_list_prepend(menu, act);
 
 	if (od->icq)
 	{
-		act = purple_plugin_action_new(_("Set User Info (web)..."),
+		act = purple_protocol_action_new(_("Set User Info (web)..."),
 				oscar_show_set_info_icqurl);
 		menu = g_list_prepend(menu, act);
 	}
 
-	act = purple_plugin_action_new(_("Change Password..."),
+	act = purple_protocol_action_new(_("Change Password..."),
 			oscar_change_pass);
 	menu = g_list_prepend(menu, act);
 
 	if (od->authinfo != NULL && od->authinfo->chpassurl != NULL)
 	{
 		/* This only happens when connecting with the old-style BUCP login */
-		act = purple_plugin_action_new(_("Change Password (web)"),
+		act = purple_protocol_action_new(_("Change Password (web)"),
 				oscar_show_chpassurl);
 		menu = g_list_prepend(menu, act);
 	}
 
 	if (!od->icq)
 	{
-		act = purple_plugin_action_new(_("Configure IM Forwarding (web)"),
+		act = purple_protocol_action_new(_("Configure IM Forwarding (web)"),
 				oscar_show_imforwardingurl);
 		menu = g_list_prepend(menu, act);
 	}
@@ -5316,41 +5315,41 @@
 	if (od->icq)
 	{
 		/* ICQ actions */
-		act = purple_plugin_action_new(_("Set Privacy Options..."),
+		act = purple_protocol_action_new(_("Set Privacy Options..."),
 				oscar_show_icq_privacy_opts);
 		menu = g_list_prepend(menu, act);
 
-		act = purple_plugin_action_new(_("Show Visible List"), oscar_show_visible_list);
+		act = purple_protocol_action_new(_("Show Visible List"), oscar_show_visible_list);
 		menu = g_list_prepend(menu, act);
 
-		act = purple_plugin_action_new(_("Show Invisible List"), oscar_show_invisible_list);
+		act = purple_protocol_action_new(_("Show Invisible List"), oscar_show_invisible_list);
 		menu = g_list_prepend(menu, act);
 	}
 	else
 	{
 		/* AIM actions */
-		act = purple_plugin_action_new(_("Confirm Account"),
+		act = purple_protocol_action_new(_("Confirm Account"),
 				oscar_confirm_account);
 		menu = g_list_prepend(menu, act);
 
-		act = purple_plugin_action_new(_("Display Currently Registered Email Address"),
+		act = purple_protocol_action_new(_("Display Currently Registered Email Address"),
 				oscar_show_email);
 		menu = g_list_prepend(menu, act);
 
-		act = purple_plugin_action_new(_("Change Currently Registered Email Address..."),
+		act = purple_protocol_action_new(_("Change Currently Registered Email Address..."),
 				oscar_show_change_email);
 		menu = g_list_prepend(menu, act);
 	}
 
 	menu = g_list_prepend(menu, NULL);
 
-	act = purple_plugin_action_new(_("Show Buddies Awaiting Authorization"),
+	act = purple_protocol_action_new(_("Show Buddies Awaiting Authorization"),
 			oscar_show_awaitingauth);
 	menu = g_list_prepend(menu, act);
 
 	menu = g_list_prepend(menu, NULL);
 
-	act = purple_plugin_action_new(_("Search for Buddy by Email Address..."),
+	act = purple_protocol_action_new(_("Search for Buddy by Email Address..."),
 			oscar_show_find_email);
 	menu = g_list_prepend(menu, act);
 
@@ -5530,9 +5529,8 @@
 	return FALSE;
 }
 
-void oscar_init(PurplePlugin *plugin, gboolean is_icq)
+void oscar_init(PurpleProtocol *protocol, gboolean is_icq)
 {
-	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 	PurpleAccountOption *option;
 	static gboolean init = FALSE;
 	static const gchar *encryption_keys[] = {
@@ -5551,10 +5549,10 @@
 	int i;
 
 	option = purple_account_option_string_new(_("Server"), "server", get_login_server(is_icq, TRUE));
-	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+	protocol->protocol_options = g_list_append(protocol->protocol_options, option);
 
 	option = purple_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT);
-	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+	protocol->protocol_options = g_list_append(protocol->protocol_options, option);
 
 	for (i = 0; encryption_keys[i]; i++) {
 		PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1);
@@ -5563,21 +5561,21 @@
 		encryption_options = g_list_append(encryption_options, kvp);
 	}
 	option = purple_account_option_list_new(_("Connection security"), "encryption", encryption_options);
-	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+	protocol->protocol_options = g_list_append(protocol->protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Use clientLogin"), "use_clientlogin",
 			OSCAR_DEFAULT_USE_CLIENTLOGIN);
-	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+	protocol->protocol_options = g_list_append(protocol->protocol_options, option);
 
 	option = purple_account_option_bool_new(
 		_("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy",
 		OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY);
-	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
-
-	if (g_str_equal(purple_plugin_get_id(plugin), "prpl-aim")) {
+	protocol->protocol_options = g_list_append(protocol->protocol_options, option);
+
+	if (g_str_equal(protocol->id, "prpl-aim")) {
 		option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins",
 												OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS);
-		prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+		protocol->protocol_options = g_list_append(protocol->protocol_options, option);
 	}
 
 	if (init)
@@ -5593,7 +5591,7 @@
 
 	/* protocol handler */
 	/* TODO: figure out a good instance to use here */
-	purple_signal_connect(purple_get_core(), "uri-handler", &init,
+	purple_signal_connect(purple_get_core(), "uri-handler", protocol,
 		PURPLE_CALLBACK(oscar_uri_handler), NULL);
 }
 
--- a/libpurple/protocols/oscar/oscarcommon.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/oscarcommon.h	Sun Aug 18 01:53:00 2013 +0530
@@ -27,7 +27,7 @@
 #include "internal.h"
 
 #include "accountopt.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "version.h"
 #include "notify.h"
 #include "status.h"
@@ -102,5 +102,5 @@
 void oscar_send_file(PurpleConnection *gc, const char *who, const char *file);
 PurpleXfer *oscar_new_xfer(PurpleConnection *gc, const char *who);
 gboolean oscar_offline_message(const PurpleBuddy *buddy);
-GList *oscar_actions(PurplePlugin *plugin, gpointer context);
-void oscar_init(PurplePlugin *plugin, gboolean is_icq);
+GList *oscar_get_actions(PurpleConnection *gc);
+void oscar_init(PurpleProtocol *protocol, gboolean is_icq);
--- a/libpurple/protocols/oscar/visibility.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/visibility.c	Sun Aug 18 01:53:00 2013 +0530
@@ -86,9 +86,9 @@
 }
 
 static void
-show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name)
+show_private_list(PurpleProtocolAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	OscarData *od = purple_connection_get_protocol_data(gc);
 	PurpleAccount *account = purple_connection_get_account(gc);
 	GSList *buddies, *filtered_buddies, *cur;
@@ -122,7 +122,7 @@
 }
 
 void
-oscar_show_visible_list(PurplePluginAction *action)
+oscar_show_visible_list(PurpleProtocolAction *action)
 {
 	show_private_list(action, AIM_SSI_TYPE_PERMIT, _("Visible List"),
 							_("These buddies will see "
@@ -132,7 +132,7 @@
 }
 
 void
-oscar_show_invisible_list(PurplePluginAction *action)
+oscar_show_invisible_list(PurpleProtocolAction *action)
 {
 	show_private_list(action, AIM_SSI_TYPE_DENY, _("Invisible List"),
 							_("These buddies will always see you as offline"),
--- a/libpurple/protocols/oscar/visibility.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/oscar/visibility.h	Sun Aug 18 01:53:00 2013 +0530
@@ -22,11 +22,11 @@
 #define _VISIBILITY_H_
 
 #include "oscar.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "util.h"
 
 PurpleMenuAction * create_visibility_menu_item(OscarData *od, const char *bname);
-void oscar_show_visible_list(PurplePluginAction *action);
-void oscar_show_invisible_list(PurplePluginAction *action);
+void oscar_show_visible_list(PurpleProtocolAction *action);
+void oscar_show_invisible_list(PurpleProtocolAction *action);
 
-#endif
\ No newline at end of file
+#endif
--- a/libpurple/protocols/sametime/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/sametime/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -32,6 +32,7 @@
 	-I$(top_builddir)/libpurple \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(MEANWHILE_CFLAGS) \
 	-DG_LOG_DOMAIN=\"sametime\"
 
--- a/libpurple/protocols/sametime/sametime.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/sametime/sametime.c	Sun Aug 18 01:53:00 2013 +0530
@@ -40,8 +40,8 @@
 #include "imgstore.h"
 #include "mime.h"
 #include "notify.h"
-#include "plugin.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "request.h"
 #include "util.h"
 #include "version.h"
@@ -71,6 +71,7 @@
 /* scratch that, I just added it to the prpl options panel */
 #define PLUGIN_ID        "prpl-meanwhile"
 #define PLUGIN_NAME      "Sametime"
+#define PLUGIN_CATEGORY  "Protocol"
 #define PLUGIN_SUMMARY   "Sametime Protocol Plugin"
 #define PLUGIN_DESC      "Open implementation of a Lotus Sametime client"
 #define PLUGIN_AUTHOR    "Christopher (siege) O'Brien <siege@preoccupied.net>"
@@ -78,11 +79,11 @@
 
 
 /* plugin preference names */
-#define MW_PRPL_OPT_BASE          "/plugins/prpl/meanwhile"
-#define MW_PRPL_OPT_BLIST_ACTION  MW_PRPL_OPT_BASE "/blist_action"
-#define MW_PRPL_OPT_PSYCHIC       MW_PRPL_OPT_BASE "/psychic"
-#define MW_PRPL_OPT_FORCE_LOGIN   MW_PRPL_OPT_BASE "/force_login"
-#define MW_PRPL_OPT_SAVE_DYNAMIC  MW_PRPL_OPT_BASE "/save_dynamic"
+#define MW_PROTOCOL_OPT_BASE          "/plugins/prpl/meanwhile"
+#define MW_PROTOCOL_OPT_BLIST_ACTION  MW_PROTOCOL_OPT_BASE "/blist_action"
+#define MW_PROTOCOL_OPT_PSYCHIC       MW_PROTOCOL_OPT_BASE "/psychic"
+#define MW_PROTOCOL_OPT_FORCE_LOGIN   MW_PROTOCOL_OPT_BASE "/force_login"
+#define MW_PROTOCOL_OPT_SAVE_DYNAMIC  MW_PROTOCOL_OPT_BASE "/save_dynamic"
 
 
 /* stages of connecting-ness */
@@ -162,7 +163,7 @@
 
 
 /* testing for the above */
-#define BLIST_PREF_IS(n) (purple_prefs_get_int(MW_PRPL_OPT_BLIST_ACTION)==(n))
+#define BLIST_PREF_IS(n) (purple_prefs_get_int(MW_PROTOCOL_OPT_BLIST_ACTION)==(n))
 #define BLIST_PREF_IS_LOCAL()  BLIST_PREF_IS(blist_choice_LOCAL)
 #define BLIST_PREF_IS_MERGE()  BLIST_PREF_IS(blist_choice_MERGE)
 #define BLIST_PREF_IS_STORE()  BLIST_PREF_IS(blist_choice_STORE)
@@ -197,7 +198,7 @@
 
 /** the purple plugin data.
     available as purple_connection_get_protocol_data(gc) and mwSession_getClientData */
-struct mwPurplePluginData {
+struct mwPurpleProtocolData {
   struct mwSession *session;
 
   struct mwServiceAware *srvc_aware;
@@ -236,9 +237,9 @@
 
 static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist);
 
-static void blist_store(struct mwPurplePluginData *pd);
-
-static void blist_schedule(struct mwPurplePluginData *pd);
+static void blist_store(struct mwPurpleProtocolData *pd);
+
+static void blist_schedule(struct mwPurpleProtocolData *pd);
 
 static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist);
 
@@ -246,19 +247,19 @@
 
 static gboolean buddy_is_external(PurpleBuddy *b);
 
-static void buddy_add(struct mwPurplePluginData *pd, PurpleBuddy *buddy);
+static void buddy_add(struct mwPurpleProtocolData *pd, PurpleBuddy *buddy);
 
 static PurpleBuddy *
 buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
 	     struct mwSametimeUser *stuser);
 
-static void group_add(struct mwPurplePluginData *pd, PurpleGroup *group);
+static void group_add(struct mwPurpleProtocolData *pd, PurpleGroup *group);
 
 static PurpleGroup *
 group_ensure(PurpleConnection *gc, struct mwSametimeGroup *stgroup);
 
 static struct mwAwareList *
-list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group);
+list_ensure(struct mwPurpleProtocolData *pd, PurpleGroup *group);
 
 
 /* session functions */
@@ -272,7 +273,7 @@
 /* conference functions */
 
 static struct mwConference *
-conf_find_by_id(struct mwPurplePluginData *pd, int id);
+conf_find_by_id(struct mwPurpleProtocolData *pd, int id);
 
 
 /* conversation functions */
@@ -316,7 +317,7 @@
 
 /** resolves a mwSession from a PurpleConnection */
 static struct mwSession *gc_to_session(PurpleConnection *gc) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   g_return_val_if_fail(gc != NULL, NULL);
 
@@ -329,7 +330,7 @@
 
 /** resolves a PurpleConnection from a mwSession */
 static PurpleConnection *session_to_gc(struct mwSession *session) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   g_return_val_if_fail(session != NULL, NULL);
 
@@ -341,7 +342,7 @@
 
 
 static void write_cb(gpointer data, gint source, PurpleInputCondition cond) {
-  struct mwPurplePluginData *pd = data;
+  struct mwPurpleProtocolData *pd = data;
   PurpleCircularBuffer *circ = pd->sock_buf;
   gsize avail;
   int ret;
@@ -373,7 +374,7 @@
 
 static int mw_session_io_write(struct mwSession *session,
 			       const guchar *buf, gsize len) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   gssize ret = 0;
   int err = 0;
 
@@ -431,7 +432,7 @@
 
 
 static void mw_session_io_close(struct mwSession *session) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   pd = mwSession_getClientData(session);
   g_return_if_fail(pd != NULL);
@@ -487,7 +488,7 @@
   PurpleConnection *gc;
   PurpleAccount *acct;
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   guint32 idle;
   guint stat;
   const char *id;
@@ -592,11 +593,11 @@
   }
 
   if(aware->online) {
-    purple_prpl_got_user_status(acct, id, status, NULL);
-    purple_prpl_got_user_idle(acct, id, !!idle, (time_t) idle);
+    purple_protocol_got_user_status(acct, id, status, NULL);
+    purple_protocol_got_user_idle(acct, id, !!idle, (time_t) idle);
 
   } else {
-    purple_prpl_got_user_status(acct, id, MW_STATE_OFFLINE, NULL);
+    purple_protocol_got_user_status(acct, id, MW_STATE_OFFLINE, NULL);
   }
 }
 
@@ -624,7 +625,7 @@
 /** Ensures that an Aware List is associated with the given group, and
     returns that list. */
 static struct mwAwareList *
-list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group) {
+list_ensure(struct mwPurpleProtocolData *pd, PurpleGroup *group) {
 
   struct mwAwareList *list;
 
@@ -741,7 +742,7 @@
 }
 
 
-static void blist_store(struct mwPurplePluginData *pd) {
+static void blist_store(struct mwPurpleProtocolData *pd) {
 
   struct mwSametimeList *stlist;
   struct mwServiceStorage *srvc;
@@ -794,7 +795,7 @@
 
 
 static gboolean blist_save_cb(gpointer data) {
-  struct mwPurplePluginData *pd = data;
+  struct mwPurpleProtocolData *pd = data;
 
   blist_store(pd);
   pd->save_event = 0;
@@ -803,7 +804,7 @@
 
 
 /** schedules the buddy list to be saved to the server */
-static void blist_schedule(struct mwPurplePluginData *pd) {
+static void blist_schedule(struct mwPurpleProtocolData *pd) {
   if(pd->save_event) return;
 
   pd->save_event = purple_timeout_add_seconds(BLIST_SAVE_SECONDS,
@@ -819,7 +820,7 @@
 
 /** Actually add a buddy to the aware service, and schedule the buddy
     list to be saved to the server */
-static void buddy_add(struct mwPurplePluginData *pd,
+static void buddy_add(struct mwPurpleProtocolData *pd,
 		      PurpleBuddy *buddy) {
 
   struct mwAwareIdBlock idb = { mwAware_USER, (char *) purple_buddy_get_name(buddy), NULL };
@@ -848,7 +849,7 @@
 static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
 			       struct mwSametimeUser *stuser) {
 
-  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
+  struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
   PurpleBuddy *buddy;
   PurpleAccount *acct = purple_connection_get_account(gc);
 
@@ -878,7 +879,7 @@
 
 
 /** add aware watch for a dynamic group */
-static void group_add(struct mwPurplePluginData *pd,
+static void group_add(struct mwPurpleProtocolData *pd,
 		      PurpleGroup *group) {
 
   struct mwAwareIdBlock idb = { mwAware_GROUP, NULL, NULL };
@@ -1227,7 +1228,7 @@
 			   guint32 result, struct mwStorageUnit *item,
 			   gpointer data) {
 
-  struct mwPurplePluginData *pd = data;
+  struct mwPurpleProtocolData *pd = data;
   struct mwSametimeList *stlist;
 
   struct mwGetBuffer *b;
@@ -1260,7 +1261,7 @@
 
 /** signal triggered when a conversation is opened in Purple */
 static void conversation_created_cb(PurpleConversation *g_conv,
-				    struct mwPurplePluginData *pd) {
+				    struct mwPurpleProtocolData *pd) {
 
   /* we need to tell the IM service to negotiate features for the
      conversation right away, otherwise it'll wait until the first
@@ -1293,7 +1294,7 @@
 
 
 static void blist_menu_nab(PurpleBlistNode *node, gpointer data) {
-  struct mwPurplePluginData *pd = data;
+  struct mwPurpleProtocolData *pd = data;
   PurpleConnection *gc;
 
   PurpleGroup *group = (PurpleGroup *) node;
@@ -1331,7 +1332,7 @@
     so we use the blist-node-extended-menu signal to trigger this
     handler */
 static void blist_node_menu_cb(PurpleBlistNode *node,
-                               GList **menu, struct mwPurplePluginData *pd) {
+                               GList **menu, struct mwPurpleProtocolData *pd) {
   const char *owner;
   PurpleAccount *acct;
   PurpleMenuAction *act;
@@ -1405,7 +1406,7 @@
 
 
 /** Last thing to happen from a started session */
-static void services_starting(struct mwPurplePluginData *pd) {
+static void services_starting(struct mwPurpleProtocolData *pd) {
 
   PurpleConnection *gc;
   PurpleAccount *acct;
@@ -1457,7 +1458,7 @@
 
 static void session_loginRedirect(struct mwSession *session,
 				  const char *host) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleAccount *account;
   guint port;
@@ -1483,20 +1484,20 @@
 }
 
 
-static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status);
+static void mw_protocol_set_status(PurpleAccount *acct, PurpleStatus *status);
 
 
 /** called from mw_session_stateChange when the session's state is
     mwSession_STARTED. Any finalizing of start-up stuff should go
     here */
-static void session_started(struct mwPurplePluginData *pd) {
+static void session_started(struct mwPurpleProtocolData *pd) {
   PurpleStatus *status;
   PurpleAccount *acct;
 
   /* set out initial status */
   acct = purple_connection_get_account(pd->gc);
   status = purple_account_get_active_status(acct);
-  mw_prpl_set_status(acct, status);
+  mw_protocol_set_status(acct, status);
 
   /* start watching for new conversations */
   purple_signal_connect(purple_conversations_get_handle(),
@@ -1513,7 +1514,7 @@
 }
 
 
-static void session_stopping(struct mwPurplePluginData *pd) {
+static void session_stopping(struct mwPurpleProtocolData *pd) {
   /* stop watching the signals from session_started */
   purple_signals_disconnect_by_handle(pd);
 }
@@ -1522,7 +1523,7 @@
 static void mw_session_stateChange(struct mwSession *session,
 				   enum mwSessionState state,
 				   gpointer info) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   const char *msg = NULL;
 
@@ -1629,7 +1630,7 @@
 
 
 static void mw_session_setPrivacyInfo(struct mwSession *session) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleAccount *acct;
   struct mwPrivacyInfo *privacy;
@@ -1675,7 +1676,7 @@
 
 
 static void mw_session_setUserStatus(struct mwSession *session) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL };
   struct mwUserStatus *stat;
@@ -1743,7 +1744,7 @@
 /** callback triggered from purple_input_add, watches the socked for
     available data to be processed by the session */
 static void read_cb(gpointer data, gint source, PurpleInputCondition cond) {
-  struct mwPurplePluginData *pd = data;
+  struct mwPurpleProtocolData *pd = data;
   int ret = 0, err = 0;
 
   g_return_if_fail(pd != NULL);
@@ -1794,7 +1795,7 @@
     in, and if the session logging in receives a redirect message */
 static void connect_cb(gpointer data, gint source, const gchar *error_message) {
 
-  struct mwPurplePluginData *pd = data;
+  struct mwPurpleProtocolData *pd = data;
 
   if(source < 0) {
     /* connection failed */
@@ -1833,7 +1834,7 @@
 				struct mwLoginInfo *from,
 				gboolean may_reply,
 				const char *text) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleAccount *acct;
   PurpleIMConversation *im;
   PurpleBuddy *buddy;
@@ -1903,7 +1904,7 @@
 
   struct mwServiceConference *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
 
   char *c_inviter, *c_name, *c_topic, *c_invitation;
@@ -1952,7 +1953,7 @@
 
 
 static struct mwConference *
-conf_find_by_id(struct mwPurplePluginData *pd, int id) {
+conf_find_by_id(struct mwPurpleProtocolData *pd, int id) {
 
   struct mwServiceConference *srvc = pd->srvc_conf;
   struct mwConference *conf = NULL;
@@ -1977,7 +1978,7 @@
 static void mw_conf_opened(struct mwConference *conf, GList *members) {
   struct mwServiceConference *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleChatConversation *g_conf;
 
@@ -2008,7 +2009,7 @@
 static void mw_conf_closed(struct mwConference *conf, guint32 reason) {
   struct mwServiceConference *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
 
   const char *n = mwConference_getName(conf);
@@ -2066,7 +2067,7 @@
 
   struct mwServiceConference *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   char *esc;
 
@@ -2167,7 +2168,7 @@
 
   struct mwServiceFileTransfer *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleAccount *acct;
   const char *who;
@@ -2412,7 +2413,7 @@
 static PurpleIMConversation *convo_get_im(struct mwConversation *conv) {
   struct mwServiceIm *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleAccount *acct;
 
@@ -2560,7 +2561,7 @@
 static void mw_conversation_opened(struct mwConversation *conv) {
   struct mwServiceIm *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleAccount *acct;
 
@@ -2635,7 +2636,7 @@
 
 
 static void im_recv_text(struct mwConversation *conv,
-			 struct mwPurplePluginData *pd,
+			 struct mwPurpleProtocolData *pd,
 			 const char *msg) {
 
   struct mwIdBlock *idb;
@@ -2656,7 +2657,7 @@
 
 
 static void im_recv_typing(struct mwConversation *conv,
-			   struct mwPurplePluginData *pd,
+			   struct mwPurpleProtocolData *pd,
 			   gboolean typing) {
 
   struct mwIdBlock *idb;
@@ -2668,7 +2669,7 @@
 
 
 static void im_recv_html(struct mwConversation *conv,
-			 struct mwPurplePluginData *pd,
+			 struct mwPurpleProtocolData *pd,
 			 const char *msg) {
   struct mwIdBlock *idb;
   char *t1, *t2;
@@ -2692,7 +2693,7 @@
 
 
 static void im_recv_subj(struct mwConversation *conv,
-			 struct mwPurplePluginData *pd,
+			 struct mwPurpleProtocolData *pd,
 			 const char *subj) {
 
   /** @todo somehow indicate receipt of a conversation subject. It
@@ -2721,7 +2722,7 @@
 
 
 static void im_recv_mime(struct mwConversation *conv,
-			 struct mwPurplePluginData *pd,
+			 struct mwPurpleProtocolData *pd,
 			 const char *data) {
 
   GHashTable *img_by_cid;
@@ -2860,7 +2861,7 @@
 				 gconstpointer msg) {
   struct mwServiceIm *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   srvc = mwConversation_getService(conv);
   session = mwService_getSession(MW_SERVICE(srvc));
@@ -2899,7 +2900,7 @@
 			    const char *title, const char *name) {
   struct mwServiceIm *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   struct mwIdBlock *idb;
   GHashTable *ht;
@@ -2960,7 +2961,7 @@
 
 
 static struct mwPlace *
-place_find_by_id(struct mwPurplePluginData *pd, int id) {
+place_find_by_id(struct mwPurpleProtocolData *pd, int id) {
   struct mwServicePlace *srvc = pd->srvc_place;
   struct mwPlace *place = NULL;
   GList *l;
@@ -2983,7 +2984,7 @@
 static void mw_place_opened(struct mwPlace *place) {
   struct mwServicePlace *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   PurpleChatConversation *gconf;
 
@@ -3019,7 +3020,7 @@
 static void mw_place_closed(struct mwPlace *place, guint32 code) {
   struct mwServicePlace *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
 
   const char *n = mwPlace_getName(place);
@@ -3089,7 +3090,7 @@
 			     const char *msg) {
   struct mwServicePlace *srvc;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
   char *esc;
 
@@ -3144,13 +3145,13 @@
 }
 
 
-/** allocate and associate a mwPurplePluginData with a PurpleConnection */
-static struct mwPurplePluginData *mwPurplePluginData_new(PurpleConnection *gc) {
-  struct mwPurplePluginData *pd;
+/** allocate and associate a mwPurpleProtocolData with a PurpleConnection */
+static struct mwPurpleProtocolData *mwPurpleProtocolData_new(PurpleConnection *gc) {
+  struct mwPurpleProtocolData *pd;
 
   g_return_val_if_fail(gc != NULL, NULL);
 
-  pd = g_new0(struct mwPurplePluginData, 1);
+  pd = g_new0(struct mwPurpleProtocolData, 1);
   pd->gc = gc;
   pd->session = mwSession_new(&mw_session_handler);
   pd->srvc_aware = mw_srvc_aware_new(pd->session);
@@ -3181,7 +3182,7 @@
 }
 
 
-static void mwPurplePluginData_free(struct mwPurplePluginData *pd) {
+static void mwPurpleProtocolData_free(struct mwPurpleProtocolData *pd) {
   g_return_if_fail(pd != NULL);
 
   purple_connection_set_protocol_data(pd->gc, NULL);
@@ -3214,7 +3215,7 @@
 }
 
 
-static const char *mw_prpl_list_icon(PurpleAccount *a, PurpleBuddy *b) {
+static const char *mw_protocol_list_icon(PurpleAccount *a, PurpleBuddy *b) {
   /* my little green dude is a chopped up version of the aim running
      guy.  First, cut off the head and store someplace safe. Then,
      take the left-half side of the body and throw it away. Make a
@@ -3230,7 +3231,7 @@
 }
 
 
-static const char* mw_prpl_list_emblem(PurpleBuddy *b)
+static const char* mw_protocol_list_emblem(PurpleBuddy *b)
 {
   if(buddy_is_external(b))
     return "external";
@@ -3239,9 +3240,9 @@
 }
 
 
-static char *mw_prpl_status_text(PurpleBuddy *b) {
+static char *mw_protocol_status_text(PurpleBuddy *b) {
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwAwareIdBlock t = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL };
   const char *ret = NULL;
 
@@ -3299,9 +3300,9 @@
 }
 
 
-static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {
+static void mw_protocol_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd = NULL;
+  struct mwPurpleProtocolData *pd = NULL;
   struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL };
 
   const char *message = NULL;
@@ -3334,7 +3335,7 @@
   }
 }
 
-static GList *mw_prpl_status_types(PurpleAccount *acct)
+static GList *mw_protocol_status_types(PurpleAccount *acct)
 {
 	GList *types = NULL;
 	PurpleStatusType *type;
@@ -3375,7 +3376,7 @@
 				    PurpleRequestFields *fields) {
   PurpleAccount *acct;
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwServiceConference *srvc;
 
   PurpleRequestField *f;
@@ -3540,7 +3541,7 @@
   PurpleBuddy *buddy = (PurpleBuddy *) node;
   PurpleAccount *acct;
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   GList *l;
 
   g_return_if_fail(node != NULL);
@@ -3577,7 +3578,7 @@
   PurpleBuddy *buddy = (PurpleBuddy *) node;
   PurpleAccount *acct;
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwSession *session;
   char *rcpt_name;
   GList *rcpt;
@@ -3608,7 +3609,7 @@
 #endif
 
 
-static GList *mw_prpl_blist_node_menu(PurpleBlistNode *node) {
+static GList *mw_protocol_blist_node_menu(PurpleBlistNode *node) {
   GList *l = NULL;
   PurpleMenuAction *act;
 
@@ -3636,7 +3637,7 @@
 }
 
 
-static GList *mw_prpl_chat_info(PurpleConnection *gc) {
+static GList *mw_protocol_chat_info(PurpleConnection *gc) {
   GList *l = NULL;
   struct proto_chat_entry *pce;
 
@@ -3649,7 +3650,7 @@
 }
 
 
-static GHashTable *mw_prpl_chat_info_defaults(PurpleConnection *gc,
+static GHashTable *mw_protocol_chat_info_defaults(PurpleConnection *gc,
 					      const char *name) {
   GHashTable *table;
 
@@ -3665,18 +3666,18 @@
 }
 
 
-static void mw_prpl_login(PurpleAccount *acct);
-
-
-static void mw_prpl_login(PurpleAccount *account) {
+static void mw_protocol_login(PurpleAccount *acct);
+
+
+static void mw_protocol_login(PurpleAccount *account) {
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   char *user, *pass, *host;
   guint port;
 
   gc = purple_account_get_connection(account);
-  pd = mwPurplePluginData_new(gc);
+  pd = mwPurpleProtocolData_new(gc);
 
   /* while we do support images, the default is to not offer it */
   purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_IMAGES);
@@ -3750,8 +3751,8 @@
 }
 
 
-static void mw_prpl_close(PurpleConnection *gc) {
-  struct mwPurplePluginData *pd;
+static void mw_protocol_close(PurpleConnection *gc) {
+  struct mwPurpleProtocolData *pd;
 
   g_return_if_fail(gc != NULL);
 
@@ -3778,7 +3779,7 @@
   }
 
   /* clean up the rest */
-  mwPurplePluginData_free(pd);
+  mwPurpleProtocolData_free(pd);
 }
 
 
@@ -3950,12 +3951,12 @@
 }
 
 
-static int mw_prpl_send_im(PurpleConnection *gc,
+static int mw_protocol_send_im(PurpleConnection *gc,
 			   const char *name,
 			   const char *message,
 			   PurpleMessageFlags flags) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwIdBlock who = { (char *) name, NULL };
   struct mwConversation *conv;
 
@@ -4024,11 +4025,11 @@
 }
 
 
-static unsigned int mw_prpl_send_typing(PurpleConnection *gc,
+static unsigned int mw_protocol_send_typing(PurpleConnection *gc,
 					const char *name,
 					PurpleIMTypingState state) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwIdBlock who = { (char *) name, NULL };
   struct mwConversation *conv;
 
@@ -4117,11 +4118,11 @@
 }
 
 
-static void mw_prpl_get_info(PurpleConnection *gc, const char *who) {
+static void mw_protocol_get_info(PurpleConnection *gc, const char *who) {
 
   struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleAccount *acct;
   PurpleBuddy *b;
   PurpleNotifyUserInfo *user_info;
@@ -4190,7 +4191,7 @@
 }
 
 
-static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status) {
+static void mw_protocol_set_status(PurpleAccount *acct, PurpleStatus *status) {
   PurpleConnection *gc;
   const char *state;
   char *message = NULL;
@@ -4243,7 +4244,7 @@
 }
 
 
-static void mw_prpl_set_idle(PurpleConnection *gc, int t) {
+static void mw_protocol_set_idle(PurpleConnection *gc, int t) {
   struct mwSession *session;
   struct mwUserStatus stat;
 
@@ -4369,7 +4370,7 @@
   BuddyAddData *data = b;
   PurpleBuddy *buddy = NULL;
   PurpleConnection *gc;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
 
   g_return_if_fail(data != NULL);
 
@@ -4453,12 +4454,12 @@
 }
 
 
-static void mw_prpl_add_buddy(PurpleConnection *gc,
+static void mw_protocol_add_buddy(PurpleConnection *gc,
 			      PurpleBuddy *buddy,
 			      PurpleGroup *group,
 			      const char *message) {
 
-  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
+  struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
   struct mwServiceResolve *srvc;
   GList *query;
   enum mwResolveFlag flags;
@@ -4492,7 +4493,7 @@
 
 
 static void foreach_add_buddies(PurpleGroup *group, GList *buddies,
-				struct mwPurplePluginData *pd) {
+				struct mwPurpleProtocolData *pd) {
   struct mwAwareList *list;
 
   list = list_ensure(pd, group);
@@ -4501,12 +4502,12 @@
 }
 
 
-static void mw_prpl_add_buddies(PurpleConnection *gc,
+static void mw_protocol_add_buddies(PurpleConnection *gc,
 				GList *buddies,
 				GList *groups,
 				const char *message) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   GHashTable *group_sets;
   struct mwAwareIdBlock *idbs, *idb;
 
@@ -4552,10 +4553,10 @@
 }
 
 
-static void mw_prpl_remove_buddy(PurpleConnection *gc,
+static void mw_protocol_remove_buddy(PurpleConnection *gc,
 				 PurpleBuddy *buddy, PurpleGroup *group) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL };
   struct mwAwareList *list;
 
@@ -4592,9 +4593,9 @@
 }
 
 
-static void mw_prpl_set_permit_deny(PurpleConnection *gc) {
+static void mw_protocol_set_permit_deny(PurpleConnection *gc) {
   PurpleAccount *acct;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwSession *session;
 
   struct mwPrivacyInfo privacy = {
@@ -4647,23 +4648,23 @@
 }
 
 
-static void mw_prpl_add_permit(PurpleConnection *gc, const char *name) {
-  mw_prpl_set_permit_deny(gc);
-}
-
-
-static void mw_prpl_add_deny(PurpleConnection *gc, const char *name) {
-  mw_prpl_set_permit_deny(gc);
-}
-
-
-static void mw_prpl_rem_permit(PurpleConnection *gc, const char *name) {
-  mw_prpl_set_permit_deny(gc);
-}
-
-
-static void mw_prpl_rem_deny(PurpleConnection *gc, const char *name) {
-  mw_prpl_set_permit_deny(gc);
+static void mw_protocol_add_permit(PurpleConnection *gc, const char *name) {
+  mw_protocol_set_permit_deny(gc);
+}
+
+
+static void mw_protocol_add_deny(PurpleConnection *gc, const char *name) {
+  mw_protocol_set_permit_deny(gc);
+}
+
+
+static void mw_protocol_rem_permit(PurpleConnection *gc, const char *name) {
+  mw_protocol_set_permit_deny(gc);
+}
+
+
+static void mw_protocol_rem_deny(PurpleConnection *gc, const char *name) {
+  mw_protocol_set_permit_deny(gc);
 }
 
 
@@ -4686,10 +4687,10 @@
 }
 
 
-static void mw_prpl_join_chat(PurpleConnection *gc,
+static void mw_protocol_join_chat(PurpleConnection *gc,
 			      GHashTable *components) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   char *c, *t;
 
   pd = purple_connection_get_protocol_data(gc);
@@ -4727,10 +4728,10 @@
 }
 
 
-static void mw_prpl_reject_chat(PurpleConnection *gc,
+static void mw_protocol_reject_chat(PurpleConnection *gc,
 				GHashTable *components) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwServiceConference *srvc;
   char *c;
 
@@ -4751,17 +4752,17 @@
 }
 
 
-static char *mw_prpl_get_chat_name(GHashTable *components) {
+static char *mw_protocol_get_chat_name(GHashTable *components) {
   return g_hash_table_lookup(components, CHAT_KEY_NAME);
 }
 
 
-static void mw_prpl_chat_invite(PurpleConnection *gc,
+static void mw_protocol_chat_invite(PurpleConnection *gc,
 				int id,
 				const char *invitation,
 				const char *who) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwConference *conf;
   struct mwPlace *place;
   struct mwIdBlock idb = { (char *) who, NULL };
@@ -4784,10 +4785,10 @@
 }
 
 
-static void mw_prpl_chat_leave(PurpleConnection *gc,
+static void mw_protocol_chat_leave(PurpleConnection *gc,
 			       int id) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwConference *conf;
 
   pd = purple_connection_get_protocol_data(gc);
@@ -4807,21 +4808,21 @@
 }
 
 
-static void mw_prpl_chat_whisper(PurpleConnection *gc,
+static void mw_protocol_chat_whisper(PurpleConnection *gc,
 				 int id,
 				 const char *who,
 				 const char *message) {
 
-  mw_prpl_send_im(gc, who, message, 0);
-}
-
-
-static int mw_prpl_chat_send(PurpleConnection *gc,
+  mw_protocol_send_im(gc, who, message, 0);
+}
+
+
+static int mw_protocol_chat_send(PurpleConnection *gc,
 			     int id,
 			     const char *message,
 			     PurpleMessageFlags flags) {
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwConference *conf;
   char *msg;
   int ret;
@@ -4848,7 +4849,7 @@
 }
 
 
-static void mw_prpl_keepalive(PurpleConnection *gc) {
+static void mw_protocol_keepalive(PurpleConnection *gc) {
   struct mwSession *session;
 
   g_return_if_fail(gc != NULL);
@@ -4860,11 +4861,11 @@
 }
 
 
-static void mw_prpl_alias_buddy(PurpleConnection *gc,
+static void mw_protocol_alias_buddy(PurpleConnection *gc,
 				const char *who,
 				const char *alias) {
 
-  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
+  struct mwPurpleProtocolData *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
@@ -4874,7 +4875,7 @@
 }
 
 
-static void mw_prpl_group_buddy(PurpleConnection *gc,
+static void mw_protocol_group_buddy(PurpleConnection *gc,
 				const char *who,
 				const char *old_group,
 				const char *new_group) {
@@ -4882,7 +4883,7 @@
   struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
   GList *gl = g_list_prepend(NULL, &idb);
 
-  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
+  struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
   PurpleGroup *group;
   struct mwAwareList *list;
 
@@ -4903,12 +4904,12 @@
 }
 
 
-static void mw_prpl_rename_group(PurpleConnection *gc,
+static void mw_protocol_rename_group(PurpleConnection *gc,
 				 const char *old,
 				 PurpleGroup *group,
 				 GList *buddies) {
 
-  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
+  struct mwPurpleProtocolData *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
@@ -4921,14 +4922,14 @@
 }
 
 
-static void mw_prpl_buddy_free(PurpleBuddy *buddy) {
+static void mw_protocol_buddy_free(PurpleBuddy *buddy) {
   /* I don't think we have any cleanup for buddies yet */
   ;
 }
 
 
-static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) {
-  struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc);
+static void mw_protocol_convo_closed(PurpleConnection *gc, const char *who) {
+  struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
   struct mwServiceIm *srvc;
   struct mwConversation *conv;
   struct mwIdBlock idb = { (char *) who, NULL };
@@ -4946,7 +4947,7 @@
 }
 
 
-static const char *mw_prpl_normalize(const PurpleAccount *account,
+static const char *mw_protocol_normalize(const PurpleAccount *account,
 				     const char *id) {
 
   /* code elsewhere assumes that the return value points to different
@@ -4959,8 +4960,8 @@
 }
 
 
-static void mw_prpl_remove_group(PurpleConnection *gc, PurpleGroup *group) {
-  struct mwPurplePluginData *pd;
+static void mw_protocol_remove_group(PurpleConnection *gc, PurpleGroup *group) {
+  struct mwPurpleProtocolData *pd;
   struct mwAwareList *list;
 
   pd = purple_connection_get_protocol_data(gc);
@@ -4979,9 +4980,9 @@
 }
 
 
-static gboolean mw_prpl_can_receive_file(PurpleConnection *gc,
+static gboolean mw_protocol_can_receive_file(PurpleConnection *gc,
 					 const char *who) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwServiceAware *srvc;
   PurpleAccount *acct;
 
@@ -5005,7 +5006,7 @@
   PurpleAccount *acct;
   PurpleConnection *gc;
 
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwServiceFileTransfer *srvc;
   struct mwFileTransfer *ft;
 
@@ -5068,7 +5069,7 @@
 }
 
 
-static PurpleXfer *mw_prpl_new_xfer(PurpleConnection *gc, const char *who) {
+static PurpleXfer *mw_protocol_new_xfer(PurpleConnection *gc, const char *who) {
   PurpleAccount *acct;
   PurpleXfer *xfer;
 
@@ -5084,10 +5085,10 @@
   return xfer;
 }
 
-static void mw_prpl_send_file(PurpleConnection *gc,
+static void mw_protocol_send_file(PurpleConnection *gc,
 			      const char *who, const char *file) {
 
-  PurpleXfer *xfer = mw_prpl_new_xfer(gc, who);
+  PurpleXfer *xfer = mw_protocol_new_xfer(gc, who);
 
   if(file) {
     DEBUG_INFO("file != NULL\n");
@@ -5099,81 +5100,6 @@
   }
 }
 
-
-static PurplePluginProtocolInfo mw_prpl_info = {
-  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
-};
-
 #if 0
 static PurplePluginPrefFrame *
 mw_plugin_get_plugin_pref_frame(PurplePlugin *plugin) {
@@ -5186,7 +5112,7 @@
   purple_plugin_pref_frame_add(frame, pref);
 
 
-  pref = purple_plugin_pref_new_with_name(MW_PRPL_OPT_BLIST_ACTION);
+  pref = purple_plugin_pref_new_with_name(MW_PROTOCOL_OPT_BLIST_ACTION);
   purple_plugin_pref_set_label(pref, _("Buddy List Storage Mode"));
 
   purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE);
@@ -5233,12 +5159,12 @@
 
 
 /** prompts for a file to import blist from */
-static void st_import_action(PurplePluginAction *act) {
+static void st_import_action(PurpleProtocolAction *act) {
   PurpleConnection *gc;
   PurpleAccount *account;
   char *title;
 
-  gc = act->context;
+  gc = act->connection;
   account = purple_connection_get_account(gc);
   title = g_strdup_printf(_("Import Sametime List for Account %s"),
 			  purple_account_get_username(account));
@@ -5273,12 +5199,12 @@
 
 
 /** prompts for a file to export blist to */
-static void st_export_action(PurplePluginAction *act) {
+static void st_export_action(PurpleProtocolAction *act) {
   PurpleConnection *gc;
   PurpleAccount *account;
   char *title;
 
-  gc = act->context;
+  gc = act->connection;
   account = purple_connection_get_account(gc);
   title = g_strdup_printf(_("Export Sametime List for Account %s"),
 			  purple_account_get_username(account));
@@ -5314,7 +5240,7 @@
 }
 
 
-static void remote_group_done(struct mwPurplePluginData *pd,
+static void remote_group_done(struct mwPurpleProtocolData *pd,
 			      const char *id, const char *name) {
   PurpleConnection *gc;
   PurpleAccount *acct;
@@ -5359,7 +5285,7 @@
 }
 
 
-static void remote_group_multi_cb(struct mwPurplePluginData *pd,
+static void remote_group_multi_cb(struct mwPurpleProtocolData *pd,
 				  PurpleRequestFields *fields) {
   PurpleRequestField *f;
   GList *l;
@@ -5380,7 +5306,7 @@
 
 
 static void remote_group_multi(struct mwResolveResult *result,
-			       struct mwPurplePluginData *pd) {
+			       struct mwPurpleProtocolData *pd) {
 
   PurpleRequestFields *fields;
   PurpleRequestFieldGroup *g;
@@ -5436,7 +5362,7 @@
 
   struct mwResolveResult *res = NULL;
   struct mwSession *session;
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   PurpleConnection *gc;
 
   session = mwService_getSession(MW_SERVICE(srvc));
@@ -5476,7 +5402,7 @@
 
 
 static void remote_group_action_cb(PurpleConnection *gc, const char *name) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwServiceResolve *srvc;
   GList *query;
   enum mwResolveFlag flags;
@@ -5498,12 +5424,12 @@
 }
 
 
-static void remote_group_action(PurplePluginAction *act) {
+static void remote_group_action(PurpleProtocolAction *act) {
   PurpleConnection *gc;
   const char *msgA;
   const char *msgB;
 
-  gc = act->context;
+  gc = act->connection;
 
   msgA = _("Notes Address Book Group");
   msgB = _("Enter the name of a Notes Address Book group in the field below"
@@ -5601,7 +5527,7 @@
 
 
 static void search_action_cb(PurpleConnection *gc, const char *name) {
-  struct mwPurplePluginData *pd;
+  struct mwPurpleProtocolData *pd;
   struct mwServiceResolve *srvc;
   GList *query;
   enum mwResolveFlag flags;
@@ -5623,12 +5549,12 @@
 }
 
 
-static void search_action(PurplePluginAction *act) {
+static void search_action(PurpleProtocolAction *act) {
   PurpleConnection *gc;
   const char *msgA;
   const char *msgB;
 
-  gc = act->context;
+  gc = act->connection;
 
   msgA = _("Search for a user");
   msgB = _("Enter a name or partial ID in the field below to search"
@@ -5643,23 +5569,23 @@
 }
 
 
-static GList *mw_plugin_actions(PurplePlugin *plugin, gpointer context) {
-  PurplePluginAction *act;
+static GList *mw_protocol_get_actions(PurpleConnection *gc) {
+  PurpleProtocolAction *act;
   GList *l = NULL;
 
-  act = purple_plugin_action_new(_("Import Sametime List..."),
+  act = purple_protocol_action_new(_("Import Sametime List..."),
 			       st_import_action);
   l = g_list_append(l, act);
 
-  act = purple_plugin_action_new(_("Export Sametime List..."),
+  act = purple_protocol_action_new(_("Export Sametime List..."),
 			       st_export_action);
   l = g_list_append(l, act);
 
-  act = purple_plugin_action_new(_("Add Notes Address Book Group..."),
+  act = purple_protocol_action_new(_("Add Notes Address Book Group..."),
 			       remote_group_action);
   l = g_list_append(l, act);
 
-  act = purple_plugin_action_new(_("User Search..."),
+  act = purple_protocol_action_new(_("User Search..."),
 			       search_action);
   l = g_list_append(l, act);
 
@@ -5667,57 +5593,6 @@
 }
 
 
-static gboolean mw_plugin_load(PurplePlugin *plugin) {
-  return TRUE;
-}
-
-
-static gboolean mw_plugin_unload(PurplePlugin *plugin) {
-  return TRUE;
-}
-
-
-static void mw_plugin_destroy(PurplePlugin *plugin) {
-  g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]);
-  g_log_remove_handler("meanwhile", log_handler[1]);
-}
-
-static PurplePluginInfo mw_plugin_info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                           /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                          /**< priority       */
-
-	PLUGIN_ID,                                        /**< id             */
-	PLUGIN_NAME,                                      /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	PLUGIN_SUMMARY,                                   /**< summary        */
-	PLUGIN_DESC,                                      /**<  description    */
-	PLUGIN_AUTHOR,                                    /**< author         */
-	PLUGIN_HOMEPAGE,                                  /**< homepage       */
-
-	mw_plugin_load,                                   /**< load           */
-	mw_plugin_unload,                                 /**< unload         */
-	mw_plugin_destroy,                                /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&mw_prpl_info,                                    /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
-	mw_plugin_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-
 static void mw_log_handler(const gchar *domain, GLogLevelFlags flags,
 			   const gchar *msg, gpointer data) {
 
@@ -5736,7 +5611,105 @@
 }
 
 
-static void mw_plugin_init(PurplePlugin *plugin) {
+static PurpleProtocol mw_protocol = {
+  PLUGIN_ID,
+  PLUGIN_NAME,
+  sizeof(PurpleProtocol),
+  OPT_PROTO_IM_IMAGE,
+  NULL, /*< set in mw_plugin_init */
+  NULL, /*< set in mw_plugin_init */
+  NO_BUDDY_ICONS,
+  mw_protocol_get_actions,
+  mw_protocol_list_icon,
+  mw_protocol_list_emblem,
+  mw_protocol_status_text,
+  mw_protocol_tooltip_text,
+  mw_protocol_status_types,
+  mw_protocol_blist_node_menu,
+  mw_protocol_chat_info,
+  mw_protocol_chat_info_defaults,
+  mw_protocol_login,
+  mw_protocol_close,
+  mw_protocol_send_im,
+  NULL,
+  mw_protocol_send_typing,
+  mw_protocol_get_info,
+  mw_protocol_set_status,
+  mw_protocol_set_idle,
+  NULL,
+  mw_protocol_add_buddy,
+  mw_protocol_add_buddies,
+  mw_protocol_remove_buddy,
+  NULL,
+  mw_protocol_add_permit,
+  mw_protocol_add_deny,
+  mw_protocol_rem_permit,
+  mw_protocol_rem_deny,
+  mw_protocol_set_permit_deny,
+  mw_protocol_join_chat,
+  mw_protocol_reject_chat,
+  mw_protocol_get_chat_name,
+  mw_protocol_chat_invite,
+  mw_protocol_chat_leave,
+  mw_protocol_chat_whisper,
+  mw_protocol_chat_send,
+  mw_protocol_keepalive,
+  NULL,
+  NULL,
+  mw_protocol_alias_buddy,
+  mw_protocol_group_buddy,
+  mw_protocol_rename_group,
+  mw_protocol_buddy_free,
+  mw_protocol_convo_closed,
+  mw_protocol_normalize,
+  NULL,
+  mw_protocol_remove_group,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  mw_protocol_can_receive_file,
+  mw_protocol_send_file,
+  mw_protocol_new_xfer,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL
+};
+
+
+static PurplePluginInfo *
+plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           PLUGIN_ID,
+		"name",         PLUGIN_NAME,
+		"version",      DISPLAY_VERSION,
+		"category",     PLUGIN_CATEGORY,
+		"summary",      PLUGIN_SUMMARY,
+		"description",  PLUGIN_DESC,
+		"author",       PLUGIN_AUTHOR,
+		"website",      PLUGIN_HOMEPAGE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
+
+static gboolean plugin_load(PurplePlugin *plugin, GError **error) {
   PurpleAccountUserSplit *split;
   PurpleAccountOption *opt;
   GList *l = NULL;
@@ -5745,17 +5718,17 @@
     G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION;
 
   /* set up the preferences */
-  purple_prefs_add_none(MW_PRPL_OPT_BASE);
-  purple_prefs_add_int(MW_PRPL_OPT_BLIST_ACTION, BLIST_CHOICE_DEFAULT);
+  purple_prefs_add_none(MW_PROTOCOL_OPT_BASE);
+  purple_prefs_add_int(MW_PROTOCOL_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);
+  mw_protocol.user_splits = g_list_append(mw_protocol.user_splits, split);
 
   /* remove dead preferences */
-  purple_prefs_remove(MW_PRPL_OPT_PSYCHIC);
-  purple_prefs_remove(MW_PRPL_OPT_SAVE_DYNAMIC);
+  purple_prefs_remove(MW_PROTOCOL_OPT_PSYCHIC);
+  purple_prefs_remove(MW_PROTOCOL_OPT_SAVE_DYNAMIC);
 
   /* port to connect to */
   opt = purple_account_option_int_new(_("Port"), MW_KEY_PORT,
@@ -5768,8 +5741,8 @@
     gboolean b = FALSE;
     const char *label = _("Force login (ignore server redirects)");
 
-    if(purple_prefs_exists(MW_PRPL_OPT_FORCE_LOGIN))
-      b = purple_prefs_get_bool(MW_PRPL_OPT_FORCE_LOGIN);
+    if(purple_prefs_exists(MW_PROTOCOL_OPT_FORCE_LOGIN))
+      b = purple_prefs_get_bool(MW_PROTOCOL_OPT_FORCE_LOGIN);
 
     opt = purple_account_option_bool_new(label, MW_KEY_FORCE, b);
     l = g_list_append(l, opt);
@@ -5780,7 +5753,7 @@
 				     MW_KEY_FAKE_IT, FALSE);
   l = g_list_append(l, opt);
 
-  mw_prpl_info.protocol_options = l;
+  mw_protocol.protocol_options = l;
   l = NULL;
 
   /* forward all our g_log messages to purple. Generally all the logging
@@ -5792,9 +5765,21 @@
   /* redirect meanwhile's logging to purple's */
   log_handler[1] = g_log_set_handler("meanwhile", logflags,
 				     mw_log_handler, NULL);
-}
-
-
-PURPLE_INIT_PLUGIN(sametime, mw_plugin_init, mw_plugin_info);
+
+  purple_protocols_add(&mw_protocol);
+  return TRUE;
+}
+
+
+static gboolean plugin_unload(PurplePlugin *plugin, GError **error) {
+  g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]);
+  g_log_remove_handler("meanwhile", log_handler[1]);
+
+  purple_protocols_remove(&mw_protocol);
+  return TRUE;
+}
+
+
+PURPLE_PLUGIN_INIT(sametime, plugin_query, plugin_load, plugin_unload);
 /* The End. */
 
--- a/libpurple/protocols/silc/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/silc/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -43,4 +43,5 @@
 	-I$(top_builddir)/libpurple \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(SILC_CFLAGS)
--- a/libpurple/protocols/silc/buddy.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/silc/buddy.c	Sun Aug 18 01:53:00 2013 +0530
@@ -731,7 +731,7 @@
 			    _("You cannot receive buddy notifications until you "
 			      "import his/her public key.  You can use the Get Public Key "
 			      "command to get the public key."));
-	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+	purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
 }
 
 static void
@@ -774,7 +774,7 @@
 			   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
 			   silcpurple_silcdir(), fingerprint);
 		purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
-		purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+		purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
 		silc_free(fingerprint);
 		silc_free(r->offline_pk);
 		if (r->public_key)
@@ -1007,7 +1007,7 @@
 	purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
 
 	/* Update online status */
-	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
+	purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
 
 	/* Finally, start watching this user so we receive its status
 	   changes from the server */
--- a/libpurple/protocols/silc/ops.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/silc/ops.c	Sun Aug 18 01:53:00 2013 +0530
@@ -904,7 +904,7 @@
 				     client_entry->mode & SILC_UMODE_PAGE ||
 				     client_entry->mode & SILC_UMODE_DETACHED)) {
 					client_entry->mode = mode;
-					purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
+					purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
 				}
 				else if ((mode & SILC_UMODE_GONE) ||
 					 (mode & SILC_UMODE_INDISPOSED) ||
@@ -912,16 +912,16 @@
 					 (mode & SILC_UMODE_PAGE) ||
 					 (mode & SILC_UMODE_DETACHED)) {
 					client_entry->mode = mode;
-					purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+					purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
 				}
 			} else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
 				   notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF ||
 				   notify == SILC_NOTIFY_TYPE_KILLED) {
 				client_entry->mode = mode;
-				purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+				purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
 			} else if (notify == SILC_NOTIFY_TYPE_NONE) {
 				client_entry->mode = mode;
-				purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
+				purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
 			}
 		}
 		break;
--- a/libpurple/protocols/silc/silc.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/silc/silc.c	Sun Aug 18 01:53:00 2013 +0530
@@ -902,9 +902,9 @@
 }
 
 static void
-silcpurple_attrs(PurplePluginAction *action)
+silcpurple_attrs(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
@@ -1069,9 +1069,9 @@
 }
 
 static void
-silcpurple_detach(PurplePluginAction *action)
+silcpurple_detach(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	SilcPurple sg;
 
 	if (!gc)
@@ -1086,9 +1086,9 @@
 }
 
 static void
-silcpurple_view_motd(PurplePluginAction *action)
+silcpurple_view_motd(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	SilcPurple sg;
 	char *tmp;
 
@@ -1209,9 +1209,9 @@
 }
 
 static void
-silcpurple_create_keypair(PurplePluginAction *action)
+silcpurple_create_keypair(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	SilcPurple sg = purple_connection_get_protocol_data(gc);
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *g;
@@ -1280,9 +1280,9 @@
 }
 
 static void
-silcpurple_change_pass(PurplePluginAction *action)
+silcpurple_change_pass(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_account_request_change_password(purple_connection_get_account(gc));
 }
 
@@ -1297,9 +1297,9 @@
 }
 
 static void
-silcpurple_show_set_info(PurplePluginAction *action)
+silcpurple_show_set_info(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_account_request_change_user_info(purple_connection_get_account(gc));
 }
 
@@ -1309,32 +1309,32 @@
 }
 
 static GList *
-silcpurple_actions(PurplePlugin *plugin, gpointer context)
+silcpurple_get_actions(PurpleConnection *gc)
 {
 	GList *list = NULL;
-	PurplePluginAction *act;
+	PurpleProtocolAction *act;
 
-	act = purple_plugin_action_new(_("Online Status"),
+	act = purple_protocol_action_new(_("Online Status"),
 			silcpurple_attrs);
 	list = g_list_append(list, act);
 
-	act = purple_plugin_action_new(_("Detach From Server"),
+	act = purple_protocol_action_new(_("Detach From Server"),
 			silcpurple_detach);
 	list = g_list_append(list, act);
 
-	act = purple_plugin_action_new(_("View Message of the Day"),
+	act = purple_protocol_action_new(_("View Message of the Day"),
 			silcpurple_view_motd);
 	list = g_list_append(list, act);
 
-	act = purple_plugin_action_new(_("Create SILC Key Pair..."),
+	act = purple_protocol_action_new(_("Create SILC Key Pair..."),
 			silcpurple_create_keypair);
 	list = g_list_append(list, act);
 
-	act = purple_plugin_action_new(_("Change Password..."),
+	act = purple_protocol_action_new(_("Change Password..."),
 			silcpurple_change_pass);
 	list = g_list_append(list, act);
 
-	act = purple_plugin_action_new(_("Set User Info..."),
+	act = purple_protocol_action_new(_("Set User Info..."),
 			silcpurple_show_set_info);
 	list = g_list_append(list, act);
 
@@ -1914,120 +1914,120 @@
 static void
 silcpurple_register_commands(void)
 {
-	purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("part", "w", PURPLE_CMD_P_PROTOCOL,
 			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+			PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 			"prpl-silc", silcpurple_cmd_chat_part, _("part [channel]:  Leave the chat"), NULL);
-	purple_cmd_register("leave", "w", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("leave", "w", PURPLE_CMD_P_PROTOCOL,
 			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+			PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 			"prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]:  Leave the chat"), NULL);
-	purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("topic", "s", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
 			silcpurple_cmd_chat_topic, _("topic [&lt;new topic&gt;]:  View or change the topic"), NULL);
-	purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("join", "ws", PURPLE_CMD_P_PROTOCOL,
 			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+			PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 			"prpl-silc", silcpurple_cmd_chat_join,
 			_("join &lt;channel&gt; [&lt;password&gt;]:  Join a chat on this network"), NULL);
-	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
 			silcpurple_cmd_chat_list, _("list:  List channels on this network"), NULL);
-	purple_cmd_register("whois", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("whois", "w", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc",
 			silcpurple_cmd_whois, _("whois &lt;nick&gt;:  View nick's information"), NULL);
-	purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_msg,
 			_("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user"), NULL);
-	purple_cmd_register("query", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("query", "ws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query,
 			_("query &lt;nick&gt; [&lt;message&gt;]:  Send a private message to a user"), NULL);
-	purple_cmd_register("motd", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("motd", "", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd,
 			_("motd:  View the server's Message Of The Day"), NULL);
-	purple_cmd_register("detach", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("detach", "", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_detach,
 			_("detach:  Detach this session"), NULL);
-	purple_cmd_register("quit", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("quit", "s", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit,
 			_("quit [message]:  Disconnect from the server, with an optional message"), NULL);
-	purple_cmd_register("call", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("call", "s", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_call,
 			_("call &lt;command&gt;:  Call any silc client command"), NULL);
 	/* These below just get passed through for the silc client library to deal
 	 * with */
-	purple_cmd_register("kill", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("kill", "ws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("kill &lt;nick&gt; [-pubkey|&lt;reason&gt;]:  Kill nick"), NULL);
-	purple_cmd_register("nick", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("nick", "w", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_generic,
 			_("nick &lt;newnick&gt;:  Change your nickname"), NULL);
-	purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("whowas &lt;nick&gt;:  View nick's information"), NULL);
-	purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode,
 			_("cmode &lt;channel&gt; [+|-&lt;modes&gt;] [arguments]:  Change or display channel modes"), NULL);
-	purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("cumode &lt;channel&gt; +|-&lt;modes&gt; &lt;nick&gt;:  Change nick's modes on channel"), NULL);
-	purple_cmd_register("umode", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("umode", "w", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_generic,
 			_("umode &lt;usermodes&gt;:  Set your modes in the network"), NULL);
-	purple_cmd_register("oper", "s", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("oper", "s", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_generic,
 			_("oper &lt;nick&gt; [-pubkey]:  Get server operator privileges"), NULL);
-	purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("invite", "ws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("invite &lt;channel&gt; [-|+]&lt;nick&gt;:  invite nick or add/remove from channel invite list"), NULL);
-	purple_cmd_register("kick", "wws", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("kick", "wws", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("kick &lt;channel&gt; &lt;nick&gt; [comment]:  Kick client from channel"), NULL);
-	purple_cmd_register("info", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("info", "w", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("info [server]:  View server administrative details"), NULL);
-	purple_cmd_register("ban", "ww", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("ban", "ww", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
 			_("ban [&lt;channel&gt; +|-&lt;nick&gt;]:  Ban client from channel"), NULL);
-	purple_cmd_register("getkey", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("getkey", "w", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_generic,
 			_("getkey &lt;nick|server&gt;:  Retrieve client's or server's public key"), NULL);
-	purple_cmd_register("stats", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("stats", "", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_generic,
 			_("stats:  View server and network statistics"), NULL);
-	purple_cmd_register("ping", "", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("ping", "", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_generic,
 			_("ping:  Send PING to the connected server"), NULL);
 #if 0 /* Purple doesn't handle these yet */
-	purple_cmd_register("users", "w", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("users", "w", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			"prpl-silc", silcpurple_cmd_users,
 			_("users &lt;channel&gt;:  List users in channel"));
-	purple_cmd_register("names", "ww", PURPLE_CMD_P_PRPL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+	purple_cmd_register("names", "ww", PURPLE_CMD_P_PROTOCOL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
 			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_names,
 			_("names [-count|-ops|-halfops|-voices|-normal] &lt;channel(s)&gt;:  List specific users in channel(s)"));
 #endif
@@ -2051,15 +2051,18 @@
 	NULL
 };
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-silc",			/* id */
+	"SILC",					/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
 	OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE |
 	OPT_PROTO_SLASH_COMMANDS_NATIVE,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
 	{"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+	silcpurple_get_actions,                 /* get_actions */
 	silcpurple_list_icon,	                /* list_icon */
 	NULL,					/* list_emblems */
 	silcpurple_status_text,			/* status_text */
@@ -2114,7 +2117,7 @@
 	silcpurple_ftp_send_file,		/* send_file */
 	silcpurple_ftp_new_xfer,		/* new_xfer */
 	NULL,					/* offline_message */
-	&silcpurple_wb_ops,			/* whiteboard_prpl_ops */
+	&silcpurple_wb_ops,			/* whiteboard_protocol_ops */
 	NULL,					/* send_raw */
 	NULL,				        /* roomlist_room_serialize */
 	NULL,				        /* unregister_user */
@@ -2128,42 +2131,24 @@
 	NULL				        /* get_public_alias */
 };
 
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,			/**< type           */
-	NULL,					/**< ui_requirement */
-	0,					/**< flags          */
-	NULL,					/**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,		/**< priority       */
-
-	"prpl-silc",				/**< id             */
-	"SILC",					/**< name           */
-	"1.1",					/**< version        */
-	/**  summary        */
-	N_("SILC Protocol Plugin"),
-	/**  description    */
-	N_("Secure Internet Live Conferencing (SILC) Protocol"),
-	"Pekka Riikonen",			/**< author         */
-	"http://silcnet.org/",			/**< homepage       */
-
-	NULL,					/**< load           */
-	NULL,					/**< unload         */
-	NULL,					/**< destroy        */
-
-	NULL,					/**< ui_info        */
-	&prpl_info,				/**< extra_info     */
-	NULL,					/**< prefs_info     */
-	silcpurple_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
+	return purple_plugin_info_new(
+		"id",           "prpl-silc",
+		"name",         "SILC",
+		"version",      "1.1",
+		"category",     N_("Protocol"),
+		"summary",      N_("SILC Protocol Plugin"),
+		"description",  N_("Secure Internet Live Conferencing (SILC) Protocol"),
+		"author",       "Pekka Riikonen",
+		"website",      "http://silcnet.org/",
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
 #if 0
 static SilcBool silcpurple_debug_cb(char *file, char *function, int line,
@@ -2174,8 +2159,8 @@
 }
 #endif
 
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 	PurpleAccountUserSplit *split;
@@ -2187,23 +2172,23 @@
 	silc_plugin = plugin;
 
 	split = purple_account_user_split_new(_("Network"), "silcnet.org", '@');
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 	/* Account options */
 	option = purple_account_option_string_new(_("Connect server"),
 						  "server",
 						  "silc.silcnet.org");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_int_new(_("Port"), "port", 706);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
 	option = purple_account_option_string_new(_("Public Key file"),
 						  "public-key", tmp);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
 	option = purple_account_option_string_new(_("Private Key file"),
 						  "private-key", tmp);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	for (i = 0; silc_default_ciphers[i].name; i++) {
 		kvp = g_new0(PurpleKeyValuePair, 1);
@@ -2212,7 +2197,7 @@
 		list = g_list_append(list, kvp);
 	}
 	option = purple_account_option_list_new(_("Cipher"), "cipher", list);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	list = NULL;
 	for (i = 0; silc_default_hmacs[i].name; i++) {
@@ -2222,27 +2207,27 @@
 		list = g_list_append(list, kvp);
 	}
 	option = purple_account_option_list_new(_("HMAC"), "hmac", list);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Use Perfect Forward Secrecy"),
 						"pfs", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Public key authentication"),
 						"pubkey-auth", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_bool_new(_("Block IMs without Key Exchange"),
 						"block-ims", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_bool_new(_("Block messages to whiteboard"),
 						"block-wb", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_bool_new(_("Automatically open whiteboard"),
 						"open-wb", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_bool_new(_("Digitally sign and verify all messages"),
 						"sign-verify", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	purple_prefs_remove("/plugins/prpl/silc");
 
@@ -2256,6 +2241,15 @@
 silc_log_set_debug_callbacks(silcpurple_debug_cb, NULL, NULL, NULL);
 #endif
 
+	purple_protocols_add(&protocol);
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(silc, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(&protocol);
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(silc, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/silc/silcpurple.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/silc/silcpurple.h	Sun Aug 18 01:53:00 2013 +0530
@@ -29,7 +29,7 @@
 #include "debug.h"
 #include "ft.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "roomlist.h"
 #include "server.h"
--- a/libpurple/protocols/simple/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/simple/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -33,4 +33,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/simple/simple.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/simple/simple.c	Sun Aug 18 01:53:00 2013 +0530
@@ -32,8 +32,8 @@
 #include "dnsquery.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
-#include "plugin.h"
+#include "protocol.h"
+#include "plugins.h"
 #include "util.h"
 #include "version.h"
 #include "network.h"
@@ -820,7 +820,7 @@
 
 	/* we can not subscribe -> user is offline (TODO unknown status?) */
 
-	purple_prpl_got_user_status(sip->account, to, "offline", NULL);
+	purple_protocol_got_user_status(sip->account, to, "offline", NULL);
 	g_free(to);
 	return TRUE;
 }
@@ -1239,7 +1239,7 @@
 						b->dialog = NULL;
 					}
 
-					purple_prpl_got_user_status(sip->account, from, "offline", NULL);
+					purple_protocol_got_user_status(sip->account, from, "offline", NULL);
 					break;
 				}
 				i++;
@@ -1276,9 +1276,9 @@
 
 
 	if(isonline)
-		purple_prpl_got_user_status(sip->account, from, "available", NULL);
+		purple_protocol_got_user_status(sip->account, from, "available", NULL);
 	else
-		purple_prpl_got_user_status(sip->account, from, "offline", NULL);
+		purple_protocol_got_user_status(sip->account, from, "offline", NULL);
 
 	xmlnode_free(pidf);
 	g_free(from);
@@ -2046,13 +2046,16 @@
 	purple_connection_set_protocol_data(gc, NULL);
 }
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-simple",			/* id */
+	"SIMPLE",				/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	0,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
 	NO_BUDDY_ICONS,			/* icon_spec */
+	NULL,					/* get_actions */
 	simple_list_icon,		/* list_icon */
 	NULL,					/* list_emblems */
 	NULL,					/* status_text */
@@ -2107,7 +2110,7 @@
 	NULL,					/* send_file */
 	NULL,					/* new_xfer */
 	NULL,					/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
+	NULL,					/* whiteboard_protocol_ops */
 	simple_send_raw,		/* send_raw */
 	NULL,					/* roomlist_room_serialize */
 	NULL,					/* unregister_user */
@@ -2121,66 +2124,58 @@
 	NULL					/* get_public_alias */
 };
 
-
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
+	return purple_plugin_info_new(
+		"id",			"prpl-simple",
+		"name",			"SIMPLE",
+		"version",		DISPLAY_VERSION,
+		"category",		N_("Protocol"),
+		"summary",		N_("SIP/SIMPLE Protocol Plugin"),
+		"description",	N_("The SIP/SIMPLE Protocol Plugin"),
+		"author",		"Thomas Butter <butter@uni-mannheim.de>",
+		"website",		PURPLE_WEBSITE,
+		"abi-version",	PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-	"prpl-simple",                                    /**< id             */
-	"SIMPLE",                                         /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	N_("SIP/SIMPLE Protocol Plugin"),                 /**  summary        */
-	N_("The SIP/SIMPLE Protocol Plugin"),             /**  description    */
-	"Thomas Butter <butter@uni-mannheim.de>",         /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	NULL,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void _init_plugin(PurplePlugin *plugin)
+static gboolean plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountUserSplit *split;
 	PurpleAccountOption *option;
 
 	split = purple_account_user_split_new(_("Server"), "", '@');
-	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+	protocol.user_splits = g_list_append(protocol.user_splits, split);
 
 	option = purple_account_option_bool_new(_("Publish status (note: everyone may watch you)"), "dopublish", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_int_new(_("Connect port"), "port", 0);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Use UDP"), "udp", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_bool_new(_("Use proxy"), "useproxy", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_string_new(_("Proxy"), "proxy", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_string_new(_("Auth User"), "authuser", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 	option = purple_account_option_string_new(_("Auth Domain"), "authdomain", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
+
+	purple_protocols_add(&protocol);
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(simple, _init_plugin, info);
+static gboolean plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(&protocol);
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(simple, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/simple/simple.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/simple/simple.h	Sun Aug 18 01:53:00 2013 +0530
@@ -32,7 +32,7 @@
 #include "dnssrv.h"
 #include "network.h"
 #include "proxy.h"
-#include "prpl.h"
+#include "protocol.h"
 
 #include "sipmsg.h"
 
--- a/libpurple/protocols/simple/sipmsg.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/simple/sipmsg.c	Sun Aug 18 01:53:00 2013 +0530
@@ -27,8 +27,8 @@
 #include "conversation.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
-#include "plugin.h"
+#include "protocol.h"
+#include "plugins.h"
 #include "util.h"
 #include "version.h"
 
--- a/libpurple/protocols/yahoo/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -57,4 +57,5 @@
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/yahoo/libyahoo.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/libyahoo.c	Sun Aug 18 01:53:00 2013 +0530
@@ -25,6 +25,7 @@
 
 #include <account.h>
 #include <core.h>
+#include <plugins.h>
 
 #include "libymsg.h"
 #include "yahoochat.h"
@@ -33,26 +34,26 @@
 #include "yahoo_filexfer.h"
 #include "yahoo_picture.h"
 
-static PurplePlugin *my_protocol = NULL;
+static PurpleProtocol *my_protocol = NULL;
 
 static void yahoo_register_commands(void)
 {
-	purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("join", "s", PURPLE_CMD_P_PROTOCOL,
 	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
+	                  PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoo", yahoopurple_cmd_chat_join,
 	                  _("join &lt;room&gt;:  Join a chat room on the Yahoo network"), NULL);
-	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL,
 	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
+	                  PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoo", yahoopurple_cmd_chat_list,
 	                  _("list: List rooms on the Yahoo network"), NULL);
-	purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("buzz", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoo", yahoopurple_cmd_buzz,
 	                  _("buzz: Buzz a user to get their attention"), NULL);
-	purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("doodle", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoo", yahoo_doodle_purple_cmd_start,
 	                 _("doodle: Request user to start a Doodle session"), NULL);
 }
@@ -100,7 +101,7 @@
 	if (g_ascii_strcasecmp(proto, "ymsgr"))
 		return FALSE;
 
-	acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
+	acct = find_acct(my_protocol->id, acct_id);
 
 	if (!acct)
 		return FALSE;
@@ -167,14 +168,7 @@
 	return table;
 }
 
-static gboolean yahoo_unload_plugin(PurplePlugin *plugin)
-{
-	yahoo_dest_colorht();
-
-	return TRUE;
-}
-
-static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
+static PurpleWhiteboardPrplOps yahoo_whiteboard_protocol_ops =
 {
 	yahoo_doodle_start,
 	yahoo_doodle_end,
@@ -192,13 +186,16 @@
 	NULL
 };
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-yahoo",
+	"Yahoo",
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE,
 	NULL, /* user_splits */
 	NULL, /* protocol_options */
 	{"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
+	yahoo_get_actions,
 	yahoo_list_icon,
 	yahoo_list_emblem,
 	yahoo_status_text,
@@ -253,7 +250,7 @@
 	yahoo_send_file,
 	yahoo_new_xfer,
 	yahoo_offline_message, /* offline_message */
-	&yahoo_whiteboard_prpl_ops,
+	&yahoo_whiteboard_protocol_ops,
 	NULL, /* send_raw */
 	NULL, /* roomlist_room_serialize */
 	NULL, /* unregister_user */
@@ -267,74 +264,71 @@
 	NULL   /* get_public_alias */
 };
 
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-	"prpl-yahoo",                                     /**< id             */
-	"Yahoo",	                                      /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Yahoo! Protocol Plugin"),
-	                                                  /**  description    */
-	N_("Yahoo! Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-	NULL,                                             /**< load           */
-	yahoo_unload_plugin,                              /**< unload         */
-	NULL,                                             /**< destroy        */
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	yahoo_actions,
+	return purple_plugin_info_new(
+		"id",           "prpl-yahoo",
+		"name",         "Yahoo",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Yahoo! Protocol Plugin"),
+		"description",  N_("Yahoo! Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 
 	option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 #if 0
 	option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 #endif
 
-	my_protocol = plugin;
+	my_protocol = &protocol;
 	yahoo_register_commands();
 	yahoo_init_colorht();
 
-	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+	purple_signal_connect(purple_get_core(), "uri-handler", my_protocol,
 		PURPLE_CALLBACK(yahoo_uri_handler), NULL);
+
+	purple_protocols_add(my_protocol);
+
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(yahoo, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	yahoo_dest_colorht();
+	purple_protocols_remove(my_protocol);
+
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(yahoo, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/yahoo/libyahoojp.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/libyahoojp.c	Sun Aug 18 01:53:00 2013 +0530
@@ -24,6 +24,7 @@
 #include "internal.h"
 
 #include <account.h>
+#include <plugins.h>
 
 #include "libymsg.h"
 #include "yahoochat.h"
@@ -34,22 +35,22 @@
 
 static void yahoojp_register_commands(void)
 {
-	purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("join", "s", PURPLE_CMD_P_PROTOCOL,
 	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
+	                  PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoojp", yahoopurple_cmd_chat_join,
 	                  _("join &lt;room&gt;:  Join a chat room on the Yahoo network"), NULL);
-	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
+	purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL,
 	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-	                  PURPLE_CMD_FLAG_PRPL_ONLY,
+	                  PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoojp", yahoopurple_cmd_chat_list,
 	                  _("list: List rooms on the Yahoo network"), NULL);
-	purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("buzz", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoojp", yahoopurple_cmd_buzz,
 	                  _("buzz: Buzz a user to get their attention"), NULL);
-	purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
-	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("doodle", "", PURPLE_CMD_P_PROTOCOL,
+	                  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 	                  "prpl-yahoojp", yahoo_doodle_purple_cmd_start,
 	                 _("doodle: Request user to start a Doodle session"), NULL);
 }
@@ -63,14 +64,7 @@
 	return table;
 }
 
-static gboolean yahoojp_unload_plugin(PurplePlugin *plugin)
-{
-	yahoo_dest_colorht();
-
-	return TRUE;
-}
-
-static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
+static PurpleWhiteboardPrplOps yahoo_whiteboard_protocol_ops =
 {
 	yahoo_doodle_start,
 	yahoo_doodle_end,
@@ -88,13 +82,16 @@
 	NULL
 };
 
-static PurplePluginProtocolInfo prpl_info =
+static PurpleProtocol protocol =
 {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+	"prpl-yahoojp",
+	"Yahoo JAPAN",
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE,
 	NULL, /* user_splits */
 	NULL, /* protocol_options */
 	{"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
+	yahoo_get_actions,
 	yahoo_list_icon,
 	yahoo_list_emblem,
 	yahoo_status_text,
@@ -149,7 +146,7 @@
 	yahoo_send_file,
 	yahoo_new_xfer,
 	yahoo_offline_message, /* offline_message */
-	&yahoo_whiteboard_prpl_ops,
+	&yahoo_whiteboard_protocol_ops,
 	NULL, /* send_raw */
 	NULL, /* roomlist_room_serialize */
 	NULL, /* unregister_user */
@@ -165,71 +162,67 @@
 	NULL  /* get_public_alias */
 };
 
-static PurplePluginInfo info =
+static PurplePluginInfo *
+plugin_query(GError **error)
 {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-	"prpl-yahoojp",                                     /**< id             */
-	"Yahoo JAPAN",	                                      /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Yahoo! JAPAN Protocol Plugin"),
-	                                                  /**  description    */
-	N_("Yahoo! JAPAN Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-	NULL,                                             /**< load           */
-	yahoojp_unload_plugin,                              /**< unload         */
-	NULL,                                             /**< destroy        */
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	yahoo_actions,
+	return purple_plugin_info_new(
+		"id",           "prpl-yahoojp",
+		"name",         "Yahoo JAPAN",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Yahoo! JAPAN Protocol Plugin"),
+		"description",  N_("Yahoo! JAPAN Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
 
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
+static gboolean
+plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 
 	option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOOJP_XFER_HOST);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 #if 0
 	option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 #endif
 
 	yahoojp_register_commands();
 	yahoo_init_colorht();
+
+	purple_protocols_add(&protocol);
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(yahoojp, init_plugin, info);
+static gboolean
+plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	yahoo_dest_colorht();
+	purple_protocols_remove(&protocol);
 
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(yahoojp, plugin_query, plugin_load, plugin_unload);
+
--- a/libpurple/protocols/yahoo/libymsg.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/libymsg.c	Sun Aug 18 01:53:00 2013 +0530
@@ -33,7 +33,7 @@
 #include "http.h"
 #include "network.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "proxy.h"
 #include "request.h"
 #include "server.h"
@@ -133,21 +133,21 @@
 
 	if (status) {
 		if (f->status == YAHOO_STATUS_CUSTOM)
-			purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, "message",
+			purple_protocol_got_user_status(purple_connection_get_account(gc), name, status, "message",
 			                          yahoo_friend_get_status_message(f), NULL);
 		else
-			purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, NULL);
+			purple_protocol_got_user_status(purple_connection_get_account(gc), name, status, NULL);
 	}
 
 	if (f->idle != 0)
-		purple_prpl_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle);
+		purple_protocol_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle);
 	else
-		purple_prpl_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0);
+		purple_protocol_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0);
 
 	if (f->sms)
-		purple_prpl_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL);
+		purple_protocol_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL);
 	else
-		purple_prpl_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE);
+		purple_protocol_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE);
 }
 
 static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt)
@@ -302,8 +302,8 @@
 				if (f)
 					f->status = YAHOO_STATUS_OFFLINE;
 				if (name) {
-					purple_prpl_got_user_status(account, name, "offline", NULL);
-					purple_prpl_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE);
+					purple_protocol_got_user_status(account, name, "offline", NULL);
+					purple_protocol_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE);
 				}
 				break;
 			}
@@ -1134,7 +1134,7 @@
 			char *username;
 
 			username = g_markup_escape_text(im->fed_from, -1);
-			purple_prpl_got_attention(gc, username, YAHOO_BUZZ);
+			purple_protocol_got_attention(gc, username, YAHOO_BUZZ);
 			g_free(username);
 			g_free(m);
 			g_free(im->fed_from);
@@ -1295,7 +1295,7 @@
 	g_free(notify_msg);
 
 	g_hash_table_remove(yd->friends, who);
-	purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */
+	purple_protocol_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */
 	/* TODO: Shouldn't we remove the buddy from our local list? */
 }
 
@@ -4134,12 +4134,12 @@
 }
 
 
-static void yahoo_show_inbox(PurplePluginAction *action)
+static void yahoo_show_inbox(PurpleProtocolAction *action)
 {
 	/* Setup a cookie that can be used by the browser */
 	/* XXX I have no idea how this will work with Yahoo! Japan. */
 
-	PurpleConnection *gc = action->context;
+	PurpleConnection *gc = action->connection;
 	YahooData *yd = purple_connection_get_protocol_data(gc);
 	PurpleHttpRequest *req;
 	PurpleHttpCookieJar *cookiejar;
@@ -4160,18 +4160,18 @@
 #if 0
 /* XXX: it doesn't seems to work */
 static void
-yahoo_set_userinfo_fn(PurplePluginAction *action)
+yahoo_set_userinfo_fn(PurpleProtocolAction *action)
 {
-	yahoo_set_userinfo(action->context);
+	yahoo_set_userinfo(action->connection);
 }
 #endif
 
-static void yahoo_show_act_id(PurplePluginAction *action)
+static void yahoo_show_act_id(PurpleProtocolAction *action)
 {
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *group;
 	PurpleRequestField *field;
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = (PurpleConnection *) action->connection;
 	YahooData *yd = purple_connection_get_protocol_data(gc);
 	const char *name = purple_connection_get_display_name(gc);
 	int iter;
@@ -4196,9 +4196,9 @@
 					   gc);
 }
 
-static void yahoo_show_chat_goto(PurplePluginAction *action)
+static void yahoo_show_chat_goto(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	purple_request_input(gc, NULL, _("Join whom in chat?"), NULL,
 					   "", FALSE, FALSE, NULL,
 					   _("OK"), G_CALLBACK(yahoo_chat_goto),
@@ -4207,27 +4207,27 @@
 					   gc);
 }
 
-GList *yahoo_actions(PurplePlugin *plugin, gpointer context) {
+GList *yahoo_get_actions(PurpleConnection *gc) {
 	GList *m = NULL;
-	PurplePluginAction *act;
+	PurpleProtocolAction *act;
 
 #if 0
 	/* XXX: it doesn't seems to work */
-	act = purple_plugin_action_new(_("Set User Info..."),
+	act = purple_protocol_action_new(_("Set User Info..."),
 			yahoo_set_userinfo_fn);
 	m = g_list_append(m, act);
 #endif
 
-	act = purple_plugin_action_new(_("Activate ID..."),
+	act = purple_protocol_action_new(_("Activate ID..."),
 			yahoo_show_act_id);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Join User in Chat..."),
+	act = purple_protocol_action_new(_("Join User in Chat..."),
 			yahoo_show_chat_goto);
 	m = g_list_append(m, act);
 
 	m = g_list_append(m, NULL);
-	act = purple_plugin_action_new(_("Open Inbox"),
+	act = purple_protocol_action_new(_("Open Inbox"),
 			yahoo_show_inbox);
 	m = g_list_append(m, act);
 
@@ -5054,7 +5054,7 @@
 	if (*args && args[0])
 		return PURPLE_CMD_RET_FAILED;
 
-	purple_prpl_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), YAHOO_BUZZ);
+	purple_protocol_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), YAHOO_BUZZ);
 
 	return PURPLE_CMD_RET_OK;
 }
--- a/libpurple/protocols/yahoo/libymsg.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/libymsg.h	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "circularbuffer.h"
 #include "cmds.h"
 #include "http.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "network.h"
 
 #define YAHOO_PAGER_HOST_REQ_URL "http://vcs1.msg.yahoo.com/capacity"
@@ -382,7 +382,7 @@
 gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type);
 GList *yahoo_attention_types(PurpleAccount *account);
 
-GList *yahoo_actions(PurplePlugin *plugin, gpointer context);
+GList *yahoo_get_actions(PurpleConnection *gc);
 void yahoopurple_register_commands(void);
 
 PurpleCmdRet yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data);
--- a/libpurple/protocols/yahoo/util.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/util.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 
 #include "debug.h"
 #include "internal.h"
-#include "prpl.h"
+#include "protocol.h"
 
 #include "libymsg.h"
 
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/yahoo_doodle.c	Sun Aug 18 01:53:00 2013 +0530
@@ -33,7 +33,7 @@
 #include "cmds.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "proxy.h"
 #include "request.h"
 #include "server.h"
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Sun Aug 18 01:53:00 2013 +0530
@@ -25,7 +25,7 @@
 #include "internal.h"
 #include "dnsquery.h"
 
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 #include "debug.h"
 #include "http.h"
--- a/libpurple/protocols/yahoo/yahoo_friend.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/yahoo_friend.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
  */
 
 #include "internal.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 #include "debug.h"
 
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/yahoo_picture.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "buddylist.h"
 #include "debug.h"
 #include "http.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "proxy.h"
 #include "util.h"
 
--- a/libpurple/protocols/yahoo/yahoochat.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/yahoochat.c	Sun Aug 18 01:53:00 2013 +0530
@@ -34,7 +34,7 @@
 
 #include "debug.h"
 #include "http.h"
-#include "prpl.h"
+#include "protocol.h"
 
 #include "conversation.h"
 #include "notify.h"
--- a/libpurple/protocols/yahoo/ycht.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/yahoo/ycht.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
  */
 
 #include "internal.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "notify.h"
 #include "account.h"
 #include "proxy.h"
--- a/libpurple/protocols/zephyr/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/zephyr/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -105,5 +105,6 @@
 	-I$(top_srcdir)/libpurple/protocols \
 	-DCONFDIR=\"$(sysconfdir)\" \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(KRB4_CFLAGS) \
 	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/zephyr/zephyr.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/protocols/zephyr/zephyr.c	Sun Aug 18 01:53:00 2013 +0530
@@ -31,7 +31,8 @@
 #include "accountopt.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "server.h"
 #include "util.h"
 #include "cmds.h"
@@ -814,9 +815,9 @@
 				purple_notify_user_info_destroy(user_info);
 			} else {
 				if (nlocs>0)
-					purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL);
+					purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL);
 				else
-					purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL);
+					purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL);
 			}
 
 			g_free(user);
@@ -1199,9 +1200,9 @@
 					purple_notify_user_info_destroy(user_info);
 				} else {
 					if (nlocs>0)
-						purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL);
+						purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL);
 					else
-						purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL);
+						purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL);
 				}
 			}
 			else if (!g_ascii_strncasecmp(spewtype,"subscribed",10)) {
@@ -1325,9 +1326,9 @@
 				for(i=0;i<numlocs;i++) {
 					ZGetLocations(&locations,&one);
 					if (nlocs>0)
-						purple_prpl_got_user_status(account,name,"available",NULL);
+						purple_protocol_got_user_status(account,name,"available",NULL);
 					else
-						purple_prpl_got_user_status(account,name,"offline",NULL);
+						purple_protocol_got_user_status(account,name,"offline",NULL);
 				}
 			}
 #else
@@ -2712,67 +2713,67 @@
 static void zephyr_register_slash_commands(void)
 {
 
-	purple_cmd_register("msg","ws", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("msg","ws", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_msg, _("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user"), NULL);
 
-	purple_cmd_register("zlocate","w", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zlocate","w", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zlocate, _("zlocate &lt;nick&gt;: Locate user"), NULL);
 
-	purple_cmd_register("zl","w", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zl","w", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zlocate, _("zl &lt;nick&gt;: Locate user"), NULL);
 
-	purple_cmd_register("instance","s", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("instance","s", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_instance, _("instance &lt;instance&gt;: Set the instance to be used on this class"), NULL);
 
-	purple_cmd_register("inst","s", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("inst","s", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_instance, _("inst &lt;instance&gt;: Set the instance to be used on this class"), NULL);
 
-	purple_cmd_register("topic","s", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("topic","s", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_instance, _("topic &lt;instance&gt;: Set the instance to be used on this class"), NULL);
 
-	purple_cmd_register("sub", "www", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("sub", "www", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_joinchat_cir,
 			  _("sub &lt;class&gt; &lt;instance&gt; &lt;recipient&gt;: Join a new chat"), NULL);
 
-	purple_cmd_register("zi","ws", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zi","ws", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zi, _("zi &lt;instance&gt;: Send a message to &lt;message,<i>instance</i>,*&gt;"), NULL);
 
-	purple_cmd_register("zci","wws",PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zci","wws",PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zci,
 			  _("zci &lt;class&gt; &lt;instance&gt;: Send a message to &lt;<i>class</i>,<i>instance</i>,*&gt;"), NULL);
 
-	purple_cmd_register("zcir","wwws",PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zcir","wwws",PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zcir,
 			  _("zcir &lt;class&gt; &lt;instance&gt; &lt;recipient&gt;: Send a message to &lt;<i>class</i>,<i>instance</i>,<i>recipient</i>&gt;"), NULL);
 
-	purple_cmd_register("zir","wws",PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zir","wws",PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zir,
 			  _("zir &lt;instance&gt; &lt;recipient&gt;: Send a message to &lt;MESSAGE,<i>instance</i>,<i>recipient</i>&gt;"), NULL);
 
-	purple_cmd_register("zc","ws", PURPLE_CMD_P_PRPL,
-			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+	purple_cmd_register("zc","ws", PURPLE_CMD_P_PROTOCOL,
+			  PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
 			  "prpl-zephyr",
 			  zephyr_purple_cmd_zc, _("zc &lt;class&gt;: Send a message to &lt;<i>class</i>,PERSONAL,*&gt;"), NULL);
 
@@ -2797,17 +2798,17 @@
 }
 
 
-static void zephyr_action_resubscribe(PurplePluginAction *action)
+static void zephyr_action_resubscribe(PurpleProtocolAction *action)
 {
 
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	zephyr_resubscribe(gc);
 }
 
 
-static void zephyr_action_get_subs_from_server(PurplePluginAction *action)
+static void zephyr_action_get_subs_from_server(PurpleProtocolAction *action)
 {
-	PurpleConnection *gc = (PurpleConnection *) action->context;
+	PurpleConnection *gc = action->connection;
 	zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
 	gchar *title;
 	int retval, nsubs, one,i;
@@ -2850,28 +2851,31 @@
 }
 
 
-static GList *zephyr_actions(PurplePlugin *plugin, gpointer context)
+static GList *zephyr_get_actions(PurpleConnection *gc)
 {
 	GList *list = NULL;
-	PurplePluginAction *act = NULL;
-
-	act = purple_plugin_action_new(_("Resubscribe"), zephyr_action_resubscribe);
+	PurpleProtocolAction *act = NULL;
+
+	act = purple_protocol_action_new(_("Resubscribe"), zephyr_action_resubscribe);
 	list = g_list_append(list, act);
 
-	act = purple_plugin_action_new(_("Retrieve subscriptions from server"), zephyr_action_get_subs_from_server);
+	act = purple_protocol_action_new(_("Retrieve subscriptions from server"), zephyr_action_get_subs_from_server);
 	list = g_list_append(list,act);
 
 	return list;
 }
 
-static PurplePlugin *my_protocol = NULL;
-
-static PurplePluginProtocolInfo prpl_info = {
-	sizeof(PurplePluginProtocolInfo),       /* struct_size */
+static PurpleProtocol *my_protocol = NULL;
+
+static PurpleProtocol protocol = {
+	"prpl-zephyr",			/* id */
+	"Zephyr",				/* name */
+	sizeof(PurpleProtocol),       /* struct_size */
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD,
 	NULL,					/* ??? user_splits */
 	NULL,					/* ??? protocol_options */
 	NO_BUDDY_ICONS,
+	zephyr_get_actions,
 	zephyr_list_icon,
 	NULL,					/* ??? list_emblems */
 	NULL,					/* ??? status_text */
@@ -2926,7 +2930,7 @@
 	NULL,					/* send_file */
 	NULL,					/* new_xfer */
 	NULL,					/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
+	NULL,					/* whiteboard_protocol_ops */
 	NULL,					/* send_raw */
 	NULL,					/* roomlist_room_serialize */
 
@@ -2941,76 +2945,66 @@
 	NULL					/* get_public_alias */
 };
 
-static PurplePluginInfo info = {
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,				  /**< type	      */
-	NULL,						  /**< ui_requirement */
-	0,							  /**< flags	      */
-	NULL,						  /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,				  /**< priority	      */
-
-	"prpl-zephyr",					   /**< id	       */
-	"Zephyr",						 /**< name	     */
-	DISPLAY_VERSION,					  /**< version	      */
-	/**  summary	    */
-	N_("Zephyr Protocol Plugin"),
-	/**  description    */
-	N_("Zephyr Protocol Plugin"),
-	NULL,						  /**< author	      */
-	PURPLE_WEBSITE,					  /**< homepage	      */
-
-	NULL,						  /**< load	      */
-	NULL,						  /**< unload	      */
-	NULL,						  /**< destroy	      */
-
-	NULL,						  /**< ui_info	      */
-	&prpl_info,					  /**< extra_info     */
-	NULL,
-	zephyr_actions,
-
-	/* padding */
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
-
-static void init_plugin(PurplePlugin * plugin)
+static PurplePluginInfo *plugin_query(GError **error)
+{
+	return purple_plugin_info_new(
+		"id",           "prpl-zephyr",
+		"name",         "Zephyr",
+		"version",      DISPLAY_VERSION,
+		"category",     N_("Protocol"),
+		"summary",      N_("Zephyr Protocol Plugin"),
+		"description",  N_("Zephyr Protocol Plugin"),
+		"website",      PURPLE_WEBSITE,
+		"abi-version",  PURPLE_ABI_VERSION,
+		"flags",        GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL |
+		                GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY,
+		NULL
+	);
+}
+
+static gboolean plugin_load(PurplePlugin *plugin, GError **error)
 {
 	PurpleAccountOption *option;
 	char *tmp = get_exposure_level();
 
 	option = purple_account_option_bool_new(_("Use tzc"), "use_tzc", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("tzc command"), "tzc_command", "/usr/bin/tzc -e %s");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Export to .anyone"), "write_anyone", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Export to .zephyr.subs"), "write_zsubs", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Import from .anyone"), "read_anyone", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Import from .zephyr.subs"), "read_zsubs", TRUE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Realm"), "realm", "");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Exposure"), "exposure_level", tmp?tmp: EXPOSE_REALMVIS);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
 
 	option = purple_account_option_string_new(_("Encoding"), "encoding", ZEPHYR_FALLBACK_CHARSET);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
-	my_protocol = plugin;
+	protocol.protocol_options = g_list_append(protocol.protocol_options, option);
+
+	my_protocol = &protocol;
 	zephyr_register_slash_commands();
+
+	purple_protocols_add(my_protocol);
+	return TRUE;
 }
 
-PURPLE_INIT_PLUGIN(zephyr, init_plugin, info);
+static gboolean plugin_unload(PurplePlugin *plugin, GError **error)
+{
+	purple_protocols_remove(my_protocol);
+	return TRUE;
+}
+
+PURPLE_PLUGIN_INIT(zephyr, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/prpl.c	Sun Aug 18 01:52:32 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,649 +0,0 @@
-/*
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-#include "internal.h"
-#include "conversation.h"
-#include "debug.h"
-#include "network.h"
-#include "notify.h"
-#include "prpl.h"
-#include "request.h"
-#include "util.h"
-
-/**************************************************************************/
-/** @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)
-{
-	PurpleAttentionType *attn = g_new0(PurpleAttentionType, 1);
-
-	purple_attention_type_set_name(attn, name);
-	purple_attention_type_set_incoming_desc(attn, inc_desc);
-	purple_attention_type_set_outgoing_desc(attn, out_desc);
-	purple_attention_type_set_unlocalized_name(attn, ulname);
-
-	return attn;
-}
-
-
-void
-purple_attention_type_set_name(PurpleAttentionType *type, const char *name)
-{
-	g_return_if_fail(type != NULL);
-
-	type->name = name;
-}
-
-void
-purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc)
-{
-	g_return_if_fail(type != NULL);
-
-	type->incoming_description = desc;
-}
-
-void
-purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc)
-{
-	g_return_if_fail(type != NULL);
-
-	type->outgoing_description = desc;
-}
-
-void
-purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name)
-{
-	g_return_if_fail(type != NULL);
-
-	type->icon_name = name;
-}
-
-void
-purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname)
-{
-	g_return_if_fail(type != NULL);
-
-	type->unlocalized_name = ulname;
-}
-
-const char *
-purple_attention_type_get_name(const PurpleAttentionType *type)
-{
-	g_return_val_if_fail(type != NULL, NULL);
-
-	return type->name;
-}
-
-const char *
-purple_attention_type_get_incoming_desc(const PurpleAttentionType *type)
-{
-	g_return_val_if_fail(type != NULL, NULL);
-
-	return type->incoming_description;
-}
-
-const char *
-purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type)
-{
-	g_return_val_if_fail(type != NULL, NULL);
-
-	return type->outgoing_description;
-}
-
-const char *
-purple_attention_type_get_icon_name(const PurpleAttentionType *type)
-{
-	g_return_val_if_fail(type != NULL, NULL);
-
-	if(type->icon_name == NULL || *(type->icon_name) == '\0')
-		return NULL;
-
-	return type->icon_name;
-}
-
-const char *
-purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type)
-{
-	g_return_val_if_fail(type != NULL, NULL);
-
-	return type->unlocalized_name;
-}
-
-/**************************************************************************/
-/** @name Protocol Plugin API  */
-/**************************************************************************/
-void
-purple_prpl_got_account_idle(PurpleAccount *account, gboolean idle,
-						   time_t idle_time)
-{
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(purple_account_is_connected(account));
-
-	purple_presence_set_idle(purple_account_get_presence(account),
-						   idle, idle_time);
-}
-
-void
-purple_prpl_got_account_login_time(PurpleAccount *account, time_t login_time)
-{
-	PurplePresence *presence;
-
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(purple_account_is_connected(account));
-
-	if (login_time == 0)
-		login_time = time(NULL);
-
-	presence = purple_account_get_presence(account);
-
-	purple_presence_set_login_time(presence, login_time);
-}
-
-void
-purple_prpl_got_account_status(PurpleAccount *account, const char *status_id, ...)
-{
-	PurplePresence *presence;
-	PurpleStatus *status;
-	va_list args;
-
-	g_return_if_fail(account   != NULL);
-	g_return_if_fail(status_id != NULL);
-	g_return_if_fail(purple_account_is_connected(account));
-
-	presence = purple_account_get_presence(account);
-	status   = purple_presence_get_status(presence, status_id);
-
-	g_return_if_fail(status != NULL);
-
-	va_start(args, status_id);
-	purple_status_set_active_with_attrs(status, TRUE, args);
-	va_end(args);
-}
-
-void
-purple_prpl_got_account_actions(PurpleAccount *account)
-{
-
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(purple_account_is_connected(account));
-
-	purple_signal_emit(purple_accounts_get_handle(), "account-actions-changed",
-	                   account);
-}
-
-void
-purple_prpl_got_user_idle(PurpleAccount *account, const char *name,
-		gboolean idle, time_t idle_time)
-{
-	PurplePresence *presence;
-	GSList *list;
-
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(name    != NULL);
-	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
-
-	if ((list = purple_blist_find_buddies(account, name)) == NULL)
-		return;
-
-	while (list) {
-		presence = purple_buddy_get_presence(list->data);
-		list = g_slist_delete_link(list, list);
-		purple_presence_set_idle(presence, idle, idle_time);
-	}
-}
-
-void
-purple_prpl_got_user_login_time(PurpleAccount *account, const char *name,
-		time_t login_time)
-{
-	GSList *list;
-	PurplePresence *presence;
-
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(name    != NULL);
-
-	if ((list = purple_blist_find_buddies(account, name)) == NULL)
-		return;
-
-	if (login_time == 0)
-		login_time = time(NULL);
-
-	while (list) {
-		PurpleBuddy *buddy = list->data;
-		presence = purple_buddy_get_presence(buddy);
-		list = g_slist_delete_link(list, list);
-
-		if (purple_presence_get_login_time(presence) != login_time)
-		{
-			purple_presence_set_login_time(presence, login_time);
-
-			purple_signal_emit(purple_blist_get_handle(), "buddy-got-login-time", buddy);
-		}
-	}
-}
-
-void
-purple_prpl_got_user_status(PurpleAccount *account, const char *name,
-		const char *status_id, ...)
-{
-	GSList *list, *l;
-	PurpleBuddy *buddy;
-	PurplePresence *presence;
-	PurpleStatus *status;
-	PurpleStatus *old_status;
-	va_list args;
-
-	g_return_if_fail(account   != NULL);
-	g_return_if_fail(name      != NULL);
-	g_return_if_fail(status_id != NULL);
-	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
-
-	if((list = purple_blist_find_buddies(account, name)) == NULL)
-		return;
-
-	for(l = list; l != NULL; l = l->next) {
-		buddy = l->data;
-
-		presence = purple_buddy_get_presence(buddy);
-		status   = purple_presence_get_status(presence, status_id);
-
-		if(NULL == status)
-			/*
-			 * TODO: This should never happen, right?  We should call
-			 *       g_warning() or something.
-			 */
-			continue;
-
-		old_status = purple_presence_get_active_status(presence);
-
-		va_start(args, status_id);
-		purple_status_set_active_with_attrs(status, TRUE, args);
-		va_end(args);
-
-		purple_buddy_update_status(buddy, old_status);
-	}
-
-	g_slist_free(list);
-
-	/* The buddy is no longer online, they are therefore by definition not
-	 * still typing to us. */
-	if (!purple_status_is_online(status)) {
-		serv_got_typing_stopped(purple_account_get_connection(account), name);
-		purple_prpl_got_media_caps(account, name);
-	}
-}
-
-void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *name,
-					const char *status_id)
-{
-	GSList *list, *l;
-	PurpleBuddy *buddy;
-	PurplePresence *presence;
-	PurpleStatus *status;
-
-	g_return_if_fail(account   != NULL);
-	g_return_if_fail(name      != NULL);
-	g_return_if_fail(status_id != NULL);
-	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
-
-	if((list = purple_blist_find_buddies(account, name)) == NULL)
-		return;
-
-	for(l = list; l != NULL; l = l->next) {
-		buddy = l->data;
-
-		presence = purple_buddy_get_presence(buddy);
-		status   = purple_presence_get_status(presence, status_id);
-
-		if(NULL == status)
-			continue;
-
-		if (purple_status_is_active(status)) {
-			purple_status_set_active(status, FALSE);
-			purple_buddy_update_status(buddy, status);
-		}
-	}
-
-	g_slist_free(list);
-}
-
-static void
-do_prpl_change_account_status(PurpleAccount *account,
-								PurpleStatus *old_status, PurpleStatus *new_status)
-{
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
-
-	if (purple_status_is_online(new_status) &&
-		purple_account_is_disconnected(account) &&
-		purple_network_is_available())
-	{
-		purple_account_connect(account);
-		return;
-	}
-
-	if (!purple_status_is_online(new_status))
-	{
-		if (!purple_account_is_disconnected(account))
-			purple_account_disconnect(account);
-		/* Clear out the unsaved password if we switch to offline status */
-		if (!purple_account_get_remember_password(account))
-			purple_account_set_password(account, NULL, NULL, NULL);
-
-		return;
-	}
-
-	if (purple_account_is_connecting(account))
-		/*
-		 * We don't need to call the set_status PRPL function because
-		 * the PRPL will take care of setting its status during the
-		 * connection process.
-		 */
-		return;
-
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-
-	if (prpl == NULL)
-		return;
-
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (!purple_account_is_disconnected(account) && prpl_info->set_status != NULL)
-	{
-		prpl_info->set_status(account, new_status);
-	}
-}
-
-void
-purple_prpl_change_account_status(PurpleAccount *account,
-								PurpleStatus *old_status, PurpleStatus *new_status)
-{
-	g_return_if_fail(account    != NULL);
-	g_return_if_fail(new_status != NULL);
-	g_return_if_fail(!purple_status_is_exclusive(new_status) || old_status != NULL);
-
-	do_prpl_change_account_status(account, old_status, new_status);
-
-	purple_signal_emit(purple_accounts_get_handle(), "account-status-changed",
-					account, old_status, new_status);
-}
-
-GList *
-purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence)
-{
-	GList *statuses = NULL;
-	GList *l;
-	PurpleStatus *status;
-
-	g_return_val_if_fail(account  != NULL, NULL);
-	g_return_val_if_fail(presence != NULL, NULL);
-
-	for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
-	{
-		status = purple_status_new((PurpleStatusType *)l->data, presence);
-		statuses = g_list_prepend(statuses, status);
-	}
-
-	statuses = g_list_reverse(statuses);
-
-	return statuses;
-}
-
-static void
-purple_prpl_attention(PurpleConversation *conv, const char *who,
-	guint type, PurpleMessageFlags flags, time_t mtime)
-{
-	PurpleAccount *account = purple_conversation_get_account(conv);
-	purple_signal_emit(purple_conversations_get_handle(),
-		flags == PURPLE_MESSAGE_SEND ? "sent-attention" : "got-attention",
-		account, who, conv, type);
-}
-
-void
-purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code)
-{
-	PurpleAttentionType *attn;
-	PurpleMessageFlags flags;
-	PurplePlugin *prpl;
-	PurpleIMConversation *im;
-	gboolean (*send_attention)(PurpleConnection *, const char *, guint);
-	PurpleBuddy *buddy;
-	const char *alias;
-	gchar *description;
-	time_t mtime;
-
-	g_return_if_fail(gc != NULL);
-	g_return_if_fail(who != NULL);
-
-	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(purple_connection_get_account(gc), type_code);
-
-	if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL)
-		alias = purple_buddy_get_contact_alias(buddy);
-	else
-		alias = who;
-
-	if (attn && purple_attention_type_get_outgoing_desc(attn)) {
-		description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias);
-	} else {
-		description = g_strdup_printf(_("Requesting %s's attention..."), alias);
-	}
-
-	flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM;
-
-	purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n",
-			description, who);
-
-	if (!send_attention(gc, who, type_code))
-		return;
-
-	im = purple_im_conversation_new(purple_connection_get_account(gc), who);
-	purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, description, flags, mtime);
-	purple_prpl_attention(PURPLE_CONVERSATION(im), who, type_code, PURPLE_MESSAGE_SEND, time(NULL));
-
-	g_free(description);
-}
-
-static void
-got_attention(PurpleConnection *gc, int id, const char *who, guint type_code)
-{
-	PurpleMessageFlags flags;
-	PurpleAttentionType *attn;
-	PurpleBuddy *buddy;
-	const char *alias;
-	gchar *description;
-	time_t mtime;
-
-	mtime = time(NULL);
-
-	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;
-
-	/* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display
-	 * it next to the attention command. And if it is null, display a generic icon. */
-
-	if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL)
-		alias = purple_buddy_get_contact_alias(buddy);
-	else
-		alias = who;
-
-	if (attn && purple_attention_type_get_incoming_desc(attn)) {
-		description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias);
-	} else {
-		description = g_strdup_printf(_("%s has requested your attention!"), alias);
-	}
-
-	purple_debug_info("server", "got_attention: got '%s' from %s\n",
-			description, who);
-
-	if (id == -1)
-		serv_got_im(gc, who, description, flags, mtime);
-	else
-		serv_got_chat_in(gc, id, who, flags, description, mtime);
-
-	/* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */
-
-	g_free(description);
-}
-
-void
-purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code)
-{
-	PurpleConversation *conv = NULL;
-	PurpleAccount *account = purple_connection_get_account(gc);
-
-	got_attention(gc, -1, who, type_code);
-	conv =
-		purple_conversations_find_with_account(who, account);
-	if (conv)
-		purple_prpl_attention(conv, who, type_code, PURPLE_MESSAGE_RECV,
-			time(NULL));
-}
-
-void
-purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code)
-{
-	got_attention(gc, id, who, type_code);
-}
-
-gboolean
-purple_prpl_initiate_media(PurpleAccount *account,
-			   const char *who,
-			   PurpleMediaSessionType type)
-{
-#ifdef USE_VV
-	PurpleConnection *gc = NULL;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
-
-	if (account)
-		gc = purple_account_get_connection(account);
-	if (gc)
-		prpl = purple_connection_get_prpl(gc);
-	if (prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, initiate_media)) {
-		/* should check that the protocol supports this media type here? */
-		return prpl_info->initiate_media(account, who, type);
-	} else
-#endif
-	return FALSE;
-}
-
-PurpleMediaCaps
-purple_prpl_get_media_caps(PurpleAccount *account, const char *who)
-{
-#ifdef USE_VV
-	PurpleConnection *gc = NULL;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
-
-	if (account)
-		gc = purple_account_get_connection(account);
-	if (gc)
-		prpl = purple_connection_get_prpl(gc);
-	if (prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info,
-			get_media_caps)) {
-		return prpl_info->get_media_caps(account, who);
-	}
-#endif
-	return PURPLE_MEDIA_CAPS_NONE;
-}
-
-void
-purple_prpl_got_media_caps(PurpleAccount *account, const char *name)
-{
-#ifdef USE_VV
-	GSList *list;
-
-	g_return_if_fail(account != NULL);
-	g_return_if_fail(name    != NULL);
-
-	if ((list = purple_blist_find_buddies(account, name)) == NULL)
-		return;
-
-	while (list) {
-		PurpleBuddy *buddy = list->data;
-		PurpleMediaCaps oldcaps = purple_buddy_get_media_caps(buddy);
-		PurpleMediaCaps newcaps = 0;
-		const gchar *bname = purple_buddy_get_name(buddy);
-		list = g_slist_delete_link(list, list);
-
-
-		newcaps = purple_prpl_get_media_caps(account, bname);
-		purple_buddy_set_media_caps(buddy, newcaps);
-
-		if (oldcaps == newcaps)
-			continue;
-
-		purple_signal_emit(purple_blist_get_handle(),
-				"buddy-caps-changed", buddy,
-				newcaps, oldcaps);
-	}
-#endif
-}
-
-/**************************************************************************
- * Protocol Plugin Subsystem API
- **************************************************************************/
-
-PurplePlugin *
-purple_find_prpl(const char *id)
-{
-	GList *l;
-	PurplePlugin *plugin;
-
-	g_return_val_if_fail(id != NULL, NULL);
-
-	for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) {
-		plugin = (PurplePlugin *)l->data;
-
-		if (purple_strequal(plugin->info->id, id))
-			return plugin;
-	}
-
-	return NULL;
-}
--- a/libpurple/prpl.h	Sun Aug 18 01:52:32 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,974 +0,0 @@
-/**
- * @file prpl.h Protocol Plugin functions
- * @ingroup core
- */
-
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-/* this file should be all that prpls need to include. therefore, by including
- * this file, they should get glib, proxy, purple_connection, prpl, etc. */
-
-#ifndef _PURPLE_PRPL_H_
-#define _PURPLE_PRPL_H_
-
-typedef struct _PurplePluginProtocolInfo PurplePluginProtocolInfo;
-
-/** Represents "nudges" and "buzzes" that you may send to a buddy to attract
- *  their attention (or vice-versa).
- */
-typedef struct _PurpleAttentionType PurpleAttentionType;
-
-/**************************************************************************/
-/** @name Basic Protocol Information                                      */
-/**************************************************************************/
-
-typedef enum {
-	PURPLE_ICON_SCALE_DISPLAY = 0x01,		/**< We scale the icon when we display it */
-	PURPLE_ICON_SCALE_SEND = 0x02			/**< We scale the icon before we send it to the server */
-} PurpleIconScaleRules;
-
-
-/**
- * A description of a Buddy Icon specification.  This tells Purple what kind of image file
- * it should give this prpl, and what kind of image file it should expect back.
- * Dimensions less than 1 should be ignored and the image not scaled.
- */
-typedef struct _PurpleBuddyIconSpec PurpleBuddyIconSpec;
-
-/**
- * A description of a file transfer thumbnail specification.
- * This tells the UI if and what image formats the prpl support for file
- * transfer thumbnails.
- */
-typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec;
-
-/**
- * This \#define exists just to make it easier to fill out the buddy icon
- * field in the prpl info struct for protocols that couldn't care less.
- */
-#define NO_BUDDY_ICONS {NULL, 0, 0, 0, 0, 0, 0}
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "buddylist.h"
-#include "conversations.h"
-#include "ft.h"
-#include "imgstore.h"
-#include "media.h"
-#include "notify.h"
-#include "proxy.h"
-#include "plugin.h"
-#include "roomlist.h"
-#include "status.h"
-#include "whiteboard.h"
-
-
-/** @copydoc PurpleBuddyIconSpec */
-struct _PurpleBuddyIconSpec {
-	/** This is a comma-delimited list of image formats or @c NULL if icons
-	 *  are not supported.  Neither the core nor the prpl will actually
-	 *  check to see if the data it's given matches this; it's entirely up
-	 *  to the UI to do what it wants
-	 */
-	char *format;
-
-	int min_width;                     /**< Minimum width of this icon  */
-	int min_height;                    /**< Minimum height of this icon */
-	int max_width;                     /**< Maximum width of this icon  */
-	int max_height;                    /**< Maximum height of this icon */
-	size_t max_filesize;               /**< Maximum size in bytes */
-	PurpleIconScaleRules scale_rules;  /**< How to stretch this icon */
-};
-
-/** Represents an entry containing information that must be supplied by the
- *  user when joining a chat.
- */
-struct proto_chat_entry {
-	const char *label;       /**< User-friendly name of the entry */
-	const char *identifier;  /**< Used by the PRPL to identify the option */
-	gboolean required;       /**< True if it's required */
-	gboolean is_int;         /**< True if the entry expects an integer */
-	int min;                 /**< Minimum value in case of integer */
-	int max;                 /**< Maximum value in case of integer */
-	gboolean secret;         /**< True if the entry is secret (password) */
-};
-
-/**
- * Protocol options
- *
- * These should all be stuff that some plugins can do and others can't.
- */
-typedef enum
-{
-	/**
-	 * User names are unique to a chat and are not shared between rooms.
-	 *
-	 * XMPP lets you choose what name you want in chats, so it shouldn't
-	 * be pulling the aliases from the buddy list for the chat list;
-	 * it gets annoying.
-	 */
-	OPT_PROTO_UNIQUE_CHATNAME = 0x00000004,
-
-	/**
-	 * Chat rooms have topics.
-	 *
-	 * IRC and XMPP support this.
-	 */
-	OPT_PROTO_CHAT_TOPIC = 0x00000008,
-
-	/**
-	 * Don't require passwords for sign-in.
-	 *
-	 * Zephyr doesn't require passwords, so there's no
-	 * need for a password prompt.
-	 */
-	OPT_PROTO_NO_PASSWORD = 0x00000010,
-
-	/**
-	 * Notify on new mail.
-	 *
-	 * MSN and Yahoo notify you when you have new mail.
-	 */
-	OPT_PROTO_MAIL_CHECK = 0x00000020,
-
-	/**
-	 * Images in IMs.
-	 *
-	 * Oscar lets you send images in direct IMs.
-	 */
-	OPT_PROTO_IM_IMAGE = 0x00000040,
-
-	/**
-	 * Allow passwords to be optional.
-	 *
-	 * Passwords in IRC are optional, and are needed for certain
-	 * functionality.
-	 */
-	OPT_PROTO_PASSWORD_OPTIONAL = 0x00000080,
-
-	/**
-	 * Allows font size to be specified in sane point size
-	 *
-	 * Probably just XMPP and Y!M
-	 */
-	OPT_PROTO_USE_POINTSIZE = 0x00000100,
-
-	/**
-	 * Set the Register button active even when the username has not
-	 * been specified.
-	 *
-	 * Gadu-Gadu doesn't need a username to register new account (because
-	 * usernames are assigned by the server).
-	 */
-	OPT_PROTO_REGISTER_NOSCREENNAME = 0x00000200,
-
-	/**
-	 * Indicates that slash commands are native to this protocol.
-	 * Used as a hint that unknown commands should not be sent as messages.
-	 */
-	OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400,
-
-	/**
-	 * Indicates that this protocol supports sending a user-supplied message
-	 * along with an invitation.
-	 */
-	OPT_PROTO_INVITE_MESSAGE = 0x00000800,
-
-	/**
-	 * Indicates that this protocol supports sending a user-supplied message
-	 * along with an authorization acceptance.
-	 */
-	OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE = 0x00001000,
-
-	/**
-	 * Indicates that this protocol supports sending a user-supplied message
-	 * along with an authorization denial.
-	 */
-	OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE = 0x00002000
-
-} PurpleProtocolOptions;
-
-/**
- * A protocol plugin information structure.
- *
- * Every protocol plugin initializes this structure. It is the gateway
- * between purple and the protocol plugin.  Many of these callbacks can be
- * NULL.  If a callback must be implemented, it has a comment indicating so.
- */
-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 */
-	GList *protocol_options; /**< A GList of PurpleAccountOption    */
-
-	PurpleBuddyIconSpec icon_spec; /**< The icon spec. */
-
-	/**
-	 * Returns the base icon name for the given buddy and account.
-	 * If buddy is NULL and the account is non-NULL, it will return the
-	 * name to use for the account's icon. If both are NULL, it will
-	 * return the name to use for the protocol's icon.
-	 *
-	 * This must be implemented.
-	 */
-	const char *(*list_icon)(PurpleAccount *account, PurpleBuddy *buddy);
-
-	/**
-	 * Fills the four char**'s with string identifiers for "emblems"
-	 * that the UI will interpret and display as relevant
-	 */
-	const char *(*list_emblem)(PurpleBuddy *buddy);
-
-	/**
-	 * Gets a short string representing this buddy's status.  This will
-	 * be shown on the buddy list.
-	 */
-	char *(*status_text)(PurpleBuddy *buddy);
-
-	/**
-	 * Allows the prpl to add text to a buddy's tooltip.
-	 */
-	void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full);
-
-	/**
-	 * Returns a list of #PurpleStatusType which exist for this account;
-	 * this must be implemented, and must add at least the offline and
-	 * online states.
-	 */
-	GList *(*status_types)(PurpleAccount *account);
-
-	/**
-	 * Returns a list of #PurpleMenuAction structs, which represent extra
-	 * actions to be shown in (for example) the right-click menu for @a
-	 * node.
-	 */
-	GList *(*blist_node_menu)(PurpleBlistNode *node);
-
-	/**
-	 * Returns a list of #proto_chat_entry structs, which represent
-	 * information required by the PRPL to join a chat. libpurple will
-	 * call join_chat along with the information filled by the user.
-	 *
-	 * @return A list of #proto_chat_entry structs
-	 */
-	GList *(*chat_info)(PurpleConnection *);
-
-	/**
-	 * Returns a hashtable which maps #proto_chat_entry struct identifiers
-	 * to default options as strings based on chat_name. The resulting
-	 * hashtable should be created with g_hash_table_new_full(g_str_hash,
-	 * g_str_equal, NULL, g_free);. Use #get_chat_name if you instead need
-	 * to extract a chat name from a hashtable.
-	 *
-	 * @param chat_name The chat name to be turned into components
-	 * @return Hashtable containing the information extracted from chat_name
-	 */
-	GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name);
-
-	/* All the server-related functions */
-
-	/** This must be implemented. */
-	void (*login)(PurpleAccount *);
-
-	/** This must be implemented. */
-	void (*close)(PurpleConnection *);
-
-	/**
-	 * This PRPL function should return a positive value on success.
-	 * If the message is too big to be sent, return -E2BIG.  If
-	 * the account is not connected, return -ENOTCONN.  If the
-	 * PRPL is unable to send the message for another reason, return
-	 * some other negative value.  You can use one of the valid
-	 * errno values, or just big something.  If the message should
-	 * not be echoed to the conversation window, return 0.
-	 */
-	int  (*send_im)(PurpleConnection *, const char *who,
-					const char *message,
-					PurpleMessageFlags flags);
-
-	void (*set_info)(PurpleConnection *, const char *info);
-
-	/**
-	 * @return If this protocol requires the PURPLE_IM_TYPING message to
-	 *         be sent repeatedly to signify that the user is still
-	 *         typing, then the PRPL should return the number of
-	 *         seconds to wait before sending a subsequent notification.
-	 *         Otherwise the PRPL should return 0.
-	 */
-	unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleIMTypingState state);
-
-	/**
-	 * Should arrange for purple_notify_userinfo() to be called with
-	 * @a who's user info.
-	 */
-	void (*get_info)(PurpleConnection *, const char *who);
-	void (*set_status)(PurpleAccount *account, PurpleStatus *status);
-
-	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.
-	 *
-	 * 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.
-	 */
-	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);
-	void (*add_deny)(PurpleConnection *, const char *name);
-	void (*rem_permit)(PurpleConnection *, const char *name);
-	void (*rem_deny)(PurpleConnection *, const char *name);
-	void (*set_permit_deny)(PurpleConnection *);
-
-	/**
-	 * Called when the user requests joining a chat. Should arrange for
-	 * #serv_got_joined_chat to be called.
-	 *
-	 * @param components A hashtable containing information required to
-	 *                   join the chat as described by the entries returned
-	 *                   by #chat_info. It may also be called when accepting
-	 *                   an invitation, in which case this matches the
-	 *                   data parameter passed to #serv_got_chat_invite.
-	 */
-	void (*join_chat)(PurpleConnection *, GHashTable *components);
-
-	/**
-	 * Called when the user refuses a chat invitation.
-	 *
-	 * @param components A hashtable containing information required to
-	 *                   join the chat as passed to #serv_got_chat_invite.
-	 */
-	void (*reject_chat)(PurpleConnection *, GHashTable *components);
-
-	/**
-	 * Returns a chat name based on the information in components. Use
-	 * #chat_info_defaults if you instead need to generate a hashtable
-	 * from a chat name.
-	 *
-	 * @param components A hashtable containing information about the chat.
-	 */
-	char *(*get_chat_name)(GHashTable *components);
-
-	/**
-	 * Invite a user to join a chat.
-	 *
-	 * @param id      The id of the chat to invite the user to.
-	 * @param message A message displayed to the user when the invitation
-	 *                is received.
-	 * @param who     The name of the user to send the invation to.
-	 */
-	void (*chat_invite)(PurpleConnection *, int id,
-						const char *message, const char *who);
-	/**
-	 * Called when the user requests leaving a chat.
-	 *
-	 * @param id The id of the chat to leave
-	 */
-	void (*chat_leave)(PurpleConnection *, int id);
-
-	/**
-	 * Send a whisper to a user in a chat.
-	 *
-	 * @param id      The id of the chat.
-	 * @param who     The name of the user to send the whisper to.
-	 * @param message The message of the whisper.
-	 */
-	void (*chat_whisper)(PurpleConnection *, int id,
-						 const char *who, const char *message);
-
-	/**
-	 * Send a message to a chat.
-	 * This PRPL function should return a positive value on success.
-	 * If the message is too big to be sent, return -E2BIG.  If
-	 * the account is not connected, return -ENOTCONN.  If the
-	 * PRPL is unable to send the message for another reason, return
-	 * some other negative value.  You can use one of the valid
-	 * errno values, or just big something.
-	 *
-	 * @param id      The id of the chat to send the message to.
-	 * @param message The message to send to the chat.
-	 * @param flags   A bitwise OR of #PurpleMessageFlags representing
-	 *                message flags.
-	 * @return 	  A positive number or 0 in case of success,
-	 *                a negative error number in case of failure.
-	 */
-	int  (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags);
-
-	/** If implemented, this will be called regularly for this prpl's
-	 *  active connections.  You'd want to do this if you need to repeatedly
-	 *  send some kind of keepalive packet to the server to avoid being
-	 *  disconnected.  ("Regularly" is defined by
-	 *  <code>KEEPALIVE_INTERVAL</code> in <tt>libpurple/connection.c</tt>.)
-	 */
-	void (*keepalive)(PurpleConnection *);
-
-	/** new user registration */
-	void (*register_user)(PurpleAccount *);
-
-	/**
-	 * @deprecated Use #PurplePluginProtocolInfo.get_info instead.
-	 */
-	void (*get_cb_info)(PurpleConnection *, int, const char *who);
-
-	/** save/store buddy's alias on server list/roster */
-	void (*alias_buddy)(PurpleConnection *, const char *who,
-						const char *alias);
-
-	/** change a buddy's group on a server list/roster */
-	void (*group_buddy)(PurpleConnection *, const char *who,
-						const char *old_group, const char *new_group);
-
-	/** rename a group on a server list/roster */
-	void (*rename_group)(PurpleConnection *, const char *old_name,
-						 PurpleGroup *group, GList *moved_buddies);
-
-	void (*buddy_free)(PurpleBuddy *);
-
-	void (*convo_closed)(PurpleConnection *, const char *who);
-
-	/**
-	 * Convert the username @a who to its canonical form. Also checks for
-	 * validity.
-	 *
-	 * For example, AIM treats "fOo BaR" and "foobar" as the same user; this
-	 * function should return the same normalized string for both of those.
-	 * On the other hand, both of these are invalid for protocols with
-	 * number-based usernames, so function should return NULL in such case.
-	 *
-	 * @param account  The account the username is related to. Can
-	 *                 be NULL.
-	 * @param who      The username to convert.
-	 * @return         Normalized username, or NULL, if it's invalid.
-	 */
-	const char *(*normalize)(const PurpleAccount *account, const char *who);
-
-	/**
-	 * Set the buddy icon for the given connection to @a img.  The prpl
-	 * does NOT own a reference to @a img; if it needs one, it must
-	 * #purple_imgstore_ref(@a img) itself.
-	 */
-	void (*set_buddy_icon)(PurpleConnection *, PurpleStoredImage *img);
-
-	void (*remove_group)(PurpleConnection *gc, PurpleGroup *group);
-
-	/** Gets the real name of a participant in a chat.  For example, on
-	 *  XMPP this turns a chat room nick <tt>foo</tt> into
-	 *  <tt>room\@server/foo</tt>
-	 *  @param gc  the connection on which the room is.
-	 *  @param id  the ID of the chat room.
-	 *  @param who the nickname of the chat participant.
-	 *  @return    the real name of the participant.  This string must be
-	 *             freed by the caller.
-	 */
-	char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who);
-
-	void (*set_chat_topic)(PurpleConnection *gc, int id, const char *topic);
-
-	PurpleChat *(*find_blist_chat)(PurpleAccount *account, const char *name);
-
-	/* room listing prpl callbacks */
-	PurpleRoomlist *(*roomlist_get_list)(PurpleConnection *gc);
-	void (*roomlist_cancel)(PurpleRoomlist *list);
-	void (*roomlist_expand_category)(PurpleRoomlist *list, PurpleRoomlistRoom *category);
-
-	/* file transfer callbacks */
-	gboolean (*can_receive_file)(PurpleConnection *, const char *who);
-	void (*send_file)(PurpleConnection *, const char *who, const char *filename);
-	PurpleXfer *(*new_xfer)(PurpleConnection *, const char *who);
-
-	/** Checks whether offline messages to @a buddy are supported.
-	 *  @return @c TRUE if @a buddy can be sent messages while they are
-	 *          offline, or @c FALSE if not.
-	 */
-	gboolean (*offline_message)(const PurpleBuddy *buddy);
-
-	PurpleWhiteboardPrplOps *whiteboard_prpl_ops;
-
-	/** For use in plugins that may understand the underlying protocol */
-	int (*send_raw)(PurpleConnection *gc, const char *buf, int len);
-
-	/* room list serialize */
-	char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room);
-
-	/** Remove the user from the server.  The account can either be
-	 * connected or disconnected. After the removal is finished, the
-	 * connection will stay open and has to be closed!
-	 */
-	/* This is here rather than next to register_user for API compatibility
-	 * reasons.
-	 */
-	void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data);
-
-	/* Attention API for sending & receiving zaps/nudges/buzzes etc. */
-	gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type);
-	GList *(*get_attention_types)(PurpleAccount *acct);
-
-	/** 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
-	 * table is allocated every call and MUST be unrefed by the caller.
-	 *
-	 * @param account The account to specify.  This can be NULL.
-	 * @return The protocol's string hash table. The hash table should be
-	 *         destroyed by the caller when it's no longer needed.
-	 */
-	GHashTable *(*get_account_text_table)(PurpleAccount *account);
-
-	/**
-	 * Initiate a media session with the given contact.
-	 *
-	 * @param account The account to initiate the media session on.
-	 * @param who The remote user to initiate the session with.
-	 * @param type The type of media session to initiate.
-	 * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created)
-	 */
-	gboolean (*initiate_media)(PurpleAccount *account, const char *who,
-					PurpleMediaSessionType type);
-
-	/**
-	 * Checks to see if the given contact supports the given type of media session.
-	 *
-	 * @param account The account the contact is on.
-	 * @param who The remote user to check for media capability with.
-	 * @return The media caps the contact supports.
-	 */
-	PurpleMediaCaps (*get_media_caps)(PurpleAccount *account,
-					  const char *who);
-
-	/**
-	 * Returns an array of "PurpleMood"s, with the last one having
-	 * "mood" set to @c NULL.
-	 */
-	PurpleMood *(*get_moods)(PurpleAccount *account);
-
-	/**
-	 * Set the user's "friendly name" (or alias or nickname or
-	 * whatever term you want to call it) on the server.  The
-	 * protocol plugin should call success_cb or failure_cb
-	 * *asynchronously* (if it knows immediately that the set will fail,
-	 * call one of the callbacks from an idle/0-second timeout) depending
-	 * on if the nickname is set successfully.
-	 *
-	 * @param gc    The connection for which to set an alias
-	 * @param alias The new server-side alias/nickname for this account,
-	 *              or NULL to unset the alias/nickname (or return it to
-	 *              a protocol-specific "default").
-	 * @param success_cb Callback to be called if the public alias is set
-	 * @param failure_cb Callback to be called if setting the public alias
-	 *                   fails
-	 * @see purple_account_set_public_alias
-	 */
-	void (*set_public_alias)(PurpleConnection *gc, const char *alias,
-	                         PurpleSetPublicAliasSuccessCallback success_cb,
-	                         PurpleSetPublicAliasFailureCallback failure_cb);
-	/**
-	 * Retrieve the user's "friendly name" as set on the server.
-	 * The protocol plugin should call success_cb or failure_cb
-	 * *asynchronously* (even if it knows immediately that the get will fail,
-	 * call one of the callbacks from an idle/0-second timeout) depending
-	 * on if the nickname is retrieved.
-	 *
-	 * @param gc    The connection for which to retireve the alias
-	 * @param success_cb Callback to be called with the retrieved alias
-	 * @param failure_cb Callback to be called if the prpl is unable to
-	 *                   retrieve the alias
-	 * @see purple_account_get_public_alias
-	 */
-	void (*get_public_alias)(PurpleConnection *gc,
-	                         PurpleGetPublicAliasSuccessCallback success_cb,
-	                         PurpleGetPublicAliasFailureCallback failure_cb);
-};
-
-#define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
-	(G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size && \
-	 prpl->member != NULL)
-
-
-#define PURPLE_IS_PROTOCOL_PLUGIN(plugin) \
-	((plugin)->info->type == PURPLE_PLUGIN_PROTOCOL)
-
-#define PURPLE_PLUGIN_PROTOCOL_INFO(plugin) \
-	((PurplePluginProtocolInfo *)(plugin)->info->extra_info)
-
-G_BEGIN_DECLS
-
-/**************************************************************************/
-/** @name Attention Type API                                              */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Creates a new #PurpleAttentionType object and sets its mandatory parameters.
- *
- * @param ulname A non-localized string that can be used by UIs in need of such
- *               non-localized strings.  This should be the same as @a name,
- *               without localization.
- * @param name A localized string that the UI may display for the event. This
- *             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.
- */
-PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name,
-								const char *inc_desc, const char *out_desc);
-
-/**
- * Sets the displayed name of the attention-demanding event.
- *
- * @param type The attention type.
- * @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.
- */
-void purple_attention_type_set_name(PurpleAttentionType *type, const char *name);
-
-/**
- * Sets the description of the attention-demanding event shown in  conversations
- * when the event is received.
- *
- * @param type The attention type.
- * @param desc The localized description for incoming events.
- */
-void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc);
-
-/**
- * Sets the description of the attention-demanding event shown in conversations
- * when the event is sent.
- *
- * @param type The attention type.
- * @param desc The localized description for outgoing events.
- */
-void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc);
-
-/**
- * Sets the name of the icon to display for the attention event; this is optional.
- *
- * @param type The attention type.
- * @param name The icon's name.
- * @note Icons are optional for attention events.
- */
-void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name);
-
-/**
- * Sets the unlocalized name of the attention event; some UIs may need this,
- * thus it is required.
- *
- * @param type The attention type.
- * @param ulname The unlocalized name.  This should be the same string given as
- *               the localized name, but without localization.
- */
-void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname);
-
-/**
- * Get the attention type's name as displayed by the UI.
- *
- * @param type The attention type.
- *
- * @return The name.
- */
-const char *purple_attention_type_get_name(const PurpleAttentionType *type);
-
-/**
- * Get the attention type's description shown when the event is received.
- *
- * @param type The attention type.
- * @return The description.
- */
-const char *purple_attention_type_get_incoming_desc(const PurpleAttentionType *type);
-
-/**
- * Get the attention type's description shown when the event is sent.
- *
- * @param type The attention type.
- * @return The description.
- */
-const char *purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type);
-
-/**
- * Get the attention type's icon name.
- *
- * @param type The attention type.
- * @return The icon name or @c NULL if unset/empty.
- * @note Icons are optional for attention events.
- */
-const char *purple_attention_type_get_icon_name(const PurpleAttentionType *type);
-
-/**
- * Get the attention type's unlocalized name; this is useful for some UIs.
- *
- * @param type The attention type
- * @return The unlocalized name.
- */
-const char *purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type);
-
-/*@}*/
-
-/**************************************************************************/
-/** @name Protocol Plugin API                                             */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Notifies Purple that our account's idle state and time have changed.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account   The account.
- * @param idle      The user's idle state.
- * @param idle_time The user's idle time.
- */
-void purple_prpl_got_account_idle(PurpleAccount *account, gboolean idle,
-								time_t idle_time);
-
-/**
- * Notifies Purple of our account's log-in time.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account    The account the user is on.
- * @param login_time The user's log-in time.
- */
-void purple_prpl_got_account_login_time(PurpleAccount *account, time_t login_time);
-
-/**
- * Notifies Purple that our account's status has changed.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account   The account the user is on.
- * @param status_id The status ID.
- * @param ...       A NULL-terminated list of attribute IDs and values,
- *                  beginning with the value for @a attr_id.
- */
-void purple_prpl_got_account_status(PurpleAccount *account,
-								  const char *status_id, ...) G_GNUC_NULL_TERMINATED;
-
-/**
- * Notifies Purple that our account's actions have changed. This is only
- * called after the initial connection. Emits the account-actions-changed
- * signal.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account   The account.
- *
- * @see account-actions-changed
- */
-void purple_prpl_got_account_actions(PurpleAccount *account);
-
-/**
- * Notifies Purple that a buddy's idle state and time have changed.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account   The account the user is on.
- * @param name      The name of the buddy.
- * @param idle      The user's idle state.
- * @param idle_time The user's idle time.  This is the time at
- *                  which the user became idle, in seconds since
- *                  the epoch.  If the PRPL does not know this value
- *                  then it should pass 0.
- */
-void purple_prpl_got_user_idle(PurpleAccount *account, const char *name,
-							 gboolean idle, time_t idle_time);
-
-/**
- * Notifies Purple of a buddy's log-in time.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account    The account the user is on.
- * @param name       The name of the buddy.
- * @param login_time The user's log-in time.
- */
-void purple_prpl_got_user_login_time(PurpleAccount *account, const char *name,
-								   time_t login_time);
-
-/**
- * Notifies Purple that a buddy's status has been activated.
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account   The account the user is on.
- * @param name      The name of the buddy.
- * @param status_id The status ID.
- * @param ...       A NULL-terminated list of attribute IDs and values,
- *                  beginning with the value for @a attr_id.
- */
-void purple_prpl_got_user_status(PurpleAccount *account, const char *name,
-							   const char *status_id, ...) G_GNUC_NULL_TERMINATED;
-
-/**
- * Notifies libpurple that a buddy's status has been deactivated
- *
- * This is meant to be called from protocol plugins.
- *
- * @param account   The account the user is on.
- * @param name      The name of the buddy.
- * @param status_id The status ID.
- */
-void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *name,
-					const char *status_id);
-
-/**
- * Informs the server that our account's status changed.
- *
- * @param account    The account the user is on.
- * @param old_status The previous status.
- * @param new_status The status that was activated, or deactivated
- *                   (in the case of independent statuses).
- */
-void purple_prpl_change_account_status(PurpleAccount *account,
-									 PurpleStatus *old_status,
-									 PurpleStatus *new_status);
-
-/**
- * Retrieves the list of stock status types from a prpl.
- *
- * @param account The account the user is on.
- * @param presence The presence for which we're going to get statuses
- *
- * @return List of statuses
- */
-GList *purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence);
-
-/**
- * Send an attention request message.
- *
- * @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 purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code);
-
-/**
- * Process an incoming attention message.
- *
- * @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 purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code);
-
-/**
- * Process an incoming attention message in a chat.
- *
- * @param gc The connection that received the attention message.
- * @param id The chat id.
- * @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 purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code);
-
-/**
- * Determines if the contact supports the given media session type.
- *
- * @param account The account the user is on.
- * @param who The name of the contact to check capabilities for.
- *
- * @return The media caps the contact supports.
- */
-PurpleMediaCaps purple_prpl_get_media_caps(PurpleAccount *account,
-				  const char *who);
-
-/**
- * Initiates a media session with the given contact.
- *
- * @param account The account the user is on.
- * @param who The name of the contact to start a session with.
- * @param type The type of media session to start.
- *
- * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created)
- */
-gboolean purple_prpl_initiate_media(PurpleAccount *account,
-					const char *who,
-					PurpleMediaSessionType type);
-
-/**
- * Signals that the prpl received capabilities for the given contact.
- *
- * This function is intended to be used only by prpls.
- *
- * @param account The account the user is on.
- * @param who The name of the contact for which capabilities have been received.
- */
-void purple_prpl_got_media_caps(PurpleAccount *account, const char *who);
-
-/*@}*/
-
-/**************************************************************************/
-/** @name Protocol Plugin Subsystem API                                   */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Finds a protocol plugin structure of the specified type.
- *
- * @param id The protocol plugin;
- */
-PurplePlugin *purple_find_prpl(const char *id);
-
-/*@}*/
-
-G_END_DECLS
-
-#endif /* _PRPL_H_ */
--- a/libpurple/purple.h.in	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/purple.h.in	Sun Aug 18 01:53:00 2013 +0530
@@ -71,13 +71,13 @@
 #include <network.h>
 #include <notify.h>
 #include <ntlm.h>
-#include <plugin.h>
+#include <plugins.h>
 #include <pluginpref.h>
 #include <pounce.h>
 #include <prefs.h>
 #include <presence.h>
 #include <proxy.h>
-#include <prpl.h>
+#include <protocol.h>
 #include <request.h>
 #include <roomlist.h>
 #include <savedstatuses.h>
--- a/libpurple/roomlist.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/roomlist.c	Sun Aug 18 01:53:00 2013 +0530
@@ -207,27 +207,22 @@
 
 PurpleRoomlist *purple_roomlist_get_list(PurpleConnection *gc)
 {
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	g_return_val_if_fail(gc != NULL, NULL);
 	g_return_val_if_fail(PURPLE_CONNECTION_IS_CONNECTED(gc), NULL);
 
-	prpl = purple_connection_get_prpl(gc);
+	protocol = purple_connection_get_protocol_info(gc);
 
-	if(prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if(prpl_info && prpl_info->roomlist_get_list)
-		return prpl_info->roomlist_get_list(gc);
+	if(protocol && protocol->roomlist_get_list)
+		return protocol->roomlist_get_list(gc);
 
 	return NULL;
 }
 
 void purple_roomlist_cancel_get_list(PurpleRoomlist *list)
 {
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConnection *gc;
 
 	g_return_if_fail(list != NULL);
@@ -237,19 +232,15 @@
 	g_return_if_fail(gc != NULL);
 
 	if(gc)
-		prpl = purple_connection_get_prpl(gc);
+		protocol = purple_connection_get_protocol_info(gc);
 
-	if(prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if(prpl_info && prpl_info->roomlist_cancel)
-		prpl_info->roomlist_cancel(list);
+	if(protocol && protocol->roomlist_cancel)
+		protocol->roomlist_cancel(list);
 }
 
 void purple_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category)
 {
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConnection *gc;
 
 	g_return_if_fail(list != NULL);
@@ -260,13 +251,10 @@
 	g_return_if_fail(gc != NULL);
 
 	if(gc)
-		prpl = purple_connection_get_prpl(gc);
+		protocol = purple_connection_get_protocol_info(gc);
 
-	if(prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if(prpl_info && prpl_info->roomlist_expand_category)
-		prpl_info->roomlist_expand_category(list, category);
+	if(protocol && protocol->roomlist_expand_category)
+		protocol->roomlist_expand_category(list, category);
 }
 
 GList * purple_roomlist_get_fields(PurpleRoomlist *list)
--- a/libpurple/server.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/server.c	Sun Aug 18 01:53:00 2013 +0530
@@ -30,7 +30,7 @@
 #include "log.h"
 #include "notify.h"
 #include "prefs.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "signals.h"
 #include "server.h"
@@ -43,15 +43,13 @@
 unsigned int
 serv_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->send_typing)
-			return prpl_info->send_typing(gc, name, state);
+		if (protocol->send_typing)
+			return protocol->send_typing(gc, name, state);
 	}
 
 	return 0;
@@ -122,26 +120,23 @@
 	PurpleIMConversation *im = NULL;
 	PurpleAccount *account = NULL;
 	PurplePresence *presence = NULL;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	int val = -EINVAL;
 	const gchar *auto_reply_pref = NULL;
 
 	g_return_val_if_fail(gc != NULL, val);
 
-	prpl = purple_connection_get_prpl(gc);
+	protocol = purple_connection_get_protocol_info(gc);
 
-	g_return_val_if_fail(prpl != NULL, val);
-
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	g_return_val_if_fail(protocol != NULL, val);
 
 	account  = purple_connection_get_account(gc);
 	presence = purple_account_get_presence(account);
 
 	im = purple_conversations_find_im_with_account(name, account);
 
-	if (prpl_info->send_im)
-		val = prpl_info->send_im(gc, name, message, flags);
+	if (protocol->send_im)
+		val = protocol->send_im(gc, name, message, flags);
 
 	/*
 	 * XXX - If "only auto-reply when away & idle" is set, then shouldn't
@@ -165,36 +160,32 @@
 
 void serv_get_info(PurpleConnection *gc, const char *name)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->get_info)
-			prpl_info->get_info(gc, name);
+		if (protocol->get_info)
+			protocol->get_info(gc, name);
 	}
 }
 
 void serv_set_info(PurpleConnection *gc, const char *info)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleAccount *account;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->set_info) {
+		if (protocol->set_info) {
 			account = purple_connection_get_account(gc);
 
 			if (purple_signal_emit_return_1(purple_accounts_get_handle(),
 					"account-setting-info", account, info))
 				return;
 
-			prpl_info->set_info(gc, info);
+			protocol->set_info(gc, info);
 
 			purple_signal_emit(purple_accounts_get_handle(),
 					"account-set-info", account, info);
@@ -209,8 +200,7 @@
 {
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (b) {
 		account = purple_buddy_get_account(b);
@@ -219,11 +209,10 @@
 			gc = purple_account_get_connection(account);
 
 			if (gc) {
-				prpl = purple_connection_get_prpl(gc);
-				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+				protocol = purple_connection_get_protocol_info(gc);
 
-				if (prpl_info->alias_buddy)
-					prpl_info->alias_buddy(gc,
+				if (protocol->alias_buddy)
+					protocol->alias_buddy(gc,
 							purple_buddy_get_name(b),
 							purple_buddy_get_local_alias(b));
 			}
@@ -302,16 +291,16 @@
 
 PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code)
 {
-	PurplePlugin *prpl;
+	PurpleProtocol *protocol;
 	PurpleAttentionType* attn;
 	GList *(*get_attention_types)(PurpleAccount *);
 
 	g_return_val_if_fail(account != NULL, NULL);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
 	/* Lookup the attention type in the protocol's attention_types list, if any. */
-	get_attention_types = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->get_attention_types;
+	get_attention_types = protocol->get_attention_types;
 	if (get_attention_types) {
 		GList *attention_types;
 
@@ -336,8 +325,7 @@
 {
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	g_return_if_fail(b != NULL);
 	g_return_if_fail(og != NULL);
@@ -347,11 +335,10 @@
 	gc = purple_account_get_connection(account);
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->group_buddy)
-			prpl_info->group_buddy(gc, purple_buddy_get_name(b),
+		if (protocol->group_buddy)
+			protocol->group_buddy(gc, purple_buddy_get_name(b),
 					purple_group_get_name(og),
 					purple_group_get_name(ng));
 	}
@@ -359,68 +346,58 @@
 
 void serv_add_permit(PurpleConnection *gc, const char *name)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->add_permit)
-			prpl_info->add_permit(gc, name);
+		if (protocol->add_permit)
+			protocol->add_permit(gc, name);
 	}
 }
 
 void serv_add_deny(PurpleConnection *gc, const char *name)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->add_deny)
-			prpl_info->add_deny(gc, name);
+		if (protocol->add_deny)
+			protocol->add_deny(gc, name);
 	}
 }
 
 void serv_rem_permit(PurpleConnection *gc, const char *name)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->rem_permit)
-			prpl_info->rem_permit(gc, name);
+		if (protocol->rem_permit)
+			protocol->rem_permit(gc, name);
 	}
 }
 
 void serv_rem_deny(PurpleConnection *gc, const char *name)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->rem_deny)
-			prpl_info->rem_deny(gc, name);
+		if (protocol->rem_deny)
+			protocol->rem_deny(gc, name);
 	}
 }
 
 void serv_set_permit_deny(PurpleConnection *gc)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
 		/*
 		 * this is called when either you import a buddy list, and make lots
@@ -428,44 +405,39 @@
 		 * in the prefs. In either case you should probably be resetting and
 		 * resending the permit/deny info when you get this.
 		 */
-		if (prpl_info->set_permit_deny)
-			prpl_info->set_permit_deny(gc);
+		if (protocol->set_permit_deny)
+			protocol->set_permit_deny(gc);
 	}
 }
 
 void serv_join_chat(PurpleConnection *gc, GHashTable *data)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->join_chat)
-			prpl_info->join_chat(gc, data);
+		if (protocol->join_chat)
+			protocol->join_chat(gc, data);
 	}
 }
 
 
 void serv_reject_chat(PurpleConnection *gc, GHashTable *data)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->reject_chat)
-			prpl_info->reject_chat(gc, data);
+		if (protocol->reject_chat)
+			protocol->reject_chat(gc, data);
 	}
 }
 
 void serv_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name)
 {
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleChatConversation *chat;
 	char *buffy = message && *message ? g_strdup(message) : NULL;
 
@@ -475,16 +447,13 @@
 		return;
 
 	if(gc)
-		prpl = purple_connection_get_prpl(gc);
-
-	if(prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
 	purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user",
 					 chat, name, &buffy);
 
-	if (prpl_info && prpl_info->chat_invite)
-		prpl_info->chat_invite(gc, id, buffy, name);
+	if (protocol && protocol->chat_invite)
+		protocol->chat_invite(gc, id, buffy, name);
 
 	purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user",
 					 chat, name, buffy);
@@ -499,40 +468,34 @@
  */
 void serv_chat_leave(PurpleConnection *gc, int id)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
-	prpl = purple_connection_get_prpl(gc);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	protocol = purple_connection_get_protocol_info(gc);
 
-	if (prpl_info->chat_leave)
-		prpl_info->chat_leave(gc, id);
+	if (protocol->chat_leave)
+		protocol->chat_leave(gc, id);
 }
 
 void serv_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->chat_whisper)
-			prpl_info->chat_whisper(gc, id, who, message);
+		if (protocol->chat_whisper)
+			protocol->chat_whisper(gc, id, who, message);
 	}
 }
 
 int serv_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
-	prpl = purple_connection_get_prpl(gc);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	protocol = purple_connection_get_protocol_info(gc);
 
-	if (prpl_info->chat_send)
-		return prpl_info->chat_send(gc, id, message, flags);
+	if (protocol->chat_send)
+		return protocol->chat_send(gc, id, message, flags);
 
 	return -EINVAL;
 }
@@ -923,16 +886,14 @@
 
 void serv_send_file(PurpleConnection *gc, const char *who, const char *file)
 {
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	if (gc) {
-		prpl = purple_connection_get_prpl(gc);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_connection_get_protocol_info(gc);
 
-		if (prpl_info->send_file &&
-				(!prpl_info->can_receive_file
-						|| prpl_info->can_receive_file(gc, who)))
-			prpl_info->send_file(gc, who, file);
+		if (protocol->send_file &&
+				(!protocol->can_receive_file
+						|| protocol->can_receive_file(gc, who)))
+			protocol->send_file(gc, who, file);
 	}
 }
--- a/libpurple/server.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/server.h	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 
 #include "accounts.h"
 #include "conversations.h"
-#include "prpl.h"
+#include "protocol.h"
 
 G_BEGIN_DECLS
 
--- a/libpurple/sslconn.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/sslconn.c	Sun Aug 18 01:53:00 2013 +0530
@@ -29,6 +29,7 @@
 
 #include "certificate.h"
 #include "debug.h"
+#include "plugins.h"
 #include "request.h"
 #include "sslconn.h"
 
@@ -44,10 +45,10 @@
 	if (_ssl_initialized)
 		return FALSE;
 
-	plugin = purple_plugins_find_with_id("core-ssl");
+	plugin = purple_plugins_find_plugin("core-ssl");
 
-	if (plugin != NULL && !purple_plugin_is_loaded(plugin))
-		purple_plugin_load(plugin);
+	if (plugin != NULL)
+		purple_plugin_load(plugin, NULL);
 
 	ops = purple_ssl_get_ops();
 	if ((ops == NULL) || (ops->init == NULL) || (ops->uninit == NULL) ||
--- a/libpurple/status.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/status.c	Sun Aug 18 01:53:00 2013 +0530
@@ -559,7 +559,7 @@
 		PurpleAccountUiOps *ops = purple_accounts_get_ui_ops();
 
 		if (purple_account_get_enabled(account, purple_core_get_ui()))
-			purple_prpl_change_account_status(account, old_status, new_status);
+			purple_protocol_change_account_status(account, old_status, new_status);
 
 		if (ops != NULL && ops->status_changed != NULL)
 		{
--- a/libpurple/tests/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/tests/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -23,6 +23,7 @@
 check_libpurple_CFLAGS=\
         @CHECK_CFLAGS@ \
 		$(GLIB_CFLAGS) \
+		$(GPLUGIN_CFLAGS) \
 		$(DEBUG_CFLAGS) \
 		$(LIBXML_CFLAGS) \
 		-I.. \
@@ -35,6 +36,7 @@
 		$(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
 		$(top_builddir)/libpurple/libpurple.la \
         @CHECK_LIBS@ \
-		$(GLIB_LIBS)
+		$(GLIB_LIBS) \
+		$(GPLUGIN_LIBS)
 
 endif
--- a/libpurple/util.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/util.c	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 #include "core.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "prefs.h"
 #include "util.h"
 
@@ -3389,15 +3389,11 @@
 
 	if (account != NULL)
 	{
-		PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-
-		if (prpl != NULL)
-		{
-			PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-			if (prpl_info->normalize)
-				ret = prpl_info->normalize(account, str);
-		}
+		PurpleProtocol *protocol =
+				purple_find_protocol_info(purple_account_get_protocol_id(account));
+
+		if (protocol != NULL && protocol->normalize)
+			ret = protocol->normalize(account, str);
 	}
 
 	if (ret == NULL)
@@ -3437,23 +3433,20 @@
 }
 
 gboolean
-purple_validate(const PurplePlugin *prpl, const char *str)
+purple_validate(const PurpleProtocol *protocol, const char *str)
 {
-	PurplePluginProtocolInfo *prpl_info;
 	const char *normalized;
 
-	g_return_val_if_fail(prpl != NULL, FALSE);
+	g_return_val_if_fail(protocol != NULL, FALSE);
 	g_return_val_if_fail(str != NULL, FALSE);
 
 	if (str[0] == '\0')
 		return FALSE;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (!prpl_info->normalize)
+	if (!protocol->normalize)
 		return TRUE;
 
-	normalized = prpl_info->normalize(NULL, str);
+	normalized = protocol->normalize(NULL, str);
 
 	return (NULL != normalized);
 }
--- a/libpurple/util.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/util.h	Sun Aug 18 01:53:00 2013 +0530
@@ -50,7 +50,7 @@
 #include "signals.h"
 #include "xmlnode.h"
 #include "notify.h"
-#include "plugin.h"
+#include "protocol.h"
 
 
 typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len);
@@ -961,7 +961,7 @@
  *
  * @return TRUE, if string is valid, otherwise FALSE.
  */
-gboolean purple_validate(const PurplePlugin *prpl, const char *str);
+gboolean purple_validate(const PurpleProtocol *protocol, const char *str);
 
 /**
  * Compares two strings to see if the first contains the second as
--- a/libpurple/whiteboard.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/whiteboard.c	Sun Aug 18 01:53:00 2013 +0530
@@ -23,7 +23,7 @@
 
 #include "internal.h"
 #include "whiteboard.h"
-#include "prpl.h"
+#include "protocol.h"
 
 /**
  * A PurpleWhiteboard
@@ -37,7 +37,7 @@
 
 	void *ui_data;                   /**< Graphical user-interface data */
 	void *proto_data;                /**< Protocol specific data */
-	PurpleWhiteboardPrplOps *prpl_ops; /**< Protocol-plugin operations */
+	PurpleWhiteboardPrplOps *protocol_ops; /**< Protocol-plugin operations */
 
 	GList *draw_list;                /**< List of drawing elements/deltas to send */
 };
@@ -46,7 +46,7 @@
  * Globals
  *****************************************************************************/
 static PurpleWhiteboardUiOps *whiteboard_ui_ops = NULL;
-/* static PurpleWhiteboardPrplOps *whiteboard_prpl_ops = NULL; */
+/* static PurpleWhiteboardPrplOps *whiteboard_protocol_ops = NULL; */
 
 static GList *wbList = NULL;
 
@@ -60,27 +60,26 @@
 	whiteboard_ui_ops = ops;
 }
 
-void purple_whiteboard_set_prpl_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops)
+void purple_whiteboard_set_protocol_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops)
 {
-	wb->prpl_ops = ops;
+	wb->protocol_ops = ops;
 }
 
 PurpleWhiteboard *purple_whiteboard_create(PurpleAccount *account, const char *who, int state)
 {
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleWhiteboard *wb = g_new0(PurpleWhiteboard, 1);
 
 	wb->account = account;
 	wb->state   = state;
 	wb->who     = g_strdup(who);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(
-				purple_account_get_connection(account)));
-	purple_whiteboard_set_prpl_ops(wb, prpl_info->whiteboard_prpl_ops);
+	protocol = purple_connection_get_protocol_info(purple_account_get_connection(account));
+	purple_whiteboard_set_protocol_ops(wb, protocol->whiteboard_protocol_ops);
 
 	/* Start up protocol specifics */
-	if(wb->prpl_ops && wb->prpl_ops->start)
-		wb->prpl_ops->start(wb);
+	if(wb->protocol_ops && wb->protocol_ops->start)
+		wb->protocol_ops->start(wb);
 
 	wbList = g_list_append(wbList, wb);
 
@@ -99,8 +98,8 @@
 	}
 
 	/* Do protocol specific session ending procedures */
-	if(wb->prpl_ops && wb->prpl_ops->end)
-		wb->prpl_ops->end(wb);
+	if(wb->protocol_ops && wb->protocol_ops->end)
+		wb->protocol_ops->end(wb);
 
 	g_free(wb->who);
 	wbList = g_list_remove(wbList, wb);
@@ -174,11 +173,11 @@
 
 gboolean purple_whiteboard_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
 {
-	PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops;
+	PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops;
 
-	if (prpl_ops && prpl_ops->get_dimensions)
+	if (protocol_ops && protocol_ops->get_dimensions)
 	{
-		prpl_ops->get_dimensions(wb, width, height);
+		protocol_ops->get_dimensions(wb, width, height);
 		return TRUE;
 	}
 
@@ -193,10 +192,10 @@
 
 void purple_whiteboard_send_draw_list(PurpleWhiteboard *wb, GList *list)
 {
-	PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops;
+	PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops;
 
-	if (prpl_ops && prpl_ops->send_draw_list)
-		prpl_ops->send_draw_list(wb, list);
+	if (protocol_ops && protocol_ops->send_draw_list)
+		protocol_ops->send_draw_list(wb, list);
 }
 
 void purple_whiteboard_draw_point(PurpleWhiteboard *wb, int x, int y, int color, int size)
@@ -219,27 +218,27 @@
 
 void purple_whiteboard_send_clear(PurpleWhiteboard *wb)
 {
-	PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops;
+	PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops;
 
-	if (prpl_ops && prpl_ops->clear)
-		prpl_ops->clear(wb);
+	if (protocol_ops && protocol_ops->clear)
+		protocol_ops->clear(wb);
 }
 
 void purple_whiteboard_send_brush(PurpleWhiteboard *wb, int size, int color)
 {
-	PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops;
+	PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops;
 
-	if (prpl_ops && prpl_ops->set_brush)
-		prpl_ops->set_brush(wb, size, color);
+	if (protocol_ops && protocol_ops->set_brush)
+		protocol_ops->set_brush(wb, size, color);
 }
 
 gboolean purple_whiteboard_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
 {
-	PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops;
+	PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops;
 
-	if (prpl_ops && prpl_ops->get_brush)
+	if (protocol_ops && protocol_ops->get_brush)
 	{
-		prpl_ops->get_brush(wb, size, color);
+		protocol_ops->get_brush(wb, size, color);
 		return TRUE;
 	}
 	return FALSE;
--- a/libpurple/whiteboard.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/libpurple/whiteboard.h	Sun Aug 18 01:53:00 2013 +0530
@@ -99,7 +99,7 @@
  * @param wb  The whiteboard for which to set the prpl operations
  * @param ops The prpl operations to set
  */
-void purple_whiteboard_set_prpl_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops);
+void purple_whiteboard_set_protocol_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops);
 
 /**
  * Creates a whiteboard
--- a/pidgin/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -168,6 +168,7 @@
 pidgin_LDADD = \
 	@LIBOBJS@ \
 	$(GLIB_LIBS) \
+	$(GPLUGIN_LIBS) \
 	$(GCR_LIBS) \
 	$(DBUS_LIBS) \
 	$(GSTREAMER_LIBS) \
@@ -197,6 +198,7 @@
 	-I$(top_builddir) \
 	-I$(top_srcdir) \
 	$(GLIB_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(GCR_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
 	$(GSTVIDEO_CFLAGS) \
--- a/pidgin/gtkaccount.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkaccount.c	Sun Aug 18 01:53:00 2013 +0530
@@ -32,9 +32,9 @@
 #include "core.h"
 #include "debug.h"
 #include "notify.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "prefs.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "savedstatuses.h"
 #include "signals.h"
@@ -98,8 +98,7 @@
 
 	PurpleAccount *account;
 	char *protocol_id;
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 
 	PurpleProxyType new_proxy_type;
 
@@ -203,14 +202,14 @@
 		pixbuf = pidgin_pixbuf_from_imgstore(dialog->icon_img);
 	}
 
-	if (pixbuf && dialog->prpl_info &&
-	    (dialog->prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY))
+	if (pixbuf && dialog->protocol &&
+	    (dialog->protocol->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY))
 	{
 		/* Scale the icon to something reasonable */
 		int width, height;
 		GdkPixbuf *scale;
 
-		pidgin_buddy_icon_get_scale_size(pixbuf, &dialog->prpl_info->icon_spec,
+		pidgin_buddy_icon_get_scale_size(pixbuf, &dialog->protocol->icon_spec,
 				PURPLE_ICON_SCALE_DISPLAY, &width, &height);
 		scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
 
@@ -235,19 +234,13 @@
 set_account_protocol_cb(GtkWidget *widget, const char *id,
 						AccountPrefsDialog *dialog)
 {
-	PurplePlugin *new_plugin;
-
-	new_plugin = purple_find_prpl(id);
-
-	dialog->plugin = new_plugin;
-
-	if (dialog->plugin != NULL)
-	{
-		dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
-
-		g_free(dialog->protocol_id);
-		dialog->protocol_id = g_strdup(dialog->plugin->info->id);
-	}
+	PurpleProtocol *new_protocol;
+
+	new_protocol = purple_find_protocol_info(id);
+
+	dialog->protocol = new_protocol;
+	g_free(dialog->protocol_id);
+	dialog->protocol_id = dialog->protocol ? g_strdup(dialog->protocol->id) : NULL;
 
 	if (dialog->account != NULL)
 		purple_account_clear_settings(dialog->account);
@@ -259,13 +252,13 @@
 
 	gtk_widget_grab_focus(dialog->protocol_menu);
 
-	if (!dialog->prpl_info || !dialog->prpl_info->register_user) {
+	if (!dialog->protocol || !dialog->protocol->register_user) {
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
 			dialog->register_button), FALSE);
 		gtk_widget_hide(dialog->register_button);
 	} else {
-		if (dialog->prpl_info != NULL &&
-		   (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)) {
+		if (dialog->protocol != NULL &&
+		   (dialog->protocol->options & OPT_PROTO_REGISTER_NOSCREENNAME)) {
 			gtk_widget_set_sensitive(dialog->register_button, TRUE);
 		} else {
 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
@@ -279,9 +272,9 @@
 static void
 username_changed_cb(GtkEntry *entry, AccountPrefsDialog *dialog)
 {
-	gboolean opt_noscreenname = (dialog->prpl_info != NULL &&
-		(dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME));
-	gboolean username_valid = purple_validate(dialog->plugin,
+	gboolean opt_noscreenname = (dialog->protocol != NULL &&
+		(dialog->protocol->options & OPT_PROTO_REGISTER_NOSCREENNAME));
+	gboolean username_valid = purple_validate(dialog->protocol,
 		gtk_entry_get_text(entry));
 
 	if (dialog->ok_button) {
@@ -310,12 +303,12 @@
 	GHashTable *table;
 	const char *label;
 
-	if (!dialog->prpl_info || ! PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(
-		dialog->prpl_info, get_account_text_table)) {
+	if (!dialog->protocol || ! PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(
+		dialog->protocol, get_account_text_table)) {
 		return FALSE;
 	}
 
-	table = dialog->prpl_info->get_account_text_table(NULL);
+	table = dialog->protocol->get_account_text_table(NULL);
 	label = g_hash_table_lookup(table, "login_label");
 
 	if(!strcmp(gtk_entry_get_text(GTK_ENTRY(widget)), label)) {
@@ -338,8 +331,8 @@
 	GHashTable *table = NULL;
 	const char *label = NULL;
 
-	if(PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, get_account_text_table)) {
-		table = dialog->prpl_info->get_account_text_table(NULL);
+	if(PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->protocol, get_account_text_table)) {
+		table = dialog->protocol->get_account_text_table(NULL);
 		label = g_hash_table_lookup(table, "login_label");
 
 		if (*gtk_entry_get_text(GTK_ENTRY(widget)) == '\0') {
@@ -378,7 +371,7 @@
 #endif
 	gint xsize;
 
-	table = dialog->prpl_info->get_account_text_table(NULL);
+	table = dialog->protocol->get_account_text_table(NULL);
 	label = g_hash_table_lookup(table, "login_label");
 	text = gtk_entry_get_text(GTK_ENTRY(widget));
 
@@ -446,8 +439,8 @@
 {
 	int register_checked = gtk_toggle_button_get_active(
 		GTK_TOGGLE_BUTTON(dialog->register_button));
-	int opt_noscreenname = (dialog->prpl_info != NULL &&
-		(dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME));
+	int opt_noscreenname = (dialog->protocol != NULL &&
+		(dialog->protocol->options & OPT_PROTO_REGISTER_NOSCREENNAME));
 	int register_noscreenname = (opt_noscreenname && register_checked);
 
 #if !GTK_CHECK_VERSION(3,2,0)
@@ -484,7 +477,7 @@
 	if (filename != NULL)
 	{
 		size_t len;
-		gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len);
+		gpointer data = pidgin_convert_buddy_icon(dialog->protocol, filename, &len);
 		set_dialog_icon(dialog, data, len, g_strdup(filename));
 	}
 
@@ -531,7 +524,7 @@
 			if ((rtmp = strchr(tmp, '\r')) || (rtmp = strchr(tmp, '\n')))
 				*rtmp = '\0';
 
-			data = pidgin_convert_buddy_icon(dialog->plugin, tmp, &len);
+			data = pidgin_convert_buddy_icon(dialog->protocol, tmp, &len);
 			/* This takes ownership of tmp */
 			set_dialog_icon(dialog, data, len, tmp);
 		}
@@ -629,11 +622,11 @@
 	if (dialog->account != NULL)
 		username = g_strdup(purple_account_get_username(dialog->account));
 
-	if (!username && dialog->prpl_info
-			&& PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, get_account_text_table)) {
+	if (!username && dialog->protocol
+			&& PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->protocol, get_account_text_table)) {
 		GHashTable *table;
 		const char *label;
-		table = dialog->prpl_info->get_account_text_table(NULL);
+		table = dialog->protocol->get_account_text_table(NULL);
 		label = g_hash_table_lookup(table, "login_label");
 
 #if GTK_CHECK_VERSION(3,2,0)
@@ -656,10 +649,10 @@
 					 G_CALLBACK(username_changed_cb), dialog);
 
 	/* Do the user split thang */
-	if (dialog->prpl_info == NULL)
+	if (dialog->protocol == NULL)
 		user_splits = NULL;
 	else
-		user_splits = dialog->prpl_info->user_splits;
+		user_splits = dialog->protocol->user_splits;
 
 	if (dialog->user_split_entries != NULL) {
 		g_list_free(dialog->user_split_entries);
@@ -748,8 +741,8 @@
 				purple_account_get_remember_password(dialog->account));
 	}
 
-	if (dialog->prpl_info != NULL &&
-		(dialog->prpl_info->options & OPT_PROTO_NO_PASSWORD)) {
+	if (dialog->protocol != NULL &&
+		(dialog->protocol->options & OPT_PROTO_NO_PASSWORD)) {
 
 		gtk_widget_hide(dialog->password_box);
 		gtk_widget_hide(dialog->remember_pass_check);
@@ -848,11 +841,11 @@
 	gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0);
 	gtk_widget_show(button);
 
-	if (dialog->prpl_info != NULL) {
-		if (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK))
+	if (dialog->protocol != NULL) {
+		if (!(dialog->protocol->options & OPT_PROTO_MAIL_CHECK))
 			gtk_widget_hide(dialog->new_mail_check);
 
-		if (dialog->prpl_info->icon_spec.format == NULL) {
+		if (dialog->protocol->icon_spec.format == NULL) {
 			gtk_widget_hide(dialog->icon_check);
 			gtk_widget_hide(dialog->icon_hbox);
 		}
@@ -887,9 +880,9 @@
 	}
 
 #if 0
-	if (!dialog->prpl_info ||
-			(!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) &&
-			 (dialog->prpl_info->icon_spec.format ==  NULL))) {
+	if (!dialog->protocol ||
+			(!(dialog->protocol->options & OPT_PROTO_MAIL_CHECK) &&
+			 (dialog->protocol->icon_spec.format ==  NULL))) {
 
 		/* Nothing to see :( aww. */
 		gtk_widget_hide(dialog->user_frame);
@@ -929,8 +922,8 @@
 		dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries);
 	}
 
-	if (dialog->prpl_info == NULL ||
-			dialog->prpl_info->protocol_options == NULL)
+	if (dialog->protocol == NULL ||
+			dialog->protocol->protocol_options == NULL)
 		return;
 
 	account = dialog->account;
@@ -942,7 +935,7 @@
 			gtk_label_new_with_mnemonic(_("Ad_vanced")), 1);
 	gtk_widget_show(vbox);
 
-	for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
+	for (l = dialog->protocol->protocol_options; l != NULL; l = l->next)
 	{
 		option = (PurpleAccountOption *)l->data;
 
@@ -1329,7 +1322,7 @@
 add_voice_options(AccountPrefsDialog *dialog)
 {
 #ifdef USE_VV
-	if (!dialog->prpl_info || !PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, initiate_media)) {
+	if (!dialog->protocol || !PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->protocol, initiate_media)) {
 		if (dialog->voice_frame) {
 			gtk_widget_destroy(dialog->voice_frame);
 			dialog->voice_frame = NULL;
@@ -1431,9 +1424,9 @@
 	/* Build the username string. */
 	username = g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->username_entry)));
 
-	if (dialog->prpl_info != NULL)
+	if (dialog->protocol != NULL)
 	{
-		for (l = dialog->prpl_info->user_splits,
+		for (l = dialog->protocol->user_splits,
 			 l2 = dialog->user_split_entries;
 			 l != NULL && l2 != NULL;
 			 l = l->next, l2 = l2->next)
@@ -1494,7 +1487,7 @@
 		purple_account_set_private_alias(account, NULL);
 
 	/* Buddy Icon */
-	if (dialog->prpl_info != NULL && dialog->prpl_info->icon_spec.format != NULL)
+	if (dialog->protocol != NULL && dialog->protocol->icon_spec.format != NULL)
 	{
 		const char *filename;
 
@@ -1524,7 +1517,7 @@
 		else if ((filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) && icon_change)
 		{
 			size_t len;
-			gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len);
+			gpointer data = pidgin_convert_buddy_icon(dialog->protocol, filename, &len);
 			purple_account_set_buddy_icon_path(account, filename);
 			purple_buddy_icons_set_account_icon(account, data, len);
 		}
@@ -1540,7 +1533,7 @@
 	purple_account_set_remember_password(account, remember);
 
 	/* Check Mail */
-	if (dialog->prpl_info && dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK)
+	if (dialog->protocol && dialog->protocol->options & OPT_PROTO_MAIL_CHECK)
 		purple_account_set_check_mail(account,
 			gtk_toggle_button_get_active(
 					GTK_TOGGLE_BUTTON(dialog->new_mail_check)));
@@ -1563,7 +1556,7 @@
 	g_free(username);
 
 	/* Add the protocol settings */
-	if (dialog->prpl_info) {
+	if (dialog->protocol) {
 		ProtocolOptEntry *opt_entry;
 		GtkTreeIter iter;
 		char *value2;
@@ -1732,10 +1725,10 @@
 	dialog->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
 	if (dialog->account == NULL) {
-		/* Select the first prpl in the list*/
-		GList *prpl_list = purple_plugins_get_protocols();
-		if (prpl_list != NULL)
-			dialog->protocol_id = g_strdup(((PurplePlugin *) prpl_list->data)->info->id);
+		/* Select the first protocol in the list*/
+		GList *protocol_list = purple_protocols_get_all();
+		if (protocol_list != NULL)
+			dialog->protocol_id = g_strdup(((PurpleProtocol *) protocol_list->data)->id);
 	}
 	else
 	{
@@ -1743,8 +1736,12 @@
 			g_strdup(purple_account_get_protocol_id(dialog->account));
 	}
 
-	if ((dialog->plugin = purple_find_prpl(dialog->protocol_id)) != NULL)
-		dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
+	/* TODO if no protocols are loaded, this should inform the user that
+	        protocols need to be loaded instead of just doing nothing */
+	if (!dialog->protocol_id)
+		return;
+
+	dialog->protocol = purple_find_protocol_info(dialog->protocol_id);
 
 	dialog->window = win = pidgin_create_dialog((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"),
 		PIDGIN_HIG_BOX_SPACE, "account", FALSE);
@@ -1779,7 +1776,7 @@
 	if (dialog->account == NULL)
 		gtk_widget_set_sensitive(button, FALSE);
 
-	if (!dialog->prpl_info || !dialog->prpl_info->register_user)
+	if (!dialog->protocol || !dialog->protocol->register_user)
 		gtk_widget_hide(button);
 
 	/* Setup the page with 'Advanced' (protocol options). */
@@ -1854,7 +1851,7 @@
 
 	if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index))
 	{
-		pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
+		pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
 		if ((pixbuf != NULL) && purple_account_is_disconnected(account))
 			gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
 
@@ -2243,17 +2240,14 @@
 {
 	GdkPixbuf *pixbuf, *buddyicon = NULL;
 	PurpleStoredImage *img = NULL;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
-
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
+	PurpleProtocol *protocol = NULL;
+
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
 	if ((pixbuf != NULL) && purple_account_is_disconnected(account))
 		gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	if (prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info != NULL && prpl_info->icon_spec.format != NULL) {
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+	if (protocol != NULL && protocol->icon_spec.format != NULL) {
 		if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) {
 			if (global_buddyicon != NULL)
 				buddyicon = g_object_ref(G_OBJECT(global_buddyicon));
@@ -2712,14 +2706,12 @@
 authorize_reason_cb(struct auth_request *ar)
 {
 	const char *protocol_id;
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	protocol_id = purple_account_get_protocol_id(ar->account);
-	if ((plugin = purple_find_prpl(protocol_id)) != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
-	if (prpl_info && (prpl_info->options & OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE)) {
+	protocol = purple_find_protocol_info(protocol_id);
+
+	if (protocol && (protocol->options & OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE)) {
 		/* Duplicate information because ar is freed by closing minidialog */
 		struct auth_request *aa = g_new0(struct auth_request, 1);
 		aa->auth_cb = ar->auth_cb;
@@ -2757,14 +2749,12 @@
 deny_reason_cb(struct auth_request *ar)
 {
 	const char *protocol_id;
-	PurplePlugin *plugin;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	protocol_id = purple_account_get_protocol_id(ar->account);
-	if ((plugin = purple_find_prpl(protocol_id)) != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
-	if (prpl_info && (prpl_info->options & OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE)) {
+	protocol = purple_find_protocol_info(protocol_id);
+
+	if (protocol && (protocol->options & OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE)) {
 		/* Duplicate information because ar is freed by closing minidialog */
 		struct auth_request *aa = g_new0(struct auth_request, 1);
 		aa->auth_cb = ar->auth_cb;
@@ -2820,7 +2810,7 @@
 	PurpleConnection *gc;
 	GtkWidget *alert;
 	PidginMiniDialog *dialog;
-	GdkPixbuf *prpl_icon;
+	GdkPixbuf *protocol_icon;
 	struct auth_request *aa;
 	const char *our_name;
 	gboolean have_valid_alias;
@@ -2859,7 +2849,7 @@
 	g_free(escaped_our_name);
 	g_free(escaped_message);
 
-	prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 
 	aa = g_new0(struct auth_request, 1);
 	aa->auth_cb = auth_cb;
@@ -2871,7 +2861,7 @@
 	aa->add_buddy_after_auth = !on_list;
 
 	alert = pidgin_make_mini_dialog_with_custom_icon(
-		gc, prpl_icon,
+		gc, protocol_icon,
 		_("Authorize buddy?"), NULL, aa,
 		_("Authorize"), authorize_reason_cb,
 		_("Deny"), deny_reason_cb,
--- a/pidgin/gtkblist.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkblist.c	Sun Aug 18 01:53:00 2013 +0530
@@ -32,9 +32,9 @@
 #include "core.h"
 #include "debug.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "prefs.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "request.h"
 #include "signals.h"
 #include "pidginstock.h"
@@ -322,7 +322,7 @@
 #ifdef USE_VV
 static void gtk_blist_menu_audio_call_cb(GtkWidget *w, PurpleBuddy *b)
 {
-	purple_prpl_initiate_media(purple_buddy_get_account(b),
+	purple_protocol_initiate_media(purple_buddy_get_account(b),
 		purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO);
 }
 
@@ -330,13 +330,13 @@
 {
 	/* if the buddy supports both audio and video, start a combined call,
 	 otherwise start a pure video session */
-	if (purple_prpl_get_media_caps(purple_buddy_get_account(b),
+	if (purple_protocol_get_media_caps(purple_buddy_get_account(b),
 			purple_buddy_get_name(b)) &
 			PURPLE_MEDIA_CAPS_AUDIO_VIDEO) {
-		purple_prpl_initiate_media(purple_buddy_get_account(b),
+		purple_protocol_initiate_media(purple_buddy_get_account(b),
 			purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO);
 	} else {
-		purple_prpl_initiate_media(purple_buddy_get_account(b),
+		purple_protocol_initiate_media(purple_buddy_get_account(b),
 			purple_buddy_get_name(b), PURPLE_MEDIA_VIDEO);
 	}
 }
@@ -384,18 +384,18 @@
 {
 	PurpleAccount *account;
 	PurpleConversation *conv;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	GHashTable *components;
 	const char *name;
 	char *chat_name;
 
 	account = purple_chat_get_account(chat);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 
 	components = purple_chat_get_components(chat);
 
-	if (prpl_info && prpl_info->get_chat_name)
-		chat_name = prpl_info->get_chat_name(components);
+	if (protocol && protocol->get_chat_name)
+		chat_name = protocol->get_chat_name(components);
 	else
 		chat_name = NULL;
 
@@ -671,7 +671,7 @@
 	purple_request_fields_add_group(fields, group);
 
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc);
+	parts = purple_connection_get_protocol_info(gc)->chat_info(gc);
 
 	for (iter = parts; iter; iter = iter->next) {
 		pce = iter->data;
@@ -748,12 +748,12 @@
 		account = purple_buddy_get_account(b);
 	} else if (PURPLE_IS_CHAT(node)) {
 		PurpleChat *c = PURPLE_CHAT(node);
-		PurplePluginProtocolInfo *prpl_info = NULL;
+		PurpleProtocol *protocol = NULL;
 		type = PURPLE_LOG_CHAT;
 		account = purple_chat_get_account(c);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
-		if (prpl_info && prpl_info->get_chat_name) {
-			name = prpl_info->get_chat_name(purple_chat_get_components(c));
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+		if (protocol && protocol->get_chat_name) {
+			name = protocol->get_chat_name(purple_chat_get_components(c));
 		}
 	} else if (PURPLE_IS_CONTACT(node)) {
 		pidgin_log_show_contact(PURPLE_CONTACT(node));
@@ -888,7 +888,7 @@
 static void
 set_sensitive_if_input_chat_cb(GtkWidget *entry, gpointer user_data)
 {
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleConnection *gc;
 	PidginChatData *data;
 	GList *tmp;
@@ -912,8 +912,8 @@
 	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(purple_connection_get_prpl(gc)) : NULL;
-	sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL);
+	protocol = (gc != NULL) ? purple_connection_get_protocol_info(gc) : NULL;
+	sensitive = (protocol != NULL && protocol->roomlist_get_list != NULL);
 
 	gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive);
 }
@@ -921,16 +921,16 @@
 static void
 set_sensitive_if_input_buddy_cb(GtkWidget *entry, gpointer user_data)
 {
-	PurplePlugin *prpl;
+	PurpleProtocol *protocol;
 	PidginAddBuddyData *data = user_data;
 	const char *text;
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(
 		data->rq_data.account));
 	text = gtk_entry_get_text(GTK_ENTRY(entry));
 
 	gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window),
-		GTK_RESPONSE_OK, purple_validate(prpl, text));
+		GTK_RESPONSE_OK, purple_validate(protocol, text));
 }
 
 static void
@@ -946,14 +946,14 @@
 chat_account_filter_func(PurpleAccount *account)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	if (gc == NULL)
 		return FALSE;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-
-	return (prpl_info->chat_info != NULL);
+	protocol = purple_connection_get_protocol_info(gc);
+
+	return (protocol->chat_info != NULL);
 }
 
 gboolean
@@ -1042,7 +1042,7 @@
 rebuild_chat_entries(PidginChatData *data, const char *default_chat_name)
 {
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	GList *list = NULL, *tmp;
 	GHashTable *defaults = NULL;
 	struct proto_chat_entry *pce;
@@ -1051,18 +1051,18 @@
 	g_return_if_fail(data->rq_data.account != NULL);
 
 	gc = purple_account_get_connection(data->rq_data.account);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+	protocol = purple_connection_get_protocol_info(gc);
 
 	gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL);
 
 	g_list_free(data->entries);
 	data->entries = NULL;
 
-	if (prpl_info->chat_info != NULL)
-		list = prpl_info->chat_info(gc);
-
-	if (prpl_info->chat_info_defaults != NULL)
-		defaults = prpl_info->chat_info_defaults(gc, default_chat_name);
+	if (protocol->chat_info != NULL)
+		list = protocol->chat_info(gc);
+
+	if (protocol->chat_info_defaults != NULL)
+		defaults = protocol->chat_info_defaults(gc, default_chat_name);
 
 	for (tmp = list; tmp; tmp = tmp->next)
 	{
@@ -1426,12 +1426,12 @@
                                       PurpleBlistNode *node)
 {
 	GList *l, *ll;
-	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-
-	if(!prpl_info || !prpl_info->blist_node_menu)
+	PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
+
+	if(!protocol || !protocol->blist_node_menu)
 		return;
 
-	for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) {
+	for(l = ll = protocol->blist_node_menu(node); l; l = l->next) {
 		PurpleMenuAction *act = (PurpleMenuAction *) l->data;
 		pidgin_append_menu_action(menu, act, node);
 	}
@@ -1482,7 +1482,7 @@
 pidgin_blist_make_buddy_menu(GtkWidget *menu, PurpleBuddy *buddy, gboolean sub) {
 	PurpleAccount *account = NULL;
 	PurpleConnection *pc = NULL;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleContact *contact;
 	PurpleBlistNode *node;
 	gboolean contact_expanded = FALSE;
@@ -1492,7 +1492,7 @@
 
 	account = purple_buddy_get_account(buddy);
 	pc = purple_account_get_connection(account);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(pc));
+	protocol = purple_connection_get_protocol_info(pc);
 
 	node = PURPLE_BLIST_NODE(buddy);
 
@@ -1502,7 +1502,7 @@
 		contact_expanded = node->contact_expanded;
 	}
 
-	if (prpl_info && prpl_info->get_info) {
+	if (protocol && protocol->get_info) {
 		pidgin_new_item_from_stock(menu, _("Get _Info"), PIDGIN_STOCK_TOOLBAR_USER_INFO,
 				G_CALLBACK(gtk_blist_menu_info_cb), buddy, 0, 0, NULL);
 	}
@@ -1510,10 +1510,10 @@
 			G_CALLBACK(gtk_blist_menu_im_cb), buddy, 0, 0, NULL);
 
 #ifdef USE_VV
-	if (prpl_info && prpl_info->get_media_caps) {
+	if (protocol && protocol->get_media_caps) {
 		PurpleAccount *account = purple_buddy_get_account(buddy);
 		const gchar *who = purple_buddy_get_name(buddy);
-		PurpleMediaCaps caps = purple_prpl_get_media_caps(account, who);
+		PurpleMediaCaps caps = purple_protocol_get_media_caps(account, who);
 		if (caps & PURPLE_MEDIA_CAPS_AUDIO) {
 			pidgin_new_item_from_stock(menu, _("_Audio Call"),
 				PIDGIN_STOCK_TOOLBAR_AUDIO_CALL,
@@ -1532,9 +1532,9 @@
 
 #endif
 
-	if (prpl_info && prpl_info->send_file) {
-		if (!prpl_info->can_receive_file ||
-			prpl_info->can_receive_file(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)))
+	if (protocol && protocol->send_file) {
+		if (!protocol->can_receive_file ||
+			protocol->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,
@@ -1859,7 +1859,7 @@
 					continue;
 
 				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);
+				buf = pidgin_create_protocol_icon(purple_buddy_get_account(buddy), PIDGIN_PROTOCOL_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),
@@ -1941,8 +1941,7 @@
 	PurpleBlistNode *node;
 	GtkTreeIter iter;
 	GtkTreeSelection *sel;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	struct _pidgin_blist_node *gtknode;
 	gboolean handled = FALSE;
 
@@ -1975,11 +1974,9 @@
 		else
 			b = (PurpleBuddy *)node;
 
-		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)
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(b)));
+
+		if (protocol && protocol->get_info)
 			pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(b)), purple_buddy_get_name(b));
 		handled = TRUE;
 	}
@@ -2104,7 +2101,7 @@
 }
 
 static void
-add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list,
+add_buddies_from_vcard(const char *protocol_id, PurpleGroup *group, GList *list,
 					   const char *alias)
 {
 	GList *l;
@@ -2119,7 +2116,7 @@
 		gc = (PurpleConnection *)l->data;
 		account = purple_connection_get_account(gc);
 
-		if (!strcmp(purple_account_get_protocol_id(account), prpl_id))
+		if (!strcmp(purple_account_get_protocol_id(account), protocol_id))
 			break;
 
 		account = NULL;
@@ -2318,7 +2315,7 @@
 		}
 
 		protocol =
-			PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->list_icon(purple_buddy_get_account(buddy),
+			purple_connection_get_protocol_info(gc)->list_icon(purple_buddy_get_account(buddy),
 														   buddy);
 
 		str = g_string_new(NULL);
@@ -2672,7 +2669,7 @@
 	PurpleAccount *account = NULL;
 	PurpleContact *contact = NULL;
 	PurpleStoredImage *custom_img;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	gint orig_width, orig_height, scale_width, scale_height;
 
 	if (PURPLE_IS_CONTACT(node)) {
@@ -2695,7 +2692,7 @@
 	}
 
 	if(account && purple_account_get_connection(account)) {
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
+		protocol = purple_connection_get_protocol_info(purple_account_get_connection(account));
 	}
 
 #if 0
@@ -2771,8 +2768,8 @@
 	scale_width = orig_width = gdk_pixbuf_get_width(buf);
 	scale_height = orig_height = gdk_pixbuf_get_height(buf);
 
-	if (prpl_info && prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY)
-		purple_buddy_icon_get_scale_size(&prpl_info->icon_spec, &scale_width, &scale_height);
+	if (protocol && protocol->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY)
+		purple_buddy_icon_get_scale_size(&protocol->icon_spec, &scale_width, &scale_height);
 
 	if (scaled || scale_height > 200 || scale_width > 200) {
 		GdkPixbuf *tmpbuf;
@@ -2837,14 +2834,14 @@
 #define TOOLTIP_BORDER 12
 #define SMALL_SPACE 6
 #define LARGE_SPACE 12
-#define PRPL_SIZE 16
+#define PROTOCOL_SIZE 16
 struct tooltip_data {
 	PangoLayout *layout;
 	PangoLayout *name_layout;
-	GdkPixbuf *prpl_icon;
+	GdkPixbuf *protocol_icon;
 	GdkPixbuf *status_icon;
 	GdkPixbuf *avatar;
-	gboolean avatar_is_prpl_icon;
+	gboolean avatar_is_protocol_icon;
 	int avatar_width;
 	int avatar_height;
 	int name_height;
@@ -2875,8 +2872,8 @@
 static struct tooltip_data * create_tip_for_account(PurpleAccount *account)
 {
 	struct tooltip_data *td = g_new0(struct tooltip_data, 1);
-	td->status_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
-		/* Yes, status_icon, not prpl_icon */
+	td->status_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
+		/* Yes, status_icon, not protocol_icon */
 	if (purple_account_is_disconnected(account))
 		gdk_pixbuf_saturate_and_pixelate(td->status_icon, td->status_icon, 0.0, FALSE);
 	td->layout = create_pango_layout(purple_account_get_username(account), &td->width, &td->height);
@@ -2900,7 +2897,7 @@
 	td->status_icon = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_LARGE);
 	td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE);
 	if (account != NULL) {
-		td->prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+		td->protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 	}
 	tooltip_text = pidgin_get_tooltip_text(node, full);
 	if (tooltip_text && *tooltip_text) {
@@ -2924,12 +2921,12 @@
 	g_free(tmp);
 
 	td->name_layout = create_pango_layout(node_name, &td->name_width, &td->name_height);
-	td->name_width += SMALL_SPACE + PRPL_SIZE;
-	td->name_height = MAX(td->name_height, PRPL_SIZE + SMALL_SPACE);
+	td->name_width += SMALL_SPACE + PROTOCOL_SIZE;
+	td->name_height = MAX(td->name_height, PROTOCOL_SIZE + SMALL_SPACE);
 #if 0  /* PRPL Icon as avatar */
 	if(!td->avatar && full) {
-		td->avatar = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE);
-		td->avatar_is_prpl_icon = TRUE;
+		td->avatar = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_LARGE);
+		td->avatar_is_protocol_icon = TRUE;
 	}
 #endif
 
@@ -2955,7 +2952,7 @@
 	int max_text_width;
 	int max_avatar_width;
 	GList *l;
-	int prpl_col = 0;
+	int protocol_col = 0;
 	GtkTextDirection dir = gtk_widget_get_direction(widget);
 	int status_size = 0;
 
@@ -2985,9 +2982,9 @@
 
 	max_width = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
 	if (dir == GTK_TEXT_DIR_RTL)
-		prpl_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE;
+		protocol_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE;
 	else
-		prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE;
+		protocol_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PROTOCOL_SIZE;
 
 	current_height = 12;
 	for(l = gtkblist->tooltipdata; l; l = l->next)
@@ -3054,10 +3051,10 @@
 			}
 		}
 
-		if (!td->avatar_is_prpl_icon && td->prpl_icon) {
-			gdk_cairo_set_source_pixbuf(cr, td->prpl_icon, prpl_col,
+		if (!td->avatar_is_protocol_icon && td->protocol_icon) {
+			gdk_cairo_set_source_pixbuf(cr, td->protocol_icon, protocol_col,
 			                            current_height +
-			                               (td->name_height - PRPL_SIZE) / 2);
+			                               (td->name_height - PROTOCOL_SIZE) / 2);
 			cairo_paint(cr);
 		}
 
@@ -3131,8 +3128,8 @@
 			g_object_unref(td->avatar);
 		if(td->status_icon)
 			g_object_unref(td->status_icon);
-		if(td->prpl_icon)
-			g_object_unref(td->prpl_icon);
+		if(td->protocol_icon)
+			g_object_unref(td->protocol_icon);
 		if (td->layout)
 			g_object_unref(td->layout);
 		if (td->name_layout)
@@ -3521,14 +3518,13 @@
 			PurpleConnection *gc = purple_account_get_connection(account);
 
 			if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) {
-				PurplePluginProtocolInfo *prpl_info =
-					PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+				PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
 				PurpleMood *mood = NULL;
 
 				/* PURPLE_CONNECTION_FLAG_SUPPORT_MOODS would not be set if the prpl doesn't
 				 * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary
 				 * here */
-				for (mood = prpl_info->get_moods(account) ;
+				for (mood = protocol->get_moods(account) ;
 				    mood->mood != NULL ; mood++) {
 					int mood_count =
 							GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));
@@ -3607,7 +3603,7 @@
 	PurpleRequestFieldGroup *g;
 	PurpleRequestField *f;
 	PurpleConnection *gc = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleMood *mood;
 	PurpleMood *global_moods = get_global_moods();
 
@@ -3615,8 +3611,8 @@
 		PurplePresence *presence = purple_account_get_presence(account);
 		PurpleStatus *status = purple_presence_get_status(presence, "mood");
 		gc = purple_account_get_connection(account);
-		g_return_if_fail(purple_connection_get_prpl(gc) != NULL);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		g_return_if_fail(purple_connection_get_protocol_info(gc) != NULL);
+		protocol = purple_connection_get_protocol_info(gc);
 		current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
 	} else {
 		current_mood = get_global_mood_status();
@@ -3632,8 +3628,8 @@
 
 	/* TODO: rlaager wants this sorted. */
 	/* TODO: darkrain wants it sorted post-translation */
-	if (account && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods))
-		mood = prpl_info->get_moods(account);
+	if (account && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_moods))
+		mood = protocol->get_moods(account);
 	else
 		mood = global_moods;
 	for ( ; mood->mood != NULL ; mood++) {
@@ -3804,8 +3800,7 @@
 static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full)
 {
 	GString *str = g_string_new("");
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	char *tmp;
 
 	if (PURPLE_IS_CHAT(node))
@@ -3819,8 +3814,7 @@
 		PidginBlistNode *bnode = purple_blist_node_get_ui_data(node);
 
 		chat = (PurpleChat *)node;
-		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_chat_get_account(chat)));
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_chat_get_account(chat)));
 
 		connections = purple_connections_get_all();
 		if (connections && connections->next)
@@ -3834,8 +3828,8 @@
 			conv = PURPLE_CHAT_CONVERSATION(bnode->conv.conv);
 		} else {
 			char *chat_name;
-			if (prpl_info && prpl_info->get_chat_name)
-				chat_name = prpl_info->get_chat_name(purple_chat_get_components(chat));
+			if (protocol && protocol->get_chat_name)
+				chat_name = protocol->get_chat_name(purple_chat_get_components(chat));
 			else
 				chat_name = g_strdup(purple_chat_get_name(chat));
 
@@ -3848,7 +3842,7 @@
 			g_string_append_printf(str, _("\n<b>Occupants:</b> %d"),
 					g_list_length(purple_chat_conversation_get_users(conv)));
 
-			if (prpl_info && (prpl_info->options & OPT_PROTO_CHAT_TOPIC)) {
+			if (protocol && (protocol->options & OPT_PROTO_CHAT_TOPIC)) {
 				const char *chattopic = purple_chat_conversation_get_topic(conv);
 				char *topic = chattopic ? g_markup_escape_text(chattopic, -1) : NULL;
 				g_string_append_printf(str, _("\n<b>Topic:</b> %s"), topic ? topic : _("(no topic set)"));
@@ -3856,8 +3850,8 @@
 			}
 		}
 
-		if (prpl_info && prpl_info->chat_info != NULL)
-			cur = prpl_info->chat_info(purple_account_get_connection(purple_chat_get_account(chat)));
+		if (protocol && protocol->chat_info != NULL)
+			cur = protocol->chat_info(purple_account_get_connection(purple_chat_get_account(chat)));
 		else
 			cur = NULL;
 
@@ -3908,8 +3902,7 @@
 			c = purple_buddy_get_contact(b);
 		}
 
-		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(b)));
 
 		presence = purple_buddy_get_presence(b);
 		user_info = purple_notify_user_info_new();
@@ -4018,10 +4011,10 @@
 		}
 
 		if (purple_account_is_connected(purple_buddy_get_account(b)) &&
-				prpl_info && prpl_info->tooltip_text)
+				protocol && protocol->tooltip_text)
 		{
 			/* Additional text from the PRPL */
-			prpl_info->tooltip_text(b, user_info, full);
+			protocol->tooltip_text(b, user_info, full);
 		}
 
 		/* These are Easter Eggs.  Patches to remove them will be rejected. */
@@ -4108,8 +4101,7 @@
 {
 	PurpleBuddy *buddy = NULL;
 	struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node);
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	const char *name = NULL;
 	char *filename, *path;
 	PurplePresence *p = NULL;
@@ -4133,7 +4125,7 @@
 		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(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PRPL_ICON_SMALL);
+			return pidgin_create_protocol_icon(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PROTOCOL_ICON_SMALL);
 		}
 	} else {
 		return NULL;
@@ -4177,13 +4169,12 @@
 		return _pidgin_blist_get_cached_emblem(path);
 	}
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(buddy)));
-	if (!prpl)
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(buddy)));
+	if (!protocol)
 		return NULL;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info && prpl_info->list_emblem)
-		name = prpl_info->list_emblem(buddy);
+	if (protocol->list_emblem)
+		name = protocol->list_emblem(buddy);
 
 	if (name == NULL) {
 		PurpleStatus *status;
@@ -4238,15 +4229,15 @@
 
 	if(buddy || chat) {
 		PurpleAccount *account;
-		PurplePlugin *prpl;
+		PurpleProtocol *protocol;
 
 		if(buddy)
 			account = purple_buddy_get_account(buddy);
 		else
 			account = purple_chat_get_account(chat);
 
-		prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-		if(!prpl)
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+		if(!protocol)
 			return NULL;
 	}
 
@@ -4329,8 +4320,7 @@
 {
 	const char *name, *name_color, *name_font, *status_color, *status_font;
 	char *text = NULL;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleContact *contact;
 	PurplePresence *presence;
 	struct _pidgin_blist_node *gtkcontactnode = NULL;
@@ -4379,13 +4369,10 @@
 	if (!aliased || biglist) {
 
 		/* Status Info */
-		prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b)));
-
-		if (prpl != NULL)
-			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-		if (prpl_info && prpl_info->status_text && purple_account_get_connection(purple_buddy_get_account(b))) {
-			char *tmp = prpl_info->status_text(b);
+		protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(b)));
+
+		if (protocol && protocol->status_text && purple_account_get_connection(purple_buddy_get_account(b))) {
+			char *tmp = protocol->status_text(b);
 			const char *end;
 
 			if(tmp && !g_utf8_validate(tmp, -1, &end)) {
@@ -5183,13 +5170,13 @@
 }
 
 static void
-pack_prpl_icon_start(GtkWidget *box,
+pack_protocol_icon_start(GtkWidget *box,
                      PurpleAccount *account)
 {
 	GdkPixbuf *pixbuf;
 	GtkWidget *image;
 
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 	if (pixbuf != NULL) {
 		image = gtk_image_new_from_pixbuf(pixbuf);
 		g_object_unref(pixbuf);
@@ -5449,7 +5436,7 @@
 	hbox = gtk_hbox_new(FALSE, 6);
 	g_object_set_data(G_OBJECT(hbox), OBJECT_DATA_KEY_ACCOUNT, account);
 
-	pack_prpl_icon_start(hbox, account);
+	pack_protocol_icon_start(hbox, account);
 
 	label = gtk_label_new(NULL);
 	markup = g_strdup_printf("<span size=\"smaller\">%s</span>", username);
@@ -6689,7 +6676,7 @@
 static void buddy_node(PurpleBuddy *buddy, GtkTreeIter *iter, PurpleBlistNode *node)
 {
 	PurplePresence *presence = purple_buddy_get_presence(buddy);
-	GdkPixbuf *status, *avatar, *emblem, *prpl_icon;
+	GdkPixbuf *status, *avatar, *emblem, *protocol_icon;
 	GdkColor *color = NULL;
 	char *mark;
 	char *idle = NULL;
@@ -6758,7 +6745,7 @@
 		}
 	}
 
-	prpl_icon = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL);
+	protocol_icon = pidgin_create_protocol_icon(purple_buddy_get_account(buddy), PIDGIN_PROTOCOL_ICON_SMALL);
 
 	if (theme != NULL)
 		color = pidgin_blist_theme_get_contact_color(theme);
@@ -6773,7 +6760,7 @@
 			   BUDDY_ICON_VISIBLE_COLUMN, biglist,
 			   EMBLEM_COLUMN, emblem,
 			   EMBLEM_VISIBLE_COLUMN, (emblem != NULL),
-			   PROTOCOL_ICON_COLUMN, prpl_icon,
+			   PROTOCOL_ICON_COLUMN, protocol_icon,
 			   PROTOCOL_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"),
 			   BGCOLOR_COLUMN, color,
 			   CONTACT_EXPANDER_COLUMN, NULL,
@@ -6789,8 +6776,8 @@
 		g_object_unref(status);
 	if(avatar)
 		g_object_unref(avatar);
-	if(prpl_icon)
-		g_object_unref(prpl_icon);
+	if(protocol_icon)
+		g_object_unref(protocol_icon);
 }
 
 /* This is a variation on the original gtk_blist_update_contact. Here we
@@ -6939,7 +6926,7 @@
 
 	if(purple_account_is_connected(purple_chat_get_account(chat))) {
 		GtkTreeIter iter;
-		GdkPixbuf *status, *avatar, *emblem, *prpl_icon;
+		GdkPixbuf *status, *avatar, *emblem, *protocol_icon;
 		const gchar *color, *font;
 		gchar *mark, *tmp;
 		gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
@@ -7001,7 +6988,7 @@
 		g_free(mark);
 		mark = tmp;
 
-		prpl_icon = pidgin_create_prpl_icon(purple_chat_get_account(chat), PIDGIN_PRPL_ICON_SMALL);
+		protocol_icon = pidgin_create_protocol_icon(purple_chat_get_account(chat), PIDGIN_PROTOCOL_ICON_SMALL);
 
 		if (theme != NULL)
 			bgcolor = pidgin_blist_theme_get_contact_color(theme);
@@ -7013,7 +7000,7 @@
 				BUDDY_ICON_VISIBLE_COLUMN, showicons,
 				EMBLEM_COLUMN, emblem,
 				EMBLEM_VISIBLE_COLUMN, emblem != NULL,
-				PROTOCOL_ICON_COLUMN, prpl_icon,
+				PROTOCOL_ICON_COLUMN, protocol_icon,
 				PROTOCOL_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"),
 				NAME_COLUMN, mark,
 				BGCOLOR_COLUMN, bgcolor,
@@ -7027,8 +7014,8 @@
 			g_object_unref(status);
 		if(avatar)
 			g_object_unref(avatar);
-		if(prpl_icon)
-			g_object_unref(prpl_icon);
+		if(protocol_icon)
+			g_object_unref(protocol_icon);
 
 	} else {
 		pidgin_blist_hide_node(list, node, TRUE);
@@ -7166,8 +7153,7 @@
 							PidginAddBuddyData *data)
 {
 	PurpleConnection *pc = NULL;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	gboolean invite_enabled = TRUE;
 
 	/* Save our account */
@@ -7176,10 +7162,8 @@
 	if (account)
 		pc = purple_account_get_connection(account);
 	if (pc)
-		prpl = purple_connection_get_prpl(pc);
-	if (prpl)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info && !(prpl_info->options & OPT_PROTO_INVITE_MESSAGE))
+		protocol = purple_connection_get_protocol_info(pc);
+	if (protocol && !(protocol->options & OPT_PROTO_INVITE_MESSAGE))
 		invite_enabled = FALSE;
 
 	gtk_widget_set_sensitive(data->entry_for_invite, invite_enabled);
@@ -7429,13 +7413,13 @@
 	GList *l;
 	PurpleConnection *gc;
 	GtkBox *vbox;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	if (account != NULL) {
 		gc = purple_account_get_connection(account);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-
-		if (prpl_info->join_chat == NULL) {
+		protocol = purple_connection_get_protocol_info(gc);
+
+		if (protocol->join_chat == NULL) {
 			purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL);
 			return;
 		}
@@ -7443,9 +7427,9 @@
 		/* 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 (prpl_info->join_chat != NULL) {
+			protocol = purple_connection_get_protocol_info(gc);
+
+			if (protocol->join_chat != NULL) {
 				account = purple_connection_get_account(gc);
 				break;
 			}
@@ -8124,21 +8108,24 @@
 
 static void
 build_plugin_actions(GtkActionGroup *action_group, GString *ui, char *parent,
-		PurplePlugin *plugin, gpointer context)
+		PurplePlugin *plugin)
 {
 	GtkAction *menuaction;
+	PurplePluginGetActionsCallback get_actions;
 	PurplePluginAction *action = NULL;
 	GList *actions, *l;
 	char *name;
 	int count = 0;
 
-	actions = PURPLE_PLUGIN_ACTIONS(plugin, context);
+	get_actions =
+		purple_plugin_info_get_actions_callback(purple_plugin_get_info(plugin));
+
+	actions = get_actions(plugin);
 
 	for (l = actions; l != NULL; l = l->next) {
 		if (l->data) {
 			action = (PurplePluginAction *)l->data;
 			action->plugin = plugin;
-			action->context = context;
 
 			name = g_strdup_printf("%s-action-%d", parent, count++);
 			menuaction = gtk_action_new(name, action->label, NULL, NULL);
@@ -8186,6 +8173,13 @@
 	purple_account_set_enabled(account, PIDGIN_UI, FALSE);
 }
 
+static void
+protocol_act(GtkWidget *obj, PurpleProtocolAction *pam)
+{
+	if (pam && pam->callback)
+		pam->callback(pam);
+}
+
 void
 pidgin_blist_update_accounts_menu(void)
 {
@@ -8234,7 +8228,7 @@
 			menuitem = gtk_image_menu_item_new_with_label(buf);
 			g_free(buf);
 
-			pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+			pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 			if (pixbuf != NULL) {
 				if (!purple_account_is_connected(account))
 					gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
@@ -8267,8 +8261,7 @@
 		PurpleConnection *gc = NULL;
 		PurpleAccount *account = NULL;
 		GdkPixbuf *pixbuf = NULL;
-		PurplePlugin *plugin = NULL;
-		PurplePluginProtocolInfo *prpl_info;
+		PurpleProtocol *protocol;
 
 		account = accounts->data;
 
@@ -8281,7 +8274,7 @@
 		accel_path_buf = g_strconcat("<Actions>/AccountActions/", buf, NULL);
 		g_free(buf);
 
-		pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+		pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 		if (pixbuf != NULL) {
 			if (!purple_account_is_connected(account))
 				gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf,
@@ -8308,13 +8301,13 @@
 		pidgin_separator(submenu);
 
 		gc = purple_account_get_connection(account);
-		plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? purple_connection_get_prpl(gc) : NULL;
-		prpl_info = plugin ? PURPLE_PLUGIN_PROTOCOL_INFO(plugin) : NULL;
-
-		if (prpl_info &&
-		    (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) ||
-			 PURPLE_PLUGIN_HAS_ACTIONS(plugin))) {
-			if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) &&
+		protocol = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ?
+				purple_connection_get_protocol_info(gc) : NULL;
+
+		if (protocol &&
+		    (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_moods) ||
+			 PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_actions))) {
+			if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_moods) &&
 			    (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) {
 
 				if (purple_account_get_status(account, "mood")) {
@@ -8325,29 +8318,28 @@
 				}
 			}
 
-			if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
+			if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_actions)) {
 				GtkWidget *menuitem;
-				PurplePluginAction *action = NULL;
+				PurpleProtocolAction *action = NULL;
 				GList *actions, *l;
 
-				actions = PURPLE_PLUGIN_ACTIONS(plugin, gc);
+				actions = protocol->get_actions(gc);
 
 				for (l = actions; l != NULL; l = l->next)
 				{
 					if (l->data)
 					{
-						action = (PurplePluginAction *) l->data;
-						action->plugin = plugin;
-						action->context = gc;
+						action = (PurpleProtocolAction *) l->data;
+						action->connection = gc;
 
 						menuitem = gtk_menu_item_new_with_label(action->label);
 						gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
 
 						g_signal_connect(G_OBJECT(menuitem), "activate",
-								G_CALLBACK(plugin_act), action);
-						g_object_set_data_full(G_OBJECT(menuitem), "plugin_action",
+								G_CALLBACK(protocol_act), action);
+						g_object_set_data_full(G_OBJECT(menuitem), "protocol_action",
 											   action,
-											   (GDestroyNotify)purple_plugin_action_free);
+											   (GDestroyNotify)purple_protocol_action_free);
 						gtk_widget_show(menuitem);
 					}
 					else
@@ -8380,6 +8372,7 @@
 pidgin_blist_update_plugin_actions(void)
 {
 	PurplePlugin *plugin = NULL;
+	PurplePluginInfo *info;
 	GList *l;
 
 	GtkAction *action;
@@ -8408,19 +8401,17 @@
 		char *name;
 
 		plugin = (PurplePlugin *)l->data;
-
-		if (PURPLE_IS_PROTOCOL_PLUGIN(plugin))
-			continue;
-
-		if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin))
+		info = purple_plugin_get_info(plugin);
+
+		if (!purple_plugin_info_get_actions_callback(info))
 			continue;
 
 		name = g_strdup_printf("plugin%d", count);
-		action = gtk_action_new(name, plugin->info->name, NULL, NULL);
+		action = gtk_action_new(name, purple_plugin_info_get_name(info), NULL, NULL);
 		gtk_action_group_add_action(plugins_action_group, action);
 		g_string_append_printf(plugins_ui, "<menu action='%s'>", name);
 
-		build_plugin_actions(plugins_action_group, plugins_ui, name, plugin, NULL);
+		build_plugin_actions(plugins_action_group, plugins_ui, name, plugin);
 
 		g_string_append(plugins_ui, "</menu>");
 		count++;
--- a/pidgin/gtkconv-theme-loader.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkconv-theme-loader.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,6 +26,7 @@
 
 #include "xmlnode.h"
 #include "debug.h"
+#include "prefs.h"
 
 /*****************************************************************************
  * Conversation Theme Builder
--- a/pidgin/gtkconv.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkconv.c	Sun Aug 18 01:53:00 2013 +0530
@@ -43,7 +43,8 @@
 #include "imgstore.h"
 #include "log.h"
 #include "notify.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "request.h"
 #include "theme-loader.h"
 #include "theme-manager.h"
@@ -186,7 +187,7 @@
 static GList *busy_list = NULL;
 static GList *xa_list = NULL;
 static GList *offline_list = NULL;
-static GHashTable *prpl_lists = NULL;
+static GHashTable *protocol_lists = NULL;
 
 static PurpleTheme *default_conv_theme = NULL;
 
@@ -384,7 +385,9 @@
 		const GList *plugins = purple_plugins_get_loaded();
 		if (plugins) {
 			for (; plugins; plugins = plugins->next) {
-				str = g_string_append(str, purple_plugin_get_name(plugins->data));
+				PurplePluginInfo *info = purple_plugin_get_info(PURPLE_PLUGIN(plugins->data));
+				str = g_string_append(str, purple_plugin_info_get_name(info));
+
 				if (plugins->next)
 					str = g_string_append(str, ", ");
 			}
@@ -552,13 +555,13 @@
 				break;
 			case PURPLE_CMD_STATUS_NOT_FOUND:
 				{
-					PurplePluginProtocolInfo *prpl_info = NULL;
+					PurpleProtocol *protocol = NULL;
 					PurpleConnection *gc;
 
 					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)) {
+						protocol = purple_connection_get_protocol_info(gc);
+
+					if ((protocol != NULL) && (protocol->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
 						char *spaceslash;
 
 						/* If the first word in the entered text has a '/' in it, then the user
@@ -595,7 +598,7 @@
 							PURPLE_MESSAGE_NO_LOG, time(NULL));
 				retval = TRUE;
 				break;
-			case PURPLE_CMD_STATUS_WRONG_PRPL:
+			case PURPLE_CMD_STATUS_WRONG_PROTOCOL:
 				purple_conversation_write(conv, "", _("That command doesn't work on this protocol."),
 						PURPLE_MESSAGE_NO_LOG, time(NULL));
 				retval = TRUE;
@@ -1184,7 +1187,7 @@
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
 	PurpleAccount *account = purple_conversation_get_account(conv);
 
-	purple_prpl_initiate_media(account,
+	purple_protocol_initiate_media(account,
 			purple_conversation_get_name(conv),
 			action == win->menu.audio_call ? PURPLE_MEDIA_AUDIO :
 			action == win->menu.video_call ? PURPLE_MEDIA_VIDEO :
@@ -1217,7 +1220,7 @@
 			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_protocol_send_attention(purple_conversation_get_connection(conv),
 			purple_conversation_get_name(conv), index);
 	}
 }
@@ -1474,7 +1477,7 @@
 	PurpleConversation *conv = gtkconv->active_conv;
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	gchar *real_who = NULL;
 
 	account = purple_conversation_get_account(conv);
@@ -1483,10 +1486,10 @@
 	gc = purple_account_get_connection(account);
 	g_return_if_fail(gc != NULL);
 
-	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,
+	protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && protocol->get_cb_real_name)
+		real_who = protocol->get_cb_real_name(gc,
 				purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), who);
 
 	if(!who && !real_who)
@@ -1529,7 +1532,7 @@
 static void
 menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv)
 {
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleConversation *conv = gtkconv->active_conv;
 	const char *who = g_object_get_data(G_OBJECT(w), "user_data");
 	PurpleConnection *gc  = purple_conversation_get_connection(conv);
@@ -1537,10 +1540,10 @@
 
 	g_return_if_fail(gc != NULL);
 
-	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,
+	protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol && protocol->get_cb_real_name)
+		real_who = protocol->get_cb_real_name(gc,
 				purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), who);
 
 	serv_send_file(gc, real_who ? real_who : who, NULL);
@@ -1628,7 +1631,7 @@
 create_chat_menu(PurpleChatConversation *chat, const char *who, PurpleConnection *gc)
 {
 	static GtkWidget *menu = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConversation *conv = PURPLE_CONVERSATION(chat);
 	PurpleAccount *account = purple_conversation_get_account(conv);
 	gboolean is_me = FALSE;
@@ -1636,7 +1639,7 @@
 	PurpleBuddy *buddy = NULL;
 
 	if (gc != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = purple_connection_get_protocol_info(gc);
 
 	/*
 	 * If a menu already exists, destroy it before creating a new one,
@@ -1660,7 +1663,7 @@
 			g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
 
 
-		if (prpl_info && prpl_info->send_file)
+		if (protocol && protocol->send_file)
 		{
 			gboolean can_receive_file = TRUE;
 
@@ -1668,14 +1671,14 @@
 				PIDGIN_STOCK_TOOLBAR_SEND_FILE, G_CALLBACK(menu_chat_send_file_cb),
 				PIDGIN_CONVERSATION(conv), 0, 0, NULL);
 
-			if (gc == NULL || prpl_info == NULL)
+			if (gc == NULL || protocol == NULL)
 				can_receive_file = FALSE;
 			else {
 				gchar *real_who = NULL;
-				if (prpl_info->get_cb_real_name)
-					real_who = prpl_info->get_cb_real_name(gc,
+				if (protocol->get_cb_real_name)
+					real_who = protocol->get_cb_real_name(gc,
 						purple_chat_conversation_get_id(chat), who);
-				if (!(!prpl_info->can_receive_file || prpl_info->can_receive_file(gc, real_who ? real_who : who)))
+				if (!(!protocol->can_receive_file || protocol->can_receive_file(gc, real_who ? real_who : who)))
 					can_receive_file = FALSE;
 				g_free(real_who);
 			}
@@ -1700,7 +1703,7 @@
 			g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
 	}
 
-	if (prpl_info && (prpl_info->get_info || prpl_info->get_cb_info)) {
+	if (protocol && (protocol->get_info || protocol->get_cb_info)) {
 		button = pidgin_new_item_from_stock(menu, _("Info"), PIDGIN_STOCK_TOOLBAR_USER_INFO,
 						G_CALLBACK(menu_chat_info_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
 
@@ -1710,7 +1713,7 @@
 			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 (!is_me && protocol && !(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 		if ((buddy = purple_blist_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);
@@ -2450,21 +2453,21 @@
  * A bunch of buddy icon functions
  **************************************************************************/
 
-static GList *get_prpl_icon_list(PurpleAccount *account)
+static GList *get_protocol_icon_list(PurpleAccount *account)
 {
 	GList *l = NULL;
-	PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	const char *prplname = prpl_info->list_icon(account, NULL);
-	l = g_hash_table_lookup(prpl_lists, prplname);
+	PurpleProtocol *protocol =
+			purple_find_protocol_info(purple_account_get_protocol_id(account));
+	const char *prplname = protocol->list_icon(account, NULL);
+	l = g_hash_table_lookup(protocol_lists, prplname);
 	if (l)
 		return l;
 
-	l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE));
-	l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM));
-	l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL));
-
-	g_hash_table_insert(prpl_lists, g_strdup(prplname), l);
+	l = g_list_prepend(l, pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_LARGE));
+	l = g_list_prepend(l, pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM));
+	l = g_list_prepend(l, pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL));
+
+	g_hash_table_insert(protocol_lists, g_strdup(prplname), l);
 	return l;
 }
 
@@ -2501,7 +2504,7 @@
 		}
 	}
 
-	return get_prpl_icon_list(account);
+	return get_protocol_icon_list(account);
 }
 
 static const char *
@@ -2622,7 +2625,7 @@
 		g_object_unref(emblem);
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) {
-		emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL);
+		emblem = pidgin_create_protocol_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PROTOCOL_ICON_SMALL);
 	} else {
 		emblem = NULL;
 	}
@@ -3269,11 +3272,11 @@
 		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));
-			PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+			PurpleProtocol *protocol =
+					purple_find_protocol_info(purple_account_get_protocol_id(account));
 			if (purple_account_get_connection(account) != NULL &&
-					PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_info_defaults)) {
-				components = prpl_info->chat_info_defaults(purple_account_get_connection(account),
+					PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, chat_info_defaults)) {
+				components = protocol->chat_info_defaults(purple_account_get_connection(account),
 						purple_conversation_get_name(conv));
 			} else {
 				components = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -3359,7 +3362,7 @@
 	 */
 	if (account != NULL && PURPLE_IS_IM_CONVERSATION(conv)) {
 		PurpleMediaCaps caps =
-				purple_prpl_get_media_caps(account,
+				purple_protocol_get_media_caps(account,
 				purple_conversation_get_name(conv));
 
 		gtk_action_set_sensitive(win->menu.audio_call,
@@ -3391,8 +3394,7 @@
 	GtkWidget *menu;
 	PurpleConversation *conv;
 	PurpleConnection *pc;
-	PurplePlugin *prpl = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	GList *list;
 
 	conv = pidgin_conv_window_get_active_conversation(win);
@@ -3407,12 +3409,10 @@
 
 	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));
+		protocol = purple_connection_get_protocol_info(pc);
+
+	if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_attention_types)) {
+		list = protocol->get_attention_types(purple_connection_get_account(pc));
 
 		/* Multiple attention types */
 		if (list && list->next) {
@@ -3922,7 +3922,7 @@
 	gchar *text;
 
 	/* Create a pixmap for the protocol icon. */
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 
 	/* Now convert it to GtkImage */
 	if (pixbuf == NULL)
@@ -4128,7 +4128,7 @@
 	PurpleConversation *conv;
 	PidginChatPane *gtkchat;
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	GtkTreeModel *tm;
 	GtkListStore *ls;
 	GtkTreePath *newpath;
@@ -4150,7 +4150,7 @@
 	gtkchat = gtkconv->u.chat;
 	gc      = purple_conversation_get_connection(conv);
 
-	if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
+	if (!gc || !(protocol = purple_connection_get_protocol_info(gc)))
 		return;
 
 	tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
@@ -4455,7 +4455,7 @@
 
 static void topic_callback(GtkWidget *w, PidginConversation *gtkconv)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConnection *gc;
 	PurpleConversation *conv = gtkconv->active_conv;
 	PidginChatPane *gtkchat;
@@ -4464,10 +4464,10 @@
 
 	gc      = purple_conversation_get_connection(conv);
 
-	if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))))
+	if(!gc || !(protocol = purple_connection_get_protocol_info(gc)))
 		return;
 
-	if(prpl_info->set_chat_topic == NULL)
+	if(protocol->set_chat_topic == NULL)
 		return;
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
@@ -4485,7 +4485,7 @@
 	else
 		gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), "");
 
-	prpl_info->set_chat_topic(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)),
+	protocol->set_chat_topic(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)),
 			new_topic);
 
 	g_free(new_topic);
@@ -4535,7 +4535,7 @@
 }
 
 static void
-update_chat_alias(PurpleBuddy *buddy, PurpleChatConversation *chat, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info)
+update_chat_alias(PurpleBuddy *buddy, PurpleChatConversation *chat, PurpleConnection *gc, PurpleProtocol *protocol)
 {
 	PidginConversation *gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat));
 	PurpleAccount *account = purple_conversation_get_account(PURPLE_CONVERSATION(chat));
@@ -4599,7 +4599,7 @@
 blist_node_aliased_cb(PurpleBlistNode *node, const char *old_alias, PurpleChatConversation *chat)
 {
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleConversation *conv = PURPLE_CONVERSATION(chat);
 
 	g_return_if_fail(node != NULL);
@@ -4607,10 +4607,10 @@
 
 	gc = purple_conversation_get_connection(conv);
 	g_return_if_fail(gc != NULL);
-	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)
+	g_return_if_fail(purple_connection_get_protocol_info(gc) != NULL);
+	protocol = purple_connection_get_protocol_info(gc);
+
+	if (protocol->options & OPT_PROTO_UNIQUE_CHATNAME)
 		return;
 
 	if (PURPLE_IS_CONTACT(node))
@@ -4622,11 +4622,11 @@
 			if(!PURPLE_IS_BUDDY(bnode))
 				continue;
 
-			update_chat_alias((PurpleBuddy *)bnode, chat, gc, prpl_info);
+			update_chat_alias((PurpleBuddy *)bnode, chat, gc, protocol);
 		}
 	}
 	else if (PURPLE_IS_BUDDY(node))
-		update_chat_alias((PurpleBuddy *)node, chat, gc, prpl_info);
+		update_chat_alias((PurpleBuddy *)node, chat, gc, protocol);
 	else if (PURPLE_IS_CHAT(node) &&
 			purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node))
 	{
@@ -4832,8 +4832,8 @@
 {
 	PurpleConversation *conv = gtkconv->active_conv;
 	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)
+	PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
+	if (protocol->options & OPT_PROTO_CHAT_TOPIC)
 	{
 		GtkWidget *hbox, *label;
 		PidginChatPane *gtkchat = gtkconv->u.chat;
@@ -4847,7 +4847,7 @@
 		gtkchat->topic_text = gtk_entry_new();
 		gtk_widget_set_size_request(gtkchat->topic_text, -1, BUDDYICON_SIZE_MIN);
 
-		if(prpl_info->set_chat_topic == NULL) {
+		if(protocol->set_chat_topic == NULL) {
 			gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE);
 		} else {
 			g_signal_connect(G_OBJECT(gtkchat->topic_text), "activate",
@@ -4869,7 +4869,7 @@
 	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list));
 	PurpleConversation *conv = gtkconv->active_conv;
 	PurpleBlistNode *node;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleProtocol *protocol;
 	PurpleAccount *account = purple_conversation_get_account(conv);
 	char *who = NULL;
 
@@ -4881,9 +4881,9 @@
 
 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account)));
+	protocol = purple_connection_get_protocol_info(purple_account_get_connection(account));
 	node = (PurpleBlistNode*)(purple_blist_find_buddy(purple_conversation_get_account(conv), who));
-	if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME))
+	if (node && protocol && (protocol->options & OPT_PROTO_UNIQUE_CHATNAME))
 		pidgin_blist_draw_tooltip(node, gtkconv->infopane);
 
 	g_free(who);
@@ -5513,7 +5513,7 @@
 	PurpleIMConversation *im;
 	PurpleAccount *convaccount = purple_conversation_get_account(conv);
 	PurpleConnection *gc = purple_account_get_connection(convaccount);
-	PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
+	PurpleProtocol *protocol = gc ? purple_connection_get_protocol_info(gc) : NULL;
 	const guchar *data = gtk_selection_data_get_data(sd);
 
 	if (info == PIDGIN_DRAG_BLIST_NODE)
@@ -5540,7 +5540,7 @@
 		 * invite him to the chat.
 		 */
 		if (PURPLE_IS_CHAT_CONVERSATION(conv) &&
-				prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) &&
+				protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, chat_invite) &&
 				strcmp(purple_account_get_protocol_id(convaccount),
 					purple_account_get_protocol_id(buddyaccount)) == 0) {
 		    purple_chat_conversation_invite_user(PURPLE_CHAT_CONVERSATION(conv), buddyname, NULL, TRUE);
@@ -5577,13 +5577,13 @@
 	}
 	else if (info == PIDGIN_DRAG_IM_CONTACT)
 	{
-		char *protocol = NULL;
+		char *protocol_id = NULL;
 		char *username = NULL;
 		PurpleAccount *account;
 		PidginConversation *gtkconv;
 
 		if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account,
-						&protocol, &username, NULL))
+						&protocol_id, &username, NULL))
 		{
 			if (account == NULL)
 			{
@@ -5596,8 +5596,8 @@
 				 * invite him to the chat.
 				 */
 				if (PURPLE_IS_CHAT_CONVERSATION(conv) &&
-						prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) &&
-						strcmp(purple_account_get_protocol_id(convaccount), protocol) == 0) {
+						protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, chat_invite) &&
+						strcmp(purple_account_get_protocol_id(convaccount), protocol_id) == 0) {
 					purple_chat_conversation_invite_user(PURPLE_CHAT_CONVERSATION(conv), username, NULL, TRUE);
 				} else {
 					im = purple_im_conversation_new(account, username);
@@ -5611,7 +5611,7 @@
 		}
 
 		g_free(username);
-		g_free(protocol);
+		g_free(protocol_id);
 
 		gtk_drag_finish(dc, TRUE,
 		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
@@ -6527,7 +6527,7 @@
 		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(purple_conversation_get_account(conv))))->options &
+	if (purple_find_protocol_info(purple_account_get_protocol_id(purple_conversation_get_account(conv)))->options &
 	    OPT_PROTO_USE_POINTSIZE) {
 		gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
 	}
@@ -7127,7 +7127,7 @@
 	PidginWindow *win;
 	PurpleConversation *conv = gtkconv->active_conv;
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	GdkPixbuf *window_icon = NULL;
 	GtkWebViewButtons buttons;
 	PurpleAccount *account;
@@ -7137,7 +7137,7 @@
 	account = purple_conversation_get_account(conv);
 
 	if (gc != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = purple_connection_get_protocol_info(gc);
 
 	if (win->menu.send_to != NULL)
 		update_send_to_selection(win);
@@ -7234,7 +7234,7 @@
 			buttons = GTK_WEBVIEW_SMILEY | GTK_WEBVIEW_IMAGE;
 		}
 
-		if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)
+		if (!(protocol->options & OPT_PROTO_IM_IMAGE)
 		 && !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES)) {
 			features |= PURPLE_CONNECTION_FLAG_NO_IMAGES;
 			purple_conversation_set_features(conv, features);
@@ -7255,27 +7255,27 @@
 		/* Deal with menu items */
 		gtk_action_set_sensitive(win->menu.view_log, TRUE);
 		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.get_info, (protocol->get_info != NULL));
+		gtk_action_set_sensitive(win->menu.invite, (protocol->chat_invite != NULL));
 		gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_FLAG_HTML));
 		gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES));
 
 		if (PURPLE_IS_IM_CONVERSATION(conv))
 		{
-			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.add, (protocol->add_buddy != NULL));
+			gtk_action_set_sensitive(win->menu.remove, (protocol->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(win->menu.get_attention, (prpl_info->send_attention != NULL));
+									 (protocol->send_file != NULL && (!protocol->can_receive_file ||
+									  protocol->can_receive_file(gc, purple_conversation_get_name(conv)))));
+			gtk_action_set_sensitive(win->menu.get_attention, (protocol->send_attention != NULL));
 			gtk_action_set_sensitive(win->menu.alias,
 									 (account != NULL) &&
 									 (purple_blist_find_buddy(account, purple_conversation_get_name(conv)) != NULL));
 		}
 		else
 		{
-			gtk_action_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL));
-			gtk_action_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL));
+			gtk_action_set_sensitive(win->menu.add, (protocol->join_chat != NULL));
+			gtk_action_set_sensitive(win->menu.remove, (protocol->join_chat != NULL));
 			gtk_action_set_sensitive(win->menu.alias,
 									 (account != NULL) &&
 									 (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL));
@@ -8186,10 +8186,10 @@
 			GHashTable *comps = NULL;
 			PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv));
 			if (chat == NULL) {
-				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+				PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
 				
-				if (prpl_info->chat_info_defaults != NULL)
-					comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv));
+				if (protocol->chat_info_defaults != NULL)
+					comps = protocol->chat_info_defaults(gc, purple_conversation_get_name(conv));
 			} else {
 				comps = purple_chat_get_components(chat);
 			}
@@ -8868,7 +8868,7 @@
 #include "imgstore.h"
 #include "log.h"
 #include "notify.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "util.h"
 
@@ -9740,12 +9740,12 @@
 		text = purple_buddy_get_contact_alias(buddy);
 	} else {
 		PurpleConnection *gc;
-		PurplePluginProtocolInfo *prpl_info = NULL;
+		PurpleProtocol *protocol = NULL;
 
 		gc = purple_conversation_get_connection(conv);
 		if (gc != NULL)
-			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-		if (prpl_info && prpl_info->set_chat_topic == NULL)
+			protocol = purple_connection_get_protocol_info(gc);
+		if (protocol && protocol->set_chat_topic == NULL)
 			/* This protocol doesn't support setting the chat room topic */
 			return FALSE;
 
@@ -9870,7 +9870,7 @@
 	xa_list = make_status_icon_list(PIDGIN_STOCK_STATUS_XA, w);
 	offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w);
 	away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w);
-	prpl_lists = g_hash_table_new(g_str_hash, g_str_equal);
+	protocol_lists = g_hash_table_new(g_str_hash, g_str_equal);
 }
 
 static void
--- a/pidgin/gtkdialogs.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkdialogs.c	Sun Aug 18 01:53:00 2013 +0530
@@ -31,8 +31,8 @@
 
 #include "debug.h"
 #include "notify.h"
-#include "plugin.h"
-#include "prpl.h"
+#include "plugins.h"
+#include "protocol.h"
 #include "request.h"
 #include "util.h"
 #include "core.h"
@@ -686,12 +686,12 @@
 	g_string_append(str, "<dt>Network Security Services (NSS):</dt><dd>Disabled</dd>");
 #endif
 
-	if (purple_plugins_find_with_id("core-perl") != NULL)
+	if (purple_plugins_find_plugin("core-perl") != NULL)
 		g_string_append(str, "<dt>Perl:</dt><dd>Enabled</dd>");
 	else
 		g_string_append(str, "<dt>Perl:</dt><dd>Disabled</dd>");
 
-	if (purple_plugins_find_with_id("core-tcl") != NULL) {
+	if (purple_plugins_find_plugin("core-tcl") != NULL) {
 		g_string_append(str, "<dt>Tcl:</dt><dd>Enabled</dd>");
 #ifdef HAVE_TK
 		g_string_append(str, "<dt>Tk:</dt><dd>Enabled</dd>");
@@ -828,47 +828,58 @@
 void pidgin_dialogs_plugins_info(void)
 {
 	GString *str;
-	GList *l = NULL;
+	GList *plugins, *l = NULL;
 	PurplePlugin *plugin = NULL;
+	PurplePluginInfo *info;
 	char *title = g_strdup_printf(_("%s Plugin Information"), PIDGIN_NAME);
 	char *pname = NULL, *pauthor = NULL;
-	const char *pver, *pwebsite, *pid;
-	gboolean ploaded, punloadable;
+	const char *pver, *plicense, *pwebsite, *pid;
+	gboolean ploaded, ploadable;
 	static GtkWidget *plugins_info = NULL;
 
 	str = g_string_sized_new(4096);
 
 	g_string_append_printf(str, "<h2>%s</h2><dl>", _("Plugin Information"));
 
-	for(l = purple_plugins_get_all(); l; l = l->next) {
-		plugin = (PurplePlugin *)l->data;
+	plugins = purple_plugins_find_all();
+
+	for(l = plugins; l; l = l->next) {
+		plugin = PURPLE_PLUGIN(l->data);
+		info = purple_plugin_get_info(plugin);
 
-		pname = g_markup_escape_text(purple_plugin_get_name(plugin), -1);
-		if ((pauthor = (char *)purple_plugin_get_author(plugin)) != NULL)
+		pname = g_markup_escape_text(purple_plugin_info_get_name(info), -1);
+		if ((pauthor = (char *)purple_plugin_info_get_author(info)) != NULL)
 			pauthor = g_markup_escape_text(pauthor, -1);
-		pver = purple_plugin_get_version(plugin);
-		pwebsite = purple_plugin_get_homepage(plugin);
-		pid = purple_plugin_get_id(plugin);
-		punloadable = purple_plugin_is_unloadable(plugin);
+		pver = purple_plugin_info_get_version(info);
+		plicense = purple_plugin_info_get_license(info);
+		pwebsite = purple_plugin_info_get_website(info);
+		pid = purple_plugin_info_get_id(info);
+		ploadable = !purple_plugin_info_get_error(info);
 		ploaded = purple_plugin_is_loaded(plugin);
 
 		g_string_append_printf(str,
 				"<dt>%s</dt><dd>"
 				"<b>Author:</b> %s<br/>"
 				"<b>Version:</b> %s<br/>"
+				"<b>License:</b> %s<br/>"
 				"<b>Website:</b> %s<br/>"
 				"<b>ID String:</b> %s<br/>"
 				"<b>Loadable:</b> %s<br/>"
 				"<b>Loaded:</b> %s"
 				"</dd><br/>",
-				pname, pauthor ? pauthor : "(null)",
-				pver, pwebsite, pid,
-				punloadable ? "<span style=\"color: #FF0000;\"><b>No</b></span>" : "Yes",
-				ploaded ? "Yes" : "No");
+				pname    ? pname    : "",
+				pauthor  ? pauthor  : "",
+				pver     ? pver     : "",
+				plicense ? plicense : "",
+				pwebsite ? pwebsite : "",
+				pid,
+				ploadable ? "Yes" : "<span style=\"color: #FF0000;\"><b>No</b></span>",
+				ploaded   ? "Yes" : "No");
 
 		g_free(pname);
 		g_free(pauthor);
 	}
+	g_list_free(plugins);
 
 	g_string_append(str, "</dl>");
 
@@ -896,15 +907,15 @@
 {
 	PurpleRequestFields *fields = _fields;
 	PurpleAccount *account;
-	PurplePlugin *prpl;
+	PurpleProtocol *protocol;
 	const char *username;
 	gboolean valid;
 
 	account = purple_request_fields_get_account(fields, "account");
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
 	username = purple_request_fields_get_string(fields, "screenname");
 
-	valid = purple_validate(prpl, username);
+	valid = purple_validate(protocol, username);
 
 	if (errmsg && !valid)
 		*errmsg = g_strdup(_("Invalid username"));
--- a/pidgin/gtkdocklet.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkdocklet.c	Sun Aug 18 01:53:00 2013 +0530
@@ -260,8 +260,8 @@
 
 	while(c != NULL) {
 		PurpleConnection *gc = c->data;
-		PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-		if (prpl_info != NULL && prpl_info->chat_info != NULL)
+		PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
+		if (protocol != NULL && protocol->chat_info != NULL)
 			return TRUE;
 		c = c->next;
 	}
@@ -297,7 +297,7 @@
 docklet_signed_on_cb(PurpleConnection *gc)
 {
 	if (!enable_join_chat) {
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL)
+		if (purple_connection_get_protocol_info(gc)->chat_info != NULL)
 			enable_join_chat = TRUE;
 	}
 	docklet_update_status();
@@ -307,7 +307,7 @@
 docklet_signed_off_cb(PurpleConnection *gc)
 {
 	if (enable_join_chat) {
-		if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL)
+		if (purple_connection_get_protocol_info(gc)->chat_info != NULL)
 			enable_join_chat = online_account_supports_chat();
 	}
 	docklet_update_status();
@@ -623,7 +623,6 @@
 }
 
 
-
 static void
 plugin_act(GtkWidget *widget, PurplePluginAction *pam)
 {
@@ -632,14 +631,16 @@
 }
 
 static void
-build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin,
-		gpointer context)
+build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin)
 {
 	GtkWidget *menuitem;
+	PurplePluginGetActionsCallback get_actions;
 	PurplePluginAction *action = NULL;
 	GList *actions, *l;
 
-	actions = PURPLE_PLUGIN_ACTIONS(plugin, context);
+	get_actions =
+		purple_plugin_info_get_actions_callback(purple_plugin_get_info(plugin));
+	actions = get_actions(plugin);
 
 	for (l = actions; l != NULL; l = l->next)
 	{
@@ -647,7 +648,6 @@
 		{
 			action = (PurplePluginAction *) l->data;
 			action->plugin = plugin;
-			action->context = context;
 
 			menuitem = gtk_menu_item_new_with_label(action->label);
 			gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
@@ -672,6 +672,7 @@
 {
 	GtkWidget *menuitem, *submenu;
 	PurplePlugin *plugin = NULL;
+	PurplePluginInfo *info;
 	GList *l;
 	int c = 0;
 
@@ -679,21 +680,20 @@
 
 	/* Add a submenu for each plugin with custom actions */
 	for (l = purple_plugins_get_loaded(); l; l = l->next) {
-		plugin = (PurplePlugin *) l->data;
+		plugin = PURPLE_PLUGIN(l->data);
+		info = purple_plugin_get_info(plugin);
 
-		if (PURPLE_IS_PROTOCOL_PLUGIN(plugin))
+		if (!purple_plugin_info_get_actions_callback(info))
 			continue;
 
-		if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin))
-			continue;
-
-		menuitem = gtk_image_menu_item_new_with_label(_(plugin->info->name));
+		menuitem =
+			gtk_image_menu_item_new_with_label(_(purple_plugin_info_get_name(info)));
 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 
 		submenu = gtk_menu_new();
 		gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
 
-		build_plugin_actions(submenu, plugin, NULL);
+		build_plugin_actions(submenu, plugin);
 
 		c++;
 	}
--- a/pidgin/gtkft.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkft.c	Sun Aug 18 01:53:00 2013 +0530
@@ -29,7 +29,7 @@
 #include "debug.h"
 #include "notify.h"
 #include "ft.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 
 #include "gtkft.h"
--- a/pidgin/gtkimhtmltoolbar.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkimhtmltoolbar.c	Sun Aug 18 01:53:00 2013 +0530
@@ -927,7 +927,7 @@
 	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);
+	purple_protocol_send_attention(gc, who, 0);
 	gtk_widget_grab_focus(toolbar->imhtml);
 }
 
@@ -1593,14 +1593,14 @@
 	PurpleConversation *conv)
 {
 	PurpleConnection *gc = purple_conversation_get_connection(conv);
-	PurplePlugin *prpl = purple_connection_get_prpl(gc);
+	PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
 
 	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(toolbar->attention,
-		conv && prpl && PURPLE_IS_IM_CONVERSATION(conv) &&
-		PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL);
+		conv && protocol && PURPLE_IS_IM_CONVERSATION(conv) &&
+		protocol->send_attention != NULL);
 }
 
--- a/pidgin/gtklog.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtklog.c	Sun Aug 18 01:53:00 2013 +0530
@@ -689,7 +689,7 @@
 	PidginLogViewer *lv = NULL;
 	const char *name = buddyname;
 	char *title;
-	GdkPixbuf *prpl_icon;
+	GdkPixbuf *protocol_icon;
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(buddyname != NULL);
@@ -727,14 +727,14 @@
 		title = g_strdup_printf(_("Conversations with %s"), name);
 	}
 
-	prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
+	protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
 
 	display_log_viewer(ht, purple_log_get_logs(type, buddyname, account),
-			title, gtk_image_new_from_pixbuf(prpl_icon),
+			title, gtk_image_new_from_pixbuf(protocol_icon),
 			purple_log_get_total_size(type, buddyname, account));
 
-	if (prpl_icon)
-		g_object_unref(prpl_icon);
+	if (protocol_icon)
+		g_object_unref(protocol_icon);
 	g_free(title);
 }
 
@@ -822,7 +822,7 @@
 	for(accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
 
 		PurpleAccount *account = (PurpleAccount *)accounts->data;
-		if(purple_find_prpl(purple_account_get_protocol_id(account)) == NULL)
+		if(purple_find_protocol_info(purple_account_get_protocol_id(account)) == NULL)
 			continue;
 
 		logs = g_list_concat(purple_log_get_system_logs(account), logs);
--- a/pidgin/gtkmain.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkmain.c	Sun Aug 18 01:53:00 2013 +0530
@@ -35,7 +35,7 @@
 #include "network.h"
 #include "notify.h"
 #include "prefs.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "pounce.h"
 #include "sound.h"
 #include "status.h"
@@ -757,17 +757,6 @@
 	purple_core_set_ui_ops(pidgin_core_get_ui_ops());
 	purple_eventloop_set_ui_ops(pidgin_eventloop_get_ui_ops());
 
-	/*
-	 * Set plugin search directories. Give priority to the plugins
-	 * in user's home directory.
-	 */
-	search_path = g_build_filename(purple_user_dir(), "plugins", NULL);
-	if (!g_stat(search_path, &st))
-		g_mkdir(search_path, S_IRUSR | S_IWUSR | S_IXUSR);
-	purple_plugins_add_search_path(search_path);
-	g_free(search_path);
-	purple_plugins_add_search_path(LIBDIR);
-
 	if (!purple_core_init(PIDGIN_UI)) {
 		fprintf(stderr,
 				"Initialization of the libpurple core failed. Dumping core.\n"
@@ -778,6 +767,15 @@
 		abort();
 	}
 
+	search_path = g_build_filename(purple_user_dir(), "plugins", NULL);
+	if (!g_stat(search_path, &st))
+		g_mkdir(search_path, S_IRUSR | S_IWUSR | S_IXUSR);
+	purple_plugins_add_search_path(search_path);
+	g_free(search_path);
+
+	purple_plugins_add_search_path(LIBDIR);
+	purple_plugins_refresh();
+
 	if (opt_si && !purple_core_ensure_single_instance()) {
 #ifdef HAVE_DBUS
 		DBusConnection *conn = purple_dbus_get_connection();
--- a/pidgin/gtknotify.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtknotify.c	Sun Aug 18 01:53:00 2013 +0530
@@ -674,7 +674,7 @@
 	if (clear)
 		return NULL;
 
-	icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
+	icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
 
 	if (new_n) {
 		data = g_new0(PidginNotifyMailData, 1);
@@ -931,7 +931,7 @@
 
 	gtk_list_store_clear(data->model);
 
-	pixbuf = pidgin_create_prpl_icon(purple_connection_get_account(gc), PIDGIN_PRPL_ICON_SMALL);
+	pixbuf = pidgin_create_protocol_icon(purple_connection_get_account(gc), PIDGIN_PROTOCOL_ICON_SMALL);
 
 	for (row = results->rows; row != NULL; row = row->next) {
 
@@ -1460,7 +1460,7 @@
 	if (pounce_dialog == NULL)
 		pounce_dialog = pidgin_create_notification_dialog(PIDGIN_NOTIFY_POUNCE);
 
-	icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 
 	pounce_data = g_new(PidginNotifyPounceData, 1);
 
--- a/pidgin/gtkplugin.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkplugin.c	Sun Aug 18 01:53:00 2013 +0530
@@ -37,10 +37,25 @@
 
 #include "gtk3compat.h"
 
+#define PIDGIN_PLUGIN_INFO_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfoPrivate))
+
 #define PIDGIN_RESPONSE_CONFIGURE 98121
 
+typedef struct
+{
+	PidginPluginConfigFrame get_config_frame;
+} PidginPluginInfoPrivate;
+
+enum
+{
+	PROP_0,
+	PROP_PIDGIN_CONFIG_FRAME,
+	PROP_LAST
+};
+
 static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model,
-                                  GtkTreeIter *iter, gboolean unload);
+                                  GtkTreeIter *iter, GError *error, gboolean unload);
 
 static GtkWidget *expander = NULL;
 static GtkWidget *plugin_dialog = NULL;
@@ -56,47 +71,155 @@
 static GtkWidget *pref_button = NULL;
 static GHashTable *plugin_pref_dialogs = NULL;
 
+/* Set method for GObject properties */
+static void
+pidgin_plugin_info_set_property(GObject *obj, guint param_id, const GValue *value,
+		GParamSpec *pspec)
+{
+	PidginPluginInfoPrivate *priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(obj);
+
+	switch (param_id) {
+		case PROP_PIDGIN_CONFIG_FRAME:
+			priv->get_config_frame = g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+/* Get method for GObject properties */
+static void
+pidgin_plugin_info_get_property(GObject *obj, guint param_id, GValue *value,
+		GParamSpec *pspec)
+{
+	PidginPluginInfoPrivate *priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(obj);
+
+	switch (param_id) {
+		case PROP_PIDGIN_CONFIG_FRAME:
+			g_value_set_pointer(value, priv->get_config_frame);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+/* Class initializer function */
+static void pidgin_plugin_info_class_init(PidginPluginInfoClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+	g_type_class_add_private(klass, sizeof(PidginPluginInfoPrivate));
+
+	/* Setup properties */
+	obj_class->get_property = pidgin_plugin_info_get_property;
+	obj_class->set_property = pidgin_plugin_info_set_property;
+
+	g_object_class_install_property(obj_class, PROP_PIDGIN_CONFIG_FRAME,
+		g_param_spec_pointer("pidgin-config-frame",
+		                     "Pidgin configuration frame callback",
+		                     "Callback that returns a GTK configuration frame",
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+GType
+pidgin_plugin_info_get_type(void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY(type == 0)) {
+		static const GTypeInfo info = {
+			.class_size = sizeof(PidginPluginInfoClass),
+			.class_init = (GClassInitFunc)pidgin_plugin_info_class_init,
+			.instance_size = sizeof(PidginPluginInfo),
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_PLUGIN_INFO,
+		                              "PidginPluginInfo", &info, 0);
+	}
+
+	return type;
+}
+
+PidginPluginInfo *
+pidgin_plugin_info_new(const char *first_property, ...)
+{
+	GObject *info;
+	va_list var_args;
+
+	/* at least ID is required */
+	if (!first_property)
+		return NULL;
+
+	va_start(var_args, first_property);
+	info = g_object_new_valist(PIDGIN_TYPE_PLUGIN_INFO, first_property,
+	                           var_args);
+	va_end(var_args);
+
+	g_object_set(info, "ui-requirement", PIDGIN_UI, NULL);
+
+	return PIDGIN_PLUGIN_INFO(info);
+}
+
 GtkWidget *
 pidgin_plugin_get_config_frame(PurplePlugin *plugin)
 {
 	GtkWidget *config = NULL;
+	PurplePluginInfo *info;
+	PidginPluginInfoPrivate *priv = NULL;
 
 	g_return_val_if_fail(plugin != NULL, NULL);
 
-	if (PIDGIN_IS_PIDGIN_PLUGIN(plugin) && plugin->info->ui_info
-		&& PIDGIN_PLUGIN_UI_INFO(plugin)->get_config_frame)
-	{
-		PidginPluginUiInfo *ui_info;
+	info = purple_plugin_get_info(plugin);
+	if (PIDGIN_IS_PLUGIN_INFO(info))
+		priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(info);
 
-		ui_info = PIDGIN_PLUGIN_UI_INFO(plugin);
+	if (priv && priv->get_config_frame)
+	{
+		config = priv->get_config_frame(plugin);
 
-		config = ui_info->get_config_frame(plugin);
-
-		if (plugin->info->prefs_info
-			&& plugin->info->prefs_info->get_plugin_pref_frame)
+		if (purple_plugin_info_get_pref_frame_callback(info))
 		{
 			purple_debug_warning("gtkplugin",
 				"Plugin %s contains both, ui_info and "
 				"prefs_info preferences; prefs_info will be "
-				"ignored.", plugin->info->name);
+				"ignored.",
+				purple_plugin_info_get_name(info));
 		}
 	}
-
-	if (config == NULL && plugin->info->prefs_info
-		&& plugin->info->prefs_info->get_plugin_pref_frame)
+	else if (purple_plugin_info_get_pref_frame_callback(info))
 	{
 		PurplePluginPrefFrame *frame;
+		PurplePluginPrefFrameCallback get_pref_frame =
+				purple_plugin_info_get_pref_frame_callback(info);
 
-		frame = plugin->info->prefs_info->get_plugin_pref_frame(plugin);
+		frame = get_pref_frame(plugin);
 
 		config = pidgin_plugin_pref_create_frame(frame);
-
-		plugin->info->prefs_info->frame = frame;
 	}
 
 	return config;
 }
 
+static gboolean
+pidgin_plugin_has_config_frame(PurplePlugin *plugin)
+{
+	PurplePluginInfo *info = purple_plugin_get_info(plugin);
+	PidginPluginInfoPrivate *priv = NULL;
+	gboolean ret;
+
+	g_return_val_if_fail(plugin != NULL, FALSE);
+
+	if (PIDGIN_IS_PLUGIN_INFO(info))
+		priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(info);
+
+	ret = ((priv && priv->get_config_frame) ||
+			purple_plugin_info_get_pref_frame_callback(info));
+
+	return ret;
+}
+
 void
 pidgin_plugins_save(void)
 {
@@ -108,44 +231,38 @@
 {
 	GtkListStore *ls = GTK_LIST_STORE(data);
 	GtkTreeIter iter;
-	GList *probes;
+	GList *plugins, *l;
 	PurplePlugin *plug;
+	PurplePluginInfo *info;
 
 	gtk_list_store_clear(ls);
-	purple_plugins_probe(G_MODULE_SUFFIX);
+	purple_plugins_refresh();
 
-	for (probes = purple_plugins_get_all();
-		 probes != NULL;
-		 probes = probes->next)
+	plugins = purple_plugins_find_all();
+
+	for (l = plugins; l != NULL; l = l->next)
 	{
 		char *name;
 		char *version;
 		char *summary;
 		char *desc;
-		plug = probes->data;
+		plug = PURPLE_PLUGIN(l->data);
+		info = purple_plugin_get_info(plug);
 
-		if (plug->info->type == PURPLE_PLUGIN_LOADER) {
-			GList *cur;
-			for (cur = PURPLE_PLUGIN_LOADER_INFO(plug)->exts; cur != NULL;
-					 cur = cur->next)
-				purple_plugins_probe(cur->data);
+		if (purple_plugin_is_internal(plug))
 			continue;
-		} else if (plug->info->type != PURPLE_PLUGIN_STANDARD ||
-			(plug->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE)) {
-			continue;
-		}
 
 		gtk_list_store_append (ls, &iter);
 
-		if (plug->info->name) {
-			name = g_markup_escape_text(_(plug->info->name), -1);
+		if (purple_plugin_info_get_name(info)) {
+			name = g_markup_escape_text(_(purple_plugin_info_get_name(info)), -1);
 		} else {
-			char *tmp = g_path_get_basename(plug->path);
+			char *tmp = g_path_get_basename(purple_plugin_get_filename(plug));
 			name = g_markup_escape_text(tmp, -1);
 			g_free(tmp);
 		}
-		version = g_markup_escape_text(purple_plugin_get_version(plug), -1);
-		summary = g_markup_escape_text(purple_plugin_get_summary(plug), -1);
+		version = g_markup_escape_text(purple_plugin_info_get_version(info), -1);
+		summary = g_markup_escape_text(purple_plugin_info_get_summary(info), -1);
 
 		desc = g_strdup_printf("<b>%s</b> %s\n%s", name,
 				       version,
@@ -158,10 +275,11 @@
 				   0, purple_plugin_is_loaded(plug),
 				   1, desc,
 				   2, plug,
-				   3, purple_plugin_is_unloadable(plug),
 				   -1);
 		g_free(desc);
 	}
+
+	g_list_free(plugins);
 }
 
 static void plugin_loading_common(PurplePlugin *plugin, GtkTreeView *view, gboolean loaded)
@@ -190,11 +308,7 @@
 				if (plug == plugin)
 				{
 					gtk_widget_set_sensitive(pref_button,
-						loaded
-						&& ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info
-							&& PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame)
-						 || (plug->info->prefs_info
-							&& plug->info->prefs_info->get_plugin_pref_frame)));
+							loaded && pidgin_plugin_has_config_frame(plug));
 				}
 			}
 
@@ -227,11 +341,6 @@
 		}
 		gtk_widget_destroy(d);
 
-		if (plug->info->prefs_info && plug->info->prefs_info->frame) {
-			purple_plugin_pref_frame_destroy(plug->info->prefs_info->frame);
-			plug->info->prefs_info->frame = NULL;
-		}
-
 		break;
 	}
 }
@@ -242,7 +351,7 @@
 	GtkTreeModel *model = (GtkTreeModel *)data[1];
 	GtkTreeIter *iter = (GtkTreeIter *)data[2];
 
-	plugin_toggled_stage_two(plugin, model, iter, TRUE);
+	plugin_toggled_stage_two(plugin, model, iter, NULL, TRUE);
 
 	g_free(data);
 }
@@ -253,25 +362,19 @@
 	GtkTreeIter *iter = g_new(GtkTreeIter, 1);
 	GtkTreePath *path = gtk_tree_path_new_from_string(pth);
 	PurplePlugin *plug;
+	GError *error = NULL;
 	GtkWidget *dialog = NULL;
 
 	gtk_tree_model_get_iter(model, iter, path);
 	gtk_tree_path_free(path);
 	gtk_tree_model_get(model, iter, 2, &plug, -1);
 
-	/* Apparently, GTK+ won't honor the sensitive flag on cell renderers for booleans. */
-	if (purple_plugin_is_unloadable(plug))
-	{
-		g_free(iter);
-		return;
-	}
-
 	if (!purple_plugin_is_loaded(plug))
 	{
 		pidgin_set_cursor(plugin_dialog, GDK_WATCH);
 
-		purple_plugin_load(plug);
-		plugin_toggled_stage_two(plug, model, iter, FALSE);
+		purple_plugin_load(plug, &error);
+		plugin_toggled_stage_two(plug, model, iter, error, FALSE);
 
 		pidgin_clear_cursor(plugin_dialog);
 	}
@@ -281,19 +384,22 @@
 			(dialog = g_hash_table_lookup(plugin_pref_dialogs, plug)))
 			pref_dialog_response_cb(dialog, GTK_RESPONSE_DELETE_EVENT, plug);
 
-		if (plug->dependent_plugins != NULL)
+		if (purple_plugin_get_dependent_plugins(plug) != NULL)
 		{
 			GString *tmp = g_string_new(_("The following plugins will be unloaded."));
-			GList *l;
+			GSList *l;
 			gpointer *cb_data;
 
-			for (l = plug->dependent_plugins ; l != NULL ; l = l->next)
+			for (l = purple_plugin_get_dependent_plugins(plug); l != NULL ; l = l->next)
 			{
 				const char *dep_name = (const char *)l->data;
-				PurplePlugin *dep_plugin = purple_plugins_find_with_id(dep_name);
+				PurplePlugin *dep_plugin = purple_plugins_find_plugin(dep_name);
+				PurplePluginInfo *dep_info;
+
 				g_return_if_fail(dep_plugin != NULL);
 
-				g_string_append_printf(tmp, "\n\t%s\n", purple_plugin_get_name(dep_plugin));
+				dep_info = purple_plugin_get_info(dep_plugin);
+				g_string_append_printf(tmp, "\n\t%s\n", purple_plugin_info_get_name(dep_info));
 			}
 
 			cb_data = g_new(gpointer, 3);
@@ -311,31 +417,26 @@
 			g_string_free(tmp, TRUE);
 		}
 		else
-			plugin_toggled_stage_two(plug, model, iter, TRUE);
+			plugin_toggled_stage_two(plug, model, iter, NULL, TRUE);
 	}
 }
 
-static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, GtkTreeIter *iter, gboolean unload)
+static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, GtkTreeIter *iter, GError *error, gboolean unload)
 {
+	PurplePluginInfo *info = purple_plugin_get_info(plug);
+
 	if (unload)
 	{
 		pidgin_set_cursor(plugin_dialog, GDK_WATCH);
 
-		if (!purple_plugin_unload(plug))
+		if (!purple_plugin_unload(plug, &error))
 		{
 			const char *primary = _("Could not unload plugin");
 			const char *reload = _("The plugin could not be unloaded now, but will be disabled at the next startup.");
 
-			if (!plug->error)
-			{
-				purple_notify_warning(NULL, NULL, primary, reload);
-			}
-			else
-			{
-				char *tmp = g_strdup_printf("%s\n\n%s", reload, plug->error);
-				purple_notify_warning(NULL, NULL, primary, tmp);
-				g_free(tmp);
-			}
+			char *tmp = g_strdup_printf("%s\n\n%s", reload, error->message);
+			purple_notify_warning(NULL, NULL, primary, tmp);
+			g_free(tmp);
 
 			purple_plugin_disable(plug);
 		}
@@ -344,22 +445,19 @@
 	}
 
 	gtk_widget_set_sensitive(pref_button,
-		purple_plugin_is_loaded(plug)
-		&& ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info
-			&& PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame)
-		 || (plug->info->prefs_info
-			&& plug->info->prefs_info->get_plugin_pref_frame)));
+		purple_plugin_is_loaded(plug) && pidgin_plugin_has_config_frame(plug));
 
-	if (plug->error != NULL)
+	if (error != NULL)
 	{
-		gchar *name = g_markup_escape_text(purple_plugin_get_name(plug), -1);
+		gchar *name = g_markup_escape_text(purple_plugin_info_get_name(info), -1);
 
-		gchar *error = g_markup_escape_text(plug->error, -1);
+		gchar *disp_error = g_markup_escape_text(error->message, -1);
 		gchar *text;
 
 		text = g_strdup_printf(
 			"<b>%s</b> %s\n<span weight=\"bold\" color=\"red\"%s</span>",
-			purple_plugin_get_name(plug), purple_plugin_get_version(plug), error);
+			purple_plugin_info_get_name(info),
+			purple_plugin_info_get_version(info), disp_error);
 		gtk_list_store_set(GTK_LIST_STORE (model), iter,
 				   1, text,
 				   -1);
@@ -367,12 +465,14 @@
 
 		text = g_strdup_printf(
 			"<span weight=\"bold\" color=\"red\">%s</span>",
-			error);
+			disp_error);
 		gtk_label_set_markup(plugin_error, text);
 		g_free(text);
 
-		g_free(error);
+		g_free(disp_error);
 		g_free(name);
+
+		g_error_free(error);
 	}
 
 	gtk_list_store_set(GTK_LIST_STORE (model), iter,
@@ -404,6 +504,7 @@
 	GtkTreeIter  iter;
 	GValue val;
 	PurplePlugin *plug;
+	PurplePluginInfo *info;
 
 	if (!gtk_tree_selection_get_selected (sel, &model, &iter))
 	{
@@ -421,9 +522,10 @@
 	val.g_type = 0;
 	gtk_tree_model_get_value (model, &iter, 2, &val);
 	plug = g_value_get_pointer(&val);
+	info = purple_plugin_get_info(plug);
 
-	name = g_markup_escape_text(purple_plugin_get_name(plug), -1);
-	version = g_markup_escape_text(purple_plugin_get_version(plug), -1);
+	name = g_markup_escape_text(purple_plugin_info_get_name(info), -1);
+	version = g_markup_escape_text(purple_plugin_info_get_version(info), -1);
 	buf = g_strdup_printf(
 		"<span size=\"larger\" weight=\"bold\">%s</span> "
 		"<span size=\"smaller\">%s</span>",
@@ -433,12 +535,13 @@
 	g_free(version);
 	g_free(buf);
 
-	gtk_text_buffer_set_text(plugin_desc, purple_plugin_get_description(plug), -1);
-	gtk_label_set_text(plugin_author, purple_plugin_get_author(plug));
-	gtk_label_set_text(plugin_filename, plug->path);
+	gtk_text_buffer_set_text(plugin_desc, purple_plugin_info_get_description(info), -1);
+	gtk_label_set_text(plugin_author, purple_plugin_info_get_author(info));
+	gtk_label_set_text(plugin_filename, purple_plugin_get_filename(plug));
 
 	g_free(plugin_website_uri);
-	plugin_website_uri = g_strdup(purple_plugin_get_homepage(plug));
+	plugin_website_uri = g_strdup(purple_plugin_info_get_website(info));
+
 	if (plugin_website_uri)
 	{
 		tmp = g_markup_escape_text(plugin_website_uri, -1);
@@ -453,13 +556,13 @@
 		gtk_label_set_text(plugin_website, NULL);
 	}
 
-	if (plug->error == NULL)
+	if (purple_plugin_info_get_error(info) == NULL)
 	{
 		gtk_label_set_text(plugin_error, NULL);
 	}
 	else
 	{
-		tmp = g_markup_escape_text(plug->error, -1);
+		tmp = g_markup_escape_text(purple_plugin_info_get_error(info), -1);
 		buf = g_strdup_printf(
 			_("<span foreground=\"red\" weight=\"bold\">"
 			  "Error: %s\n"
@@ -472,11 +575,7 @@
 	}
 
 	gtk_widget_set_sensitive(pref_button,
-		purple_plugin_is_loaded(plug)
-		&& ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info
-			&& PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame)
-		 || (plug->info->prefs_info
-			&& plug->info->prefs_info->get_plugin_pref_frame)));
+		purple_plugin_is_loaded(plug) && pidgin_plugin_has_config_frame(plug));
 
 	/* Make sure the selected plugin is still visible */
 	g_idle_add(ensure_plugin_visible, sel);
@@ -531,9 +630,11 @@
 		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_window_set_role(GTK_WINDOW(dialog), "plugin_config");
-		gtk_window_set_title(GTK_WINDOW(dialog), _(purple_plugin_get_name(plug)));
+		gtk_window_set_title(GTK_WINDOW(dialog),
+				_(purple_plugin_info_get_name(purple_plugin_get_info(plug))));
 		gtk_widget_show_all(dialog);
 		g_value_unset(&val);
+
 		break;
 	}
 }
@@ -583,6 +684,7 @@
 	GtkTreeIter iter;
 	GtkTreeView *treeview = GTK_TREE_VIEW(data);
 	PurplePlugin *plugin = NULL;
+	PurplePluginInfo *info;
 	GtkTreeModel *model = gtk_tree_view_get_model(treeview);
 	PangoLayout *layout;
 	int width, height;
@@ -592,11 +694,12 @@
 		return FALSE;
 
 	gtk_tree_model_get(model, &iter, 2, &plugin, -1);
+	info = purple_plugin_get_info(plugin);
 
 	markup = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>\n<b>%s:</b> %s\n<b>%s:</b> %s",
-			name = g_markup_escape_text(purple_plugin_get_name(plugin), -1),
-			_("Description"), desc = g_markup_escape_text(purple_plugin_get_description(plugin), -1),
-			_("Author"), author = g_markup_escape_text(purple_plugin_get_author(plugin), -1));
+			name = g_markup_escape_text(purple_plugin_info_get_name(info), -1),
+			_("Description"), desc = g_markup_escape_text(purple_plugin_info_get_description(info), -1),
+			_("Author"), author = g_markup_escape_text(purple_plugin_info_get_author(info), -1));
 
 	layout = gtk_widget_create_pango_layout(tipwindow, NULL);
 	pango_layout_set_markup(layout, markup, -1);
@@ -734,7 +837,7 @@
 	gtk_widget_set_sensitive(pref_button, FALSE);
 	gtk_window_set_role(GTK_WINDOW(plugin_dialog), "plugins");
 
-	ls = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+	ls = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER);
 	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls),
 					     1, GTK_SORT_ASCENDING);
 
--- a/pidgin/gtkplugin.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkplugin.h	Sun Aug 18 01:53:00 2013 +0530
@@ -27,36 +27,71 @@
 #define _PIDGINPLUGIN_H_
 
 #include "pidgin.h"
-#include "plugin.h"
+#include "plugins.h"
 
-typedef struct _PidginPluginUiInfo PidginPluginUiInfo;
+#define PIDGIN_TYPE_PLUGIN_INFO             (pidgin_plugin_info_get_type())
+#define PIDGIN_PLUGIN_INFO(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfo))
+#define PIDGIN_PLUGIN_INFO_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfoClass))
+#define PIDGIN_IS_PLUGIN_INFO(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), PIDGIN_TYPE_PLUGIN_INFO))
+#define PIDGIN_IS_PLUGIN_INFO_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), PIDGIN_TYPE_PLUGIN_INFO))
+#define PIDGIN_PLUGIN_INFO_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfoClass))
+
+/** @copydoc _PidginPluginInfo */
+typedef struct _PidginPluginInfo PidginPluginInfo;
+/** @copydoc _PidginPluginInfoClass */
+typedef struct _PidginPluginInfoClass PidginPluginInfoClass;
+
+typedef GtkWidget *(*PidginPluginConfigFrame)(PurplePlugin *);
 
 /**
- * A GTK+ UI structure for plugins.
+ * Extends #PurplePluginInfo to hold UI information for pidgin.
  */
-struct _PidginPluginUiInfo
-{
-	GtkWidget *(*get_config_frame)(PurplePlugin *plugin);
+struct _PidginPluginInfo {
+	/*< private >*/
+	PurplePluginInfo parent;
+};
 
-	int page_num;                                         /**< Reserved */
+/**
+ * PidginPluginInfoClass:
+ *
+ * The base class for all #PidginPluginInfo's.
+ */
+struct _PidginPluginInfoClass {
+	/*< private >*/
+	PurplePluginInfoClass parent_class;
 
-	/* padding */
 	void (*_pidgin_reserved1)(void);
 	void (*_pidgin_reserved2)(void);
 	void (*_pidgin_reserved3)(void);
 	void (*_pidgin_reserved4)(void);
 };
 
-#define PIDGIN_PLUGIN_TYPE PIDGIN_UI
+G_BEGIN_DECLS
+
+/**
+ * Returns the GType for the PidginPluginInfo object.
+ */
+GType pidgin_plugin_info_get_type(void);
 
-#define PIDGIN_IS_PIDGIN_PLUGIN(plugin) \
-	((plugin)->info != NULL && (plugin)->info->ui_info != NULL && \
-	 !strcmp((plugin)->info->ui_requirement, PIDGIN_PLUGIN_TYPE))
-
-#define PIDGIN_PLUGIN_UI_INFO(plugin) \
-	((PidginPluginUiInfo *)(plugin)->info->ui_info)
-
-G_BEGIN_DECLS
+/**
+ * Creates a new #PidginPluginInfo instance to be returned from
+ * gplugin_plugin_query() of a pidgin plugin, using the provided name/value
+ * pairs.
+ *
+ * See purple_plugin_info_new() for a list of available property names.
+ * Additionally, you can provide the property "pidgin-config-frame",
+ * which should be a callback that returns a GtkWidget for the plugin's
+ * configuration (see PidginPluginConfigFrame).
+ *
+ * @param first_property  The first property name
+ * @param ...  The value of the first property, followed optionally by more
+ *             name/value pairs, followed by @c NULL
+ *
+ * @return A new #PidginPluginInfo instance.
+ *
+ * @see purple_plugin_info_new()
+ */
+PidginPluginInfo *pidgin_plugin_info_new(const char *first_property, ...);
 
 /**
  * Returns the configuration frame widget for a GTK+ plugin, if one
--- a/pidgin/gtkpounce.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkpounce.c	Sun Aug 18 01:53:00 2013 +0530
@@ -30,7 +30,7 @@
 #include "account.h"
 #include "conversation.h"
 #include "debug.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "server.h"
 #include "sound.h"
@@ -203,7 +203,7 @@
 
 	account = purple_pounce_get_pouncer(pounce);
 
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
 
 	pouncer = purple_account_get_username(account);
 	pouncee = purple_pounce_get_pouncee(pounce);
--- a/pidgin/gtkprefs.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkprefs.c	Sun Aug 18 01:53:00 2013 +0530
@@ -34,7 +34,7 @@
 #include "notify.h"
 #include "prefs.h"
 #include "proxy.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "savedstatuses.h"
 #include "sound.h"
--- a/pidgin/gtkrequest.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkrequest.c	Sun Aug 18 01:53:00 2013 +0530
@@ -99,7 +99,7 @@
 	if (!account)
 		return;
 
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 	image = gtk_image_new_from_pixbuf(pixbuf);
 	g_object_unref(G_OBJECT(pixbuf));
 
--- a/pidgin/gtkroomlist.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkroomlist.c	Sun Aug 18 01:53:00 2013 +0530
@@ -230,13 +230,13 @@
 	char *name;
 	PurpleAccount *account = purple_roomlist_get_account(info->list);
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	if(gc != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = purple_connection_get_protocol_info(gc);
 
-	if(prpl_info != NULL && prpl_info->roomlist_room_serialize)
-		name = prpl_info->roomlist_room_serialize(info->room);
+	if(protocol != NULL && protocol->roomlist_room_serialize)
+		name = protocol->roomlist_room_serialize(info->room);
 	else
 		name = g_strdup(purple_roomlist_room_get_name(info->room));
 
@@ -537,12 +537,12 @@
 static gboolean account_filter_func(PurpleAccount *account)
 {
 	PurpleConnection *conn = purple_account_get_connection(account);
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	if (conn && PURPLE_CONNECTION_IS_CONNECTED(conn))
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(conn));
+		protocol = purple_connection_get_protocol_info(conn);
 
-	return (prpl_info && prpl_info->roomlist_get_list != NULL);
+	return (protocol && protocol->roomlist_get_list != NULL);
 }
 
 gboolean
--- a/pidgin/gtksavedstatuses.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtksavedstatuses.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1002,7 +1002,7 @@
 	const char *id = NULL, *name = NULL, *message = NULL;
 	PurpleStatusPrimitive prim = PURPLE_STATUS_UNSET;
 
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
 	if ((pixbuf != NULL) && !purple_account_is_connected(account))
 	{
 		gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
--- a/pidgin/gtkstatusbox.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkstatusbox.c	Sun Aug 18 01:53:00 2013 +0530
@@ -494,12 +494,10 @@
 	case PROP_ICON_SEL:
 		if (g_value_get_boolean(value)) {
 			if (statusbox->account) {
-				PurplePlugin *plug = purple_plugins_find_with_id(purple_account_get_protocol_id(statusbox->account));
-				if (plug) {
-					PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug);
-					if (prplinfo && prplinfo->icon_spec.format != NULL)
-						setup_icon_box(statusbox);
-				}
+				PurpleProtocol *protocol =
+						purple_find_protocol_info(purple_account_get_protocol_id(statusbox->account));
+				if (protocol && protocol->icon_spec.format != NULL)
+					setup_icon_box(statusbox);
 			} else {
 				setup_icon_box(statusbox);
 			}
@@ -715,7 +713,7 @@
 		text = g_strdup_printf("%s - <span size=\"smaller\" color=\"%s\">%s</span>",
 				       purple_account_get_username(status_box->account),
 				       aa_color, secondary ? secondary : primary);
-		emblem = pidgin_create_prpl_icon(status_box->account, PIDGIN_PRPL_ICON_SMALL);
+		emblem = pidgin_create_protocol_icon(status_box->account, PIDGIN_PROTOCOL_ICON_SMALL);
 	} else if (secondary != NULL) {
 		text = g_strdup_printf("%s<span size=\"smaller\" color=\"%s\"> - %s</span>",
 				       primary, aa_color, secondary);
@@ -1452,44 +1450,40 @@
 	PurpleStoredImage *img = NULL;
 
 	if (box->account) {
-		PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(box->account));
-		if (plug) {
-			PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug);
-			if (prplinfo && prplinfo->icon_spec.format) {
-				gpointer data = NULL;
-				size_t len = 0;
-				if (filename)
-					data = pidgin_convert_buddy_icon(plug, filename, &len);
-				img = purple_buddy_icons_set_account_icon(box->account, data, len);
-				if (img)
-					/*
-					 * set_account_icon doesn't give us a reference, but we
-					 * unref one below (for the other code path)
-					 */
-					purple_imgstore_ref(img);
-
-				purple_account_set_buddy_icon_path(box->account, filename);
-
-				purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL));
-			}
+		PurpleProtocol *protocol =
+				purple_find_protocol_info(purple_account_get_protocol_id(box->account));
+		if (protocol && protocol->icon_spec.format) {
+			gpointer data = NULL;
+			size_t len = 0;
+			if (filename)
+				data = pidgin_convert_buddy_icon(protocol, filename, &len);
+			img = purple_buddy_icons_set_account_icon(box->account, data, len);
+			if (img)
+				/*
+				 * set_account_icon doesn't give us a reference, but we
+				 * unref one below (for the other code path)
+				 */
+				purple_imgstore_ref(img);
+
+			purple_account_set_buddy_icon_path(box->account, filename);
+
+			purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL));
 		}
 	} else {
 		GList *accounts;
 		for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
 			PurpleAccount *account = accounts->data;
-			PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(account));
-			if (plug) {
-				PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug);
-				if (prplinfo != NULL &&
-				    purple_account_get_bool(account, "use-global-buddyicon", TRUE) &&
-				    prplinfo->icon_spec.format) {
-					gpointer data = NULL;
-					size_t len = 0;
-					if (filename)
-						data = pidgin_convert_buddy_icon(plug, filename, &len);
-					purple_buddy_icons_set_account_icon(account, data, len);
-					purple_account_set_buddy_icon_path(account, filename);
-				}
+			PurpleProtocol *protocol =
+					purple_find_protocol_info(purple_account_get_protocol_id(account));
+			if (protocol != NULL &&
+			    purple_account_get_bool(account, "use-global-buddyicon", TRUE) &&
+			    protocol->icon_spec.format) {
+				gpointer data = NULL;
+				size_t len = 0;
+				if (filename)
+					data = pidgin_convert_buddy_icon(protocol, filename, &len);
+				purple_buddy_icons_set_account_icon(account, data, len);
+				purple_account_set_buddy_icon_path(account, filename);
 			}
 		}
 
--- a/pidgin/gtkthemes.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkthemes.c	Sun Aug 18 01:53:00 2013 +0530
@@ -25,7 +25,7 @@
 
 #include "conversation.h"
 #include "debug.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 
 #include "gtkconv.h"
@@ -396,7 +396,7 @@
 }
 
 GSList *pidgin_themes_get_proto_smileys(const char *id) {
-	PurplePlugin *proto;
+	PurpleProtocol *protocol;
 	struct smiley_list *list, *def;
 
 	if ((current_smiley_theme == NULL) || (current_smiley_theme->list == NULL))
@@ -407,12 +407,12 @@
 	if (id == NULL)
 		return def->smileys;
 
-	proto = purple_find_prpl(id);
+	protocol = purple_find_protocol_info(id);
 
 	while (list) {
 		if (!strcmp(list->sml, "default"))
 			def = list;
-		else if (proto && !strcmp(proto->info->name, list->sml))
+		else if (protocol && !strcmp(protocol->name, list->sml))
 			break;
 
 		list = list->next;
--- a/pidgin/gtkutils.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkutils.c	Sun Aug 18 01:53:00 2013 +0530
@@ -49,7 +49,7 @@
 #include "imgstore.h"
 #include "notify.h"
 #include "prefs.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "request.h"
 #include "signals.h"
 #include "sound.h"
@@ -549,19 +549,17 @@
 }
 
 static GdkPixbuf *
-pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account)
+pidgin_create_protocol_icon_from_protocol(PurpleProtocol *protocol, PidginPrplIconSize size, PurpleAccount *account)
 {
-	PurplePluginProtocolInfo *prpl_info;
 	const char *protoname = NULL;
 	char *tmp;
 	char *filename = NULL;
 	GdkPixbuf *pixbuf;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-	if (prpl_info->list_icon == NULL)
+	if (protocol->list_icon == NULL)
 		return NULL;
 
-	protoname = prpl_info->list_icon(account, NULL);
+	protoname = protocol->list_icon(account, NULL);
 	if (protoname == NULL)
 		return NULL;
 
@@ -572,8 +570,8 @@
 	tmp = g_strconcat(protoname, ".png", NULL);
 
 	filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-				    size == PIDGIN_PRPL_ICON_SMALL ? "16" :
-				    size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48",
+				    size == PIDGIN_PROTOCOL_ICON_SMALL ? "16" :
+				    size == PIDGIN_PROTOCOL_ICON_MEDIUM ? "22" : "48",
 				    tmp, NULL);
 	g_free(tmp);
 
@@ -626,7 +624,7 @@
 create_protocols_menu(const char *default_proto_id)
 {
 	AopMenu *aop_menu = NULL;
-	PurplePlugin *plugin;
+	PurpleProtocol *protocol;
 	GdkPixbuf *pixbuf = NULL;
 	GtkTreeIter iter;
 	GtkListStore *ls;
@@ -639,25 +637,25 @@
 	aop_menu->default_item = 0;
 	aop_menu->model = GTK_TREE_MODEL(ls);
 
-	for (p = purple_plugins_get_protocols(), i = 0;
+	for (p = purple_protocols_get_all(), i = 0;
 		 p != NULL;
 		 p = p->next, i++) {
 
-		plugin = (PurplePlugin *)p->data;
-
-		pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
+		protocol = (PurpleProtocol *)p->data;
+
+		pixbuf = pidgin_create_protocol_icon_from_protocol(protocol, PIDGIN_PROTOCOL_ICON_SMALL, NULL);
 
 		gtk_list_store_append(ls, &iter);
 		gtk_list_store_set(ls, &iter,
 		                   AOP_ICON_COLUMN, pixbuf,
-		                   AOP_NAME_COLUMN, plugin->info->name,
-		                   AOP_DATA_COLUMN, plugin->info->id,
+		                   AOP_NAME_COLUMN, protocol->name,
+		                   AOP_DATA_COLUMN, protocol->id,
 		                   -1);
 
 		if (pixbuf)
 			g_object_unref(pixbuf);
 
-		if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id))
+		if (default_proto_id != NULL && !strcmp(protocol->id, default_proto_id))
 			aop_menu->default_item = i;
 	}
 
@@ -722,7 +720,7 @@
 			continue;
 		}
 
-		pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+		pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 
 		if (pixbuf) {
 			if (purple_account_is_disconnected(account) && show_all &&
@@ -911,24 +909,24 @@
 void pidgin_retrieve_user_info_in_chat(PurpleConnection *conn, const char *name, int chat)
 {
 	char *who = NULL;
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 
 	if (chat < 0) {
 		pidgin_retrieve_user_info(conn, name);
 		return;
 	}
 
-	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) {
+	protocol = purple_connection_get_protocol_info(conn);
+	if (protocol != NULL && protocol->get_cb_real_name)
+		who = protocol->get_cb_real_name(conn, chat, name);
+	if (protocol == NULL || protocol->get_cb_info == NULL) {
 		pidgin_retrieve_user_info(conn, who ? who : name);
 		g_free(who);
 		return;
 	}
 
 	show_retrieveing_info(conn, who ? who : name);
-	prpl_info->get_cb_info(conn, chat, name);
+	protocol->get_cb_info(conn, chat, name);
 	g_free(who);
 }
 
@@ -937,9 +935,9 @@
 							PurpleAccount **ret_account, char **ret_protocol,
 							char **ret_username, char **ret_alias)
 {
-	char *protocol = NULL;
-	char *username = NULL;
-	char *alias    = NULL;
+	char *protocol_id = NULL;
+	char *username    = NULL;
+	char *alias       = NULL;
 	char *str;
 	char *s;
 	gboolean valid;
@@ -988,18 +986,18 @@
 			if (!g_ascii_strcasecmp(key, "X-IM-Username:"))
 				username = g_strdup(value);
 			else if (!g_ascii_strcasecmp(key, "X-IM-Protocol:"))
-				protocol = g_strdup(value);
+				protocol_id = g_strdup(value);
 			else if (!g_ascii_strcasecmp(key, "X-IM-Alias:"))
 				alias = g_strdup(value);
 		}
 	}
 
-	if (username != NULL && protocol != NULL)
+	if (username != NULL && protocol_id != NULL)
 	{
 		valid = TRUE;
 
 		*ret_username = username;
-		*ret_protocol = protocol;
+		*ret_protocol = protocol_id;
 
 		if (ret_alias != NULL)
 			*ret_alias = alias;
@@ -1020,76 +1018,70 @@
 			for (l = list; l != NULL; l = l->next)
 			{
 				PurpleConnection *gc;
-				PurplePluginProtocolInfo *prpl_info = NULL;
-				PurplePlugin *plugin;
+				PurpleProtocol *protocol = NULL;
 
 				if (all_accounts)
 				{
 					account = (PurpleAccount *)l->data;
 
-					plugin = purple_plugins_find_with_id(
+					protocol = purple_find_protocol_info(
 						purple_account_get_protocol_id(account));
 
-					if (plugin == NULL)
+					if (protocol == NULL)
 					{
 						account = NULL;
 
 						continue;
 					}
-
-					prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 				}
 				else
 				{
 					gc = (PurpleConnection *)l->data;
 					account = purple_connection_get_account(gc);
 
-					prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+					protocol = purple_connection_get_protocol_info(gc);
 				}
 
-				protoname = prpl_info->list_icon(account, NULL);
-
-				if (!strcmp(protoname, protocol))
+				protoname = protocol->list_icon(account, NULL);
+
+				if (!strcmp(protoname, protocol_id))
 					break;
 
 				account = NULL;
 			}
 
 			/* Special case for AIM and ICQ */
-			if (account == NULL && (!strcmp(protocol, "aim") ||
-									!strcmp(protocol, "icq")))
+			if (account == NULL && (!strcmp(protocol_id, "aim") ||
+									!strcmp(protocol_id, "icq")))
 			{
 				for (l = list; l != NULL; l = l->next)
 				{
 					PurpleConnection *gc;
-					PurplePluginProtocolInfo *prpl_info = NULL;
-					PurplePlugin *plugin;
+					PurpleProtocol *protocol = NULL;
 
 					if (all_accounts)
 					{
 						account = (PurpleAccount *)l->data;
 
-						plugin = purple_plugins_find_with_id(
+						protocol = purple_find_protocol_info(
 							purple_account_get_protocol_id(account));
 
-						if (plugin == NULL)
+						if (protocol == NULL)
 						{
 							account = NULL;
 
 							continue;
 						}
-
-						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 					}
 					else
 					{
 						gc = (PurpleConnection *)l->data;
 						account = purple_connection_get_account(gc);
 
-						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+						protocol = purple_connection_get_protocol_info(gc);
 					}
 
-					protoname = prpl_info->list_icon(account, NULL);
+					protoname = protocol->list_icon(account, NULL);
 
 					if (!strcmp(protoname, "aim") || !strcmp(protoname, "icq"))
 						break;
@@ -1106,7 +1098,7 @@
 		valid = FALSE;
 
 		g_free(username);
-		g_free(protocol);
+		g_free(protocol_id);
 		g_free(alias);
 	}
 
@@ -1446,7 +1438,7 @@
 	GdkPixbuf *pb;
 	GList *files = purple_uri_list_extract_filenames((const gchar *) gtk_selection_data_get_data(sd));
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 #ifndef _WIN32
 	PurpleDesktopItem *item;
 #endif
@@ -1495,14 +1487,14 @@
 			data->account = account;
 
 			if (gc)
-				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
-
-			if (prpl_info && prpl_info->options & OPT_PROTO_IM_IMAGE)
+				protocol = purple_connection_get_protocol_info(gc);
+
+			if (protocol && protocol->options & OPT_PROTO_IM_IMAGE)
 				im = TRUE;
 
-			if (prpl_info && prpl_info->can_receive_file)
-				ft = prpl_info->can_receive_file(gc, who);
-			else if (prpl_info && prpl_info->send_file)
+			if (protocol && protocol->can_receive_file)
+				ft = protocol->can_receive_file(gc, who);
+			else if (protocol && protocol->send_file)
 				ft = TRUE;
 
 			if (im && ft)
@@ -1694,16 +1686,16 @@
 }
 
 GdkPixbuf *
-pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size)
+pidgin_create_protocol_icon(PurpleAccount *account, PidginPrplIconSize size)
 {
-	PurplePlugin *prpl;
+	PurpleProtocol *protocol;
 
 	g_return_val_if_fail(account != NULL, NULL);
 
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	if (prpl == NULL)
+	protocol = purple_find_protocol_info(purple_account_get_protocol_id(account));
+	if (protocol == NULL)
 		return NULL;
-	return pidgin_create_prpl_icon_from_prpl(prpl, size, account);
+	return pidgin_create_protocol_icon_from_protocol(protocol, size, account);
 }
 
 static void
@@ -2266,14 +2258,13 @@
 }
 
 gpointer
-pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len)
+pidgin_convert_buddy_icon(PurpleProtocol *protocol, const char *path, size_t *len)
 {
-	PurplePluginProtocolInfo *prpl_info;
 	PurpleBuddyIconSpec *spec;
 	int orig_width, orig_height, new_width, new_height;
 	GdkPixbufFormat *format;
 	char **pixbuf_formats;
-	char **prpl_formats;
+	char **protocol_formats;
 	GError *error = NULL;
 	gchar *contents;
 	gsize length;
@@ -2282,8 +2273,7 @@
 	int i;
 	gchar *tmp;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-	spec = &prpl_info->icon_spec;
+	spec = &protocol->icon_spec;
 	g_return_val_if_fail(spec->format != NULL, NULL);
 
 	format = gdk_pixbuf_get_file_info(path, &orig_width, &orig_height);
@@ -2293,9 +2283,9 @@
 	}
 
 	pixbuf_formats = gdk_pixbuf_format_get_extensions(format);
-	prpl_formats = g_strsplit(spec->format, ",", 0);
-
-	if (str_array_match(pixbuf_formats, prpl_formats) && /* This is an acceptable format AND */
+	protocol_formats = g_strsplit(spec->format, ",", 0);
+
+	if (str_array_match(pixbuf_formats, protocol_formats) && /* This is an acceptable format AND */
 		 (!(spec->scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */
 		  (spec->min_width <= orig_width && spec->max_width >= orig_width &&
 		   spec->min_height <= orig_height && spec->max_height >= orig_height))) /* The icon is the correct size */
@@ -2305,7 +2295,7 @@
 		if (!g_file_get_contents(path, &contents, &length, &error)) {
 			purple_debug_warning("buddyicon", "Could not get file contents "
 					"of %s: %s\n", path, error->message);
-			g_strfreev(prpl_formats);
+			g_strfreev(protocol_formats);
 			return NULL;
 		}
 
@@ -2314,7 +2304,7 @@
 			   constraints.  Great!  Return it without making any changes. */
 			if (len)
 				*len = length;
-			g_strfreev(prpl_formats);
+			g_strfreev(protocol_formats);
 			return contents;
 		}
 
@@ -2330,7 +2320,7 @@
 		purple_debug_warning("buddyicon", "Could not open icon '%s' for "
 				"conversion: %s\n", path, error->message);
 		g_error_free(error);
-		g_strfreev(prpl_formats);
+		g_strfreev(protocol_formats);
 		return NULL;
 	}
 	original = g_object_ref(G_OBJECT(pixbuf));
@@ -2351,31 +2341,31 @@
 
 	scale_factor = 1;
 	do {
-		for (i = 0; prpl_formats[i]; i++) {
+		for (i = 0; protocol_formats[i]; i++) {
 			int quality = 100;
 			do {
 				const char *key = NULL;
 				const char *value = NULL;
 				gchar tmp_buf[4];
 
-				purple_debug_info("buddyicon", "Converting buddy icon to %s\n", prpl_formats[i]);
-
-				if (g_str_equal(prpl_formats[i], "png")) {
+				purple_debug_info("buddyicon", "Converting buddy icon to %s\n", protocol_formats[i]);
+
+				if (g_str_equal(protocol_formats[i], "png")) {
 					key = "compression";
 					value = "9";
-				} else if (g_str_equal(prpl_formats[i], "jpeg")) {
+				} else if (g_str_equal(protocol_formats[i], "jpeg")) {
 					sprintf(tmp_buf, "%u", quality);
 					key = "quality";
 					value = tmp_buf;
 				}
 
 				if (!gdk_pixbuf_save_to_buffer(pixbuf, &contents, &length,
-						prpl_formats[i], &error, key, value, NULL))
+						protocol_formats[i], &error, key, value, NULL))
 				{
 					/* The NULL checking of error is necessary due to this bug:
 					 * http://bugzilla.gnome.org/show_bug.cgi?id=405539 */
 					purple_debug_warning("buddyicon",
-							"Could not convert to %s: %s\n", prpl_formats[i],
+							"Could not convert to %s: %s\n", protocol_formats[i],
 							(error && error->message) ? error->message : "Unknown error");
 					g_error_free(error);
 					error = NULL;
@@ -2393,10 +2383,10 @@
 							"%dx%d to %dx%d, format=%s, quality=%u, "
 							"filesize=%" G_GSIZE_FORMAT "\n",
 							orig_width, orig_height, new_width, new_height,
-							prpl_formats[i], quality, length);
+							protocol_formats[i], quality, length);
 					if (len)
 						*len = length;
-					g_strfreev(prpl_formats);
+					g_strfreev(protocol_formats);
 					g_object_unref(G_OBJECT(pixbuf));
 					g_object_unref(G_OBJECT(original));
 					return contents;
@@ -2404,7 +2394,7 @@
 
 				g_free(contents);
 
-				if (!g_str_equal(prpl_formats[i], "jpeg")) {
+				if (!g_str_equal(protocol_formats[i], "jpeg")) {
 					/* File size was too big and we can't lower the quality,
 					   so skip to the next image type. */
 					break;
@@ -2424,12 +2414,12 @@
 		g_object_unref(G_OBJECT(pixbuf));
 		pixbuf = gdk_pixbuf_scale_simple(original, new_width, new_height, GDK_INTERP_HYPER);
 	} while ((new_width > 10 || new_height > 10) && new_width > spec->min_width && new_height > spec->min_height);
-	g_strfreev(prpl_formats);
+	g_strfreev(protocol_formats);
 	g_object_unref(G_OBJECT(pixbuf));
 	g_object_unref(G_OBJECT(original));
 
 	tmp = g_strdup_printf(_("The file '%s' is too large for %s.  Please try a smaller image.\n"),
-			path, plugin->info->name);
+			path, protocol->name);
 	purple_notify_error(NULL, _("Icon Error"), _("Could not set icon"), tmp);
 	g_free(tmp);
 
--- a/pidgin/gtkutils.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkutils.h	Sun Aug 18 01:53:00 2013 +0530
@@ -28,7 +28,7 @@
 
 #include "gtkconv.h"
 #include "pidgin.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "util.h"
 
 typedef enum
@@ -49,9 +49,9 @@
 
 typedef enum
 {
-	PIDGIN_PRPL_ICON_SMALL,
-	PIDGIN_PRPL_ICON_MEDIUM,
-	PIDGIN_PRPL_ICON_LARGE
+	PIDGIN_PROTOCOL_ICON_SMALL,
+	PIDGIN_PROTOCOL_ICON_MEDIUM,
+	PIDGIN_PROTOCOL_ICON_LARGE
 } PidginPrplIconSize;
 
 #ifndef _WIN32
@@ -514,7 +514,7 @@
  *         to allocate the image buffer, or the image file
  *         contained invalid data.
  */
-GdkPixbuf *pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size);
+GdkPixbuf *pidgin_create_protocol_icon(PurpleAccount *account, PidginPrplIconSize size);
 
 /**
  * Creates a status icon for a given primitve
@@ -593,13 +593,13 @@
 /**
  * Converts a buddy icon to the required size and format
  *
- * @param plugin     The prpl to convert the icon
+ * @param protocol  The prpl to convert the icon
  * @param path       The path of a file to convert
  * @param len        If not @c NULL, the length of the returned data will be set here.
  *
  * @return           The converted image data, or @c NULL if an error occurred.
  */
-gpointer pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len);
+gpointer pidgin_convert_buddy_icon(PurpleProtocol *protocol, const char *path, size_t *len);
 
 /**
  * Converts "->" and "<-" in strings to Unicode arrow characters, for use in referencing
--- a/pidgin/gtkwebviewtoolbar.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkwebviewtoolbar.c	Sun Aug 18 01:53:00 2013 +0530
@@ -979,7 +979,7 @@
 	const gchar *who = purple_conversation_get_name(conv);
 	PurpleConnection *gc = purple_conversation_get_connection(conv);
 
-	purple_prpl_send_attention(gc, who, 0);
+	purple_protocol_send_attention(gc, who, 0);
 	gtk_widget_grab_focus(toolbar->webview);
 }
 
@@ -1625,15 +1625,15 @@
 {
 	GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar);
 	PurpleConnection *gc = purple_conversation_get_connection(conv);
-	PurplePlugin *prpl = purple_connection_get_prpl(gc);
+	PurpleProtocol *protocol = purple_connection_get_protocol_info(gc);
 
 	priv->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_action_set_sensitive(priv->attention,
-		conv && prpl && PURPLE_IS_IM_CONVERSATION(conv) &&
-		PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL);
+		conv && protocol && PURPLE_IS_IM_CONVERSATION(conv) &&
+		protocol->send_attention != NULL);
 
 	gtk_action_set_sensitive(priv->smiley,
 		(gboolean)pidgin_themes_get_proto_smileys(priv->sml));
--- a/pidgin/gtkwhiteboard.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/gtkwhiteboard.c	Sun Aug 18 01:53:00 2013 +0530
@@ -330,7 +330,7 @@
 
 /*
  * Whiteboard start button on conversation window (move this code to gtkconv?
- * and use new prpl_info member?)
+ * and use new protocol member?)
  */
 #if 0
 static void pidginwhiteboard_button_start_press(GtkButton *button, gpointer data)
--- a/pidgin/plugins/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -1,142 +1,143 @@
-DIST_SUBDIRS = cap disco gestures gevolution musicmessaging perl ticker
-
-if BUILD_GEVOLUTION
-GEVOLUTION_DIR = gevolution
-endif
-
-if ENABLE_DBUS
-MUSICMESSAGING_DIR = musicmessaging
-endif
-
-if ENABLE_CAP
-CAP_DIR = cap
-endif
-
-if USE_PERL
-PERL_DIR = perl
-endif
-
-if ENABLE_GESTURES
-GESTURE_DIR = gestures
-endif
-
-SUBDIRS = \
-	$(CAP_DIR) \
-	$(GESTURE_DIR) \
-	$(GEVOLUTION_DIR) \
-	$(MUSICMESSAGING_DIR) \
-	$(PERL_DIR) \
-	disco \
-	ticker
-
-plugindir = $(libdir)/pidgin
-
-convcolors_la_LDFLAGS       = -module -avoid-version
-contact_priority_la_LDFLAGS = -module -avoid-version
-extplacement_la_LDFLAGS     = -module -avoid-version
-gtk_signals_test_la_LDFLAGS = -module -avoid-version
-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
-webkit_la_LDFLAGS           = -module -avoid-version
-xmppconsole_la_LDFLAGS      = -module -avoid-version
-
-if PLUGINS
-
-plugin_LTLIBRARIES = \
-	convcolors.la       \
-	extplacement.la     \
-	gtkbuddynote.la     \
-	history.la          \
-	iconaway.la         \
-	markerline.la       \
-	notify.la           \
-	pidginrc.la         \
-	relnot.la           \
-	sendbutton.la       \
-	spellchk.la         \
-	themeedit.la        \
-	webkit.la           \
-	xmppconsole.la
-
-noinst_LTLIBRARIES = \
-	contact_priority.la \
-	gtk_signals_test.la
-
-convcolors_la_SOURCES       = convcolors.c
-contact_priority_la_SOURCES = contact_priority.c
-extplacement_la_SOURCES     = extplacement.c
-gtk_signals_test_la_SOURCES = gtk-signals-test.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
-webkit_la_SOURCES           = webkit.c
-xmppconsole_la_SOURCES      = xmppconsole.c
-
-convcolors_la_LIBADD        = $(GTK_LIBS)
-contact_priority_la_LIBADD  = $(GTK_LIBS)
-extplacement_la_LIBADD      = $(GTK_LIBS)
-gtk_signals_test_la_LIBADD  = $(GTK_LIBS)
-gtkbuddynote_la_LIBADD      = $(GTK_LIBS)
-history_la_LIBADD           = $(GTK_LIBS)
-iconaway_la_LIBADD          = $(GTK_LIBS)
-markerline_la_LIBADD        = $(GTK_LIBS) $(WEBKIT_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)
-webkit_la_LIBADD            = $(GTK_LIBS) $(WEBKIT_LIBS)
-xmppconsole_la_LIBADD       = $(GTK_LIBS)
-
-endif # PLUGINS
-
-EXTRA_DIST = \
-	Makefile.mingw \
-	mailchk.c \
-	pidgininc.c \
-	raw.c \
-	win32/transparency/Makefile.mingw \
-	win32/transparency/win2ktrans.c \
-	win32/winprefs/gtkappbar.c \
-	win32/winprefs/gtkappbar.h \
-	win32/winprefs/Makefile.mingw \
-	win32/winprefs/winprefs.c
-
-AM_CPPFLAGS = \
-	-DDATADIR=\"$(datadir)\" \
-	-I$(top_builddir)/libpurple \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_srcdir)/pidgin \
-	$(DEBUG_CFLAGS) \
-	$(GTK_CFLAGS) \
-	$(WEBKIT_CFLAGS) \
-	$(GSTREAMER_CFLAGS) \
-	$(PLUGIN_CFLAGS)
-
+#DIST_SUBDIRS = cap disco gestures gevolution musicmessaging perl ticker
+#
+#if BUILD_GEVOLUTION
+#GEVOLUTION_DIR = gevolution
+#endif
+#
+#if ENABLE_DBUS
+#MUSICMESSAGING_DIR = musicmessaging
+#endif
+#
+#if ENABLE_CAP
+#CAP_DIR = cap
+#endif
+#
+#if USE_PERL
+#PERL_DIR = perl
+#endif
+#
+#if ENABLE_GESTURES
+#GESTURE_DIR = gestures
+#endif
+#
+#SUBDIRS = \
+#	$(CAP_DIR) \
+#	$(GESTURE_DIR) \
+#	$(GEVOLUTION_DIR) \
+#	$(MUSICMESSAGING_DIR) \
+#	$(PERL_DIR) \
+#	disco \
+#	ticker
+#
+#plugindir = $(libdir)/pidgin
+#
+#convcolors_la_LDFLAGS       = -module -avoid-version
+#contact_priority_la_LDFLAGS = -module -avoid-version
+#extplacement_la_LDFLAGS     = -module -avoid-version
+#gtk_signals_test_la_LDFLAGS = -module -avoid-version
+#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
+#webkit_la_LDFLAGS           = -module -avoid-version
+#xmppconsole_la_LDFLAGS      = -module -avoid-version
+#
+#if PLUGINS
+#
+#plugin_LTLIBRARIES = \
+#	convcolors.la       \
+#	extplacement.la     \
+#	gtkbuddynote.la     \
+#	history.la          \
+#	iconaway.la         \
+#	markerline.la       \
+#	notify.la           \
+#	pidginrc.la         \
+#	relnot.la           \
+#	sendbutton.la       \
+#	spellchk.la         \
+#	themeedit.la        \
+#	webkit.la           \
+#	xmppconsole.la
+#
+#noinst_LTLIBRARIES = \
+#	contact_priority.la \
+#	gtk_signals_test.la
 #
-# This part allows people to build their own plugins in here.
-# Yes, it's a mess.
+#convcolors_la_SOURCES       = convcolors.c
+#contact_priority_la_SOURCES = contact_priority.c
+#extplacement_la_SOURCES     = extplacement.c
+#gtk_signals_test_la_SOURCES = gtk-signals-test.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
+#webkit_la_SOURCES           = webkit.c
+#xmppconsole_la_SOURCES      = xmppconsole.c
+#
+#convcolors_la_LIBADD        = $(GTK_LIBS)
+#contact_priority_la_LIBADD  = $(GTK_LIBS)
+#extplacement_la_LIBADD      = $(GTK_LIBS)
+#gtk_signals_test_la_LIBADD  = $(GTK_LIBS)
+#gtkbuddynote_la_LIBADD      = $(GTK_LIBS)
+#history_la_LIBADD           = $(GTK_LIBS)
+#iconaway_la_LIBADD          = $(GTK_LIBS)
+#markerline_la_LIBADD        = $(GTK_LIBS) $(WEBKIT_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)
+#webkit_la_LIBADD            = $(GTK_LIBS) $(WEBKIT_LIBS)
+#xmppconsole_la_LIBADD       = $(GTK_LIBS)
+#
+#endif # PLUGINS
 #
-SUFFIXES = .c .so
-.c.so:
-	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
-	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
-	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
-	@cp .libs/libtmp$@*.so $@
-	@rm -rf .libs/libtmp$@.*
+#EXTRA_DIST = \
+#	Makefile.mingw \
+#	mailchk.c \
+#	pidgininc.c \
+#	raw.c \
+#	win32/transparency/Makefile.mingw \
+#	win32/transparency/win2ktrans.c \
+#	win32/winprefs/gtkappbar.c \
+#	win32/winprefs/gtkappbar.h \
+#	win32/winprefs/Makefile.mingw \
+#	win32/winprefs/winprefs.c
+#
+#AM_CPPFLAGS = \
+#	-DDATADIR=\"$(datadir)\" \
+#	-I$(top_builddir)/libpurple \
+#	-I$(top_srcdir)/libpurple \
+#	-I$(top_srcdir)/pidgin \
+#	$(DEBUG_CFLAGS) \
+#	$(GTK_CFLAGS) \
+#	$(GPLUGIN_CFLAGS) \
+#	$(WEBKIT_CFLAGS) \
+#	$(GSTREAMER_CFLAGS) \
+#	$(PLUGIN_CFLAGS)
+#
+##
+## This part allows people to build their own plugins in here.
+## Yes, it's a mess.
+##
+#SUFFIXES = .c .so
+#.c.so:
+#	$(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS)
+#	$(LIBTOOL) --mode=link    $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS)
+#	@rm -f tmp$@.lo tmp$@.o libtmp$@.la
+#	@cp .libs/libtmp$@*.so $@
+#	@rm -rf .libs/libtmp$@.*
--- a/pidgin/plugins/cap/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/cap/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -24,6 +24,7 @@
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(SQLITE3_CFLAGS)
 
 EXTRA_DIST = Makefile.mingw
--- a/pidgin/plugins/crazychat/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/crazychat/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -36,6 +36,7 @@
 	-I$(top_builddir)/libpurple \
 	-I$(top_srcdir)/pidgin \
 	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(GTKGLEXT_CFLAGS) \
 	$(DEBUG_CPPFLAGS) \
 	$(DEBUG_CFLAGS) \
--- a/pidgin/plugins/crazychat/cc_pidgin_plugin.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/crazychat/cc_pidgin_plugin.c	Sun Aug 18 01:53:00 2013 +0530
@@ -2,7 +2,7 @@
 #include <assert.h>
 
 #include "internal.h"
-#include "plugin.h"
+#include "plugins.h"
 #include "gtkplugin.h"
 #include "gtkblist.h"
 #include "gtkutils.h"
--- a/pidgin/plugins/disco/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/disco/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -25,4 +25,5 @@
 	-I$(top_builddir)/libpurple \
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
-	$(GTK_CFLAGS)
+	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/disco/xmppdisco.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/disco/xmppdisco.c	Sun Aug 18 01:53:00 2013 +0530
@@ -128,7 +128,7 @@
 
 	g_hash_table_remove(iq_callbacks, id);
 	if (g_hash_table_size(iq_callbacks) == 0) {
-		PurplePlugin *prpl = purple_connection_get_prpl(pc);
+		PurplePlugin *prpl = purple_connection_get_protocol_info(pc);
 		iq_listening = FALSE;
 		purple_signal_disconnect(prpl, "jabber-receiving-iq", my_plugin,
 		                         PURPLE_CALLBACK(xmpp_iq_received));
@@ -178,7 +178,7 @@
 	/* Steals id */
 	xmpp_iq_register_callback(pc, id, cbdata, cb);
 
-	purple_signal_emit(purple_connection_get_prpl(pc), "jabber-sending-xmlnode",
+	purple_signal_emit(purple_connection_get_protocol_info(pc), "jabber-sending-xmlnode",
 	                   pc, &iq);
 	if (iq != NULL)
 		xmlnode_free(iq);
@@ -204,7 +204,7 @@
 	/* Steals id */
 	xmpp_iq_register_callback(pc, id, cbdata, cb);
 
-	purple_signal_emit(purple_connection_get_prpl(pc), "jabber-sending-xmlnode",
+	purple_signal_emit(purple_connection_get_protocol_info(pc), "jabber-sending-xmlnode",
 	                   pc, &iq);
 	if (iq != NULL)
 		xmlnode_free(iq);
@@ -578,7 +578,7 @@
 	query = xmlnode_new_child(iq, "query");
 	xmlnode_set_namespace(query, NS_REGISTER);
 
-	purple_signal_emit(purple_connection_get_prpl(service->list->pc),
+	purple_signal_emit(purple_connection_get_protocol_info(service->list->pc),
 			"jabber-sending-xmlnode", service->list->pc, &iq);
 	if (iq != NULL)
 		xmlnode_free(iq);
@@ -617,12 +617,12 @@
 static gboolean
 plugin_load(PurplePlugin *plugin)
 {
-	PurplePlugin *xmpp_prpl;
+	PurplePlugin *xmpp_protocol;
 
 	my_plugin = plugin;
 
-	xmpp_prpl = purple_plugins_find_with_id(XMPP_PLUGIN_ID);
-	if (NULL == xmpp_prpl)
+	xmpp_protocol = purple_plugins_find_with_id(XMPP_PLUGIN_ID);
+	if (NULL == xmpp_protocol)
 		return FALSE;
 
 	purple_signal_connect(purple_connections_get_handle(), "signing-off",
--- a/pidgin/plugins/disco/xmppdisco.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/disco/xmppdisco.h	Sun Aug 18 01:53:00 2013 +0530
@@ -32,7 +32,7 @@
 #define NS_MUC              "http://jabber.org/protocol/muc"
 #define NS_REGISTER         "jabber:iq:register"
 
-#include "plugin.h"
+#include "plugins.h"
 extern PurplePlugin *my_plugin;
 
 /**
--- a/pidgin/plugins/gestures/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gestures/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -23,4 +23,5 @@
 	-I$(top_builddir)/libpurple \
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
-	$(GTK_CFLAGS)
+	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/gevolution/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -26,4 +26,5 @@
 	-I$(top_srcdir)/pidgin \
 	$(EVOLUTION_ADDRESSBOOK_CFLAGS) \
 	$(DEBUG_CFLAGS) \
-	$(GTK_CFLAGS)
+	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/add_buddy_dialog.c	Sun Aug 18 01:53:00 2013 +0530
@@ -32,7 +32,7 @@
 enum
 {
 	COLUMN_NAME,
-	COLUMN_PRPL_ICON,
+	COLUMN_PROTOCOL_ICON,
 	COLUMN_USERNAME,
 	COLUMN_DATA,
 	NUM_COLUMNS
@@ -147,7 +147,7 @@
 	renderer = gtk_cell_renderer_pixbuf_new();
 	gtk_tree_view_column_pack_start(column, renderer, FALSE);
 	gtk_tree_view_column_add_attribute(column, renderer,
-									   "pixbuf", COLUMN_PRPL_ICON);
+									   "pixbuf", COLUMN_PROTOCOL_ICON);
 
 	/* Account name */
 	renderer = gtk_cell_renderer_text_new();
@@ -183,7 +183,7 @@
 	if (account == NULL)
 		return;
 
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 
 	for (l = list; l != NULL; l = l->next)
 	{
@@ -199,7 +199,7 @@
 
 		gtk_list_store_set(dialog->model, &iter,
 						   COLUMN_NAME, name,
-						   COLUMN_PRPL_ICON, pixbuf,
+						   COLUMN_PROTOCOL_ICON, pixbuf,
 						   COLUMN_USERNAME, account_name,
 						   COLUMN_DATA, contact,
 						   -1);
@@ -602,13 +602,13 @@
 	GdkPixbuf *pixbuf;
 	GtkTreeIter iter;
 
-	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 
 	gtk_list_store_append(dialog->model, &iter);
 
 	gtk_list_store_set(dialog->model, &iter,
 					   COLUMN_NAME, name,
-					   COLUMN_PRPL_ICON, pixbuf,
+					   COLUMN_PROTOCOL_ICON, pixbuf,
 					   COLUMN_DATA, contact,
 					   COLUMN_USERNAME, screenname,
 					   -1);
--- a/pidgin/plugins/gevolution/assoc-buddy.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/assoc-buddy.c	Sun Aug 18 01:53:00 2013 +0530
@@ -134,7 +134,7 @@
 {
 	EBook *book;
 	EBookQuery *query;
-	const char *prpl_id;
+	const char *protocol_id;
 	gboolean status;
 	GList *cards, *c;
 	GError *err = NULL;
@@ -188,7 +188,7 @@
 		return;
 	}
 
-	prpl_id = purple_account_get_protocol_id(dialog->buddy->account);
+	protocol_id = purple_account_get_protocol_id(dialog->buddy->account);
 
 	for (c = cards; c != NULL; c = c->next)
 	{
@@ -207,7 +207,7 @@
 						   -1);
 
 		/* See if this user has the buddy in its list. */
-		protocol_field = gevo_prpl_get_field(dialog->buddy->account,
+		protocol_field = gevo_protocol_get_field(dialog->buddy->account,
 											 dialog->buddy);
 
 		if (protocol_field > 0)
@@ -289,7 +289,7 @@
 					   COLUMN_DATA, &contact,
 					   -1);
 
-	protocol_field = gevo_prpl_get_field(dialog->buddy->account, dialog->buddy);
+	protocol_field = gevo_protocol_get_field(dialog->buddy->account, dialog->buddy);
 
 	if (protocol_field == 0)
 		return; /* XXX */
--- a/pidgin/plugins/gevolution/eds-utils.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/eds-utils.c	Sun Aug 18 01:53:00 2013 +0530
@@ -177,7 +177,7 @@
 	EBookQuery *full_query;
 	GSList *groups, *g;
 	EContact *result;
-	EContactField protocol_field = gevo_prpl_get_field(buddy->account, buddy);
+	EContactField protocol_field = gevo_protocol_get_field(buddy->account, buddy);
 
 	if (protocol_field == 0)
 		return NULL;
--- a/pidgin/plugins/gevolution/gevo-util.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/gevo-util.c	Sun Aug 18 01:53:00 2013 +0530
@@ -90,7 +90,7 @@
 }
 
 EContactField
-gevo_prpl_get_field(PurpleAccount *account, PurpleBuddy *buddy)
+gevo_protocol_get_field(PurpleAccount *account, PurpleBuddy *buddy)
 {
 	EContactField protocol_field = 0;
 	const char *protocol_id;
@@ -118,9 +118,9 @@
 }
 
 gboolean
-gevo_prpl_is_supported(PurpleAccount *account, PurpleBuddy *buddy)
+gevo_protocol_is_supported(PurpleAccount *account, PurpleBuddy *buddy)
 {
-	return (gevo_prpl_get_field(account, buddy) != 0);
+	return (gevo_protocol_get_field(account, buddy) != 0);
 }
 
 gboolean
@@ -168,14 +168,14 @@
 	if (mail == NULL)
 	{
 		PurpleAccount *account = purple_buddy_get_account(buddy);
-		const char *prpl_id = purple_account_get_protocol_id(account);
+		const char *protocol_id = purple_account_get_protocol_id(account);
 
-		if (!strcmp(prpl_id, "prpl-msn"))
+		if (!strcmp(protocol_id, "prpl-msn"))
 		{
 			mail = g_strdup(purple_normalize(account,
 										   purple_buddy_get_name(buddy)));
 		}
-		else if (!strcmp(prpl_id, "prpl-yahoo"))
+		else if (!strcmp(protocol_id, "prpl-yahoo"))
 		{
 			mail = g_strdup_printf("%s@yahoo.com",
 								   purple_normalize(account,
--- a/pidgin/plugins/gevolution/gevolution.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/gevolution.c	Sun Aug 18 01:53:00 2013 +0530
@@ -76,7 +76,7 @@
 
 static void
 update_ims_from_contact(EContact *contact, const char *name,
-						const char *prpl_id, EContactField field)
+						const char *protocol_id, EContactField field)
 {
 	GList *ims = e_contact_get(contact, field);
 	GList *l, *l2;
@@ -90,7 +90,7 @@
 		PurpleAccount *account = purple_connection_get_account(gc);
 		char *me;
 
-		if (strcmp(purple_account_get_protocol_id(account), prpl_id))
+		if (strcmp(purple_account_get_protocol_id(account), protocol_id))
 			continue;
 
 		if (!purple_account_get_bool(account, "gevo-autoadd", FALSE))
@@ -274,7 +274,7 @@
 	buddy = PURPLE_BUDDY(node);
 	account = purple_buddy_get_account(buddy);
 
-	if (!gevo_prpl_is_supported(account, buddy))
+	if (!gevo_protocol_is_supported(account, buddy))
 		return;
 
 	contact = gevo_search_buddy_in_contacts(buddy, NULL);
@@ -489,7 +489,7 @@
 
 		gtk_list_store_append(model, &iter);
 
-		pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+		pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
 		if ((pixbuf != NULL) && (!purple_account_is_connected(account)))
 			gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
 
--- a/pidgin/plugins/gevolution/gevolution.h	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/gevolution/gevolution.h	Sun Aug 18 01:53:00 2013 +0530
@@ -121,8 +121,8 @@
 					const char *screenname, const char *alias);
 GList *gevo_get_groups(void);
 
-EContactField gevo_prpl_get_field(PurpleAccount *account, PurpleBuddy *buddy);
-gboolean gevo_prpl_is_supported(PurpleAccount *account, PurpleBuddy *buddy);
+EContactField gevo_protocol_get_field(PurpleAccount *account, PurpleBuddy *buddy);
+gboolean gevo_protocol_is_supported(PurpleAccount *account, PurpleBuddy *buddy);
 gboolean gevo_load_addressbook(const gchar *uri, EBook **book, GError **error);
 char *gevo_get_email_for_buddy(PurpleBuddy *buddy);
 
--- a/pidgin/plugins/musicmessaging/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/musicmessaging/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -43,4 +43,5 @@
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS) \
 	$(DBUS_CFLAGS)
--- a/pidgin/plugins/pidgininc.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/pidgininc.c	Sun Aug 18 01:53:00 2013 +0530
@@ -1,5 +1,5 @@
 #include "internal.h"
-#include "plugin.h"
+#include "plugins.h"
 
 #include "account.h"
 #include "connection.h"
--- a/pidgin/plugins/raw.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/raw.c	Sun Aug 18 01:53:00 2013 +0530
@@ -26,7 +26,7 @@
 
 #include "conversation.h"
 #include "debug.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "version.h"
 
 #include "gtkplugin.h"
@@ -59,7 +59,7 @@
 {
 	const char *txt;
 	PurpleConnection *gc;
-	const char *prpl_id;
+	const char *protocol_id;
 
 	if (account == NULL)
 		return;
@@ -68,11 +68,11 @@
 
 	txt = gtk_entry_get_text(entry);
 
-	prpl_id = purple_account_get_protocol_id(account);
+	protocol_id = purple_account_get_protocol_id(account);
 
-	purple_debug_misc("raw", "prpl_id = %s\n", prpl_id);
+	purple_debug_misc("raw", "protocol_id = %s\n", protocol_id);
 
-	if (strcmp(prpl_id, "prpl-toc") == 0) {
+	if (strcmp(protocol_id, "prpl-toc") == 0) {
 		int *a = (int *)gc->proto_data;
 		unsigned short seqno = htons(a[1]++ & 0xffff);
 		unsigned short len = htons(strlen(txt) + 1);
@@ -82,23 +82,23 @@
 		write(*a, txt, ntohs(len));
 		purple_debug(PURPLE_DEBUG_MISC, "raw", "TOC C: %s\n", txt);
 
-	} else if (strcmp(prpl_id, "prpl-msn") == 0) {
+	} else if (strcmp(protocol_id, "prpl-msn") == 0) {
 		MsnSession *session = gc->proto_data;
 		char buf[strlen(txt) + 3];
 
 		g_snprintf(buf, sizeof(buf), "%s\r\n", txt);
 		msn_servconn_write(session->notification->servconn, buf, strlen(buf));
 
-	} else if (strcmp(prpl_id, "prpl-irc") == 0) {
+	} else if (strcmp(protocol_id, "prpl-irc") == 0) {
 		write(*(int *)gc->proto_data, txt, strlen(txt));
 		write(*(int *)gc->proto_data, "\r\n", 2);
 		purple_debug(PURPLE_DEBUG_MISC, "raw", "IRC C: %s\n", txt);
 
-	} else if (strcmp(prpl_id, "prpl-jabber") == 0) {
+	} else if (strcmp(protocol_id, "prpl-jabber") == 0) {
 		jabber_send_raw((JabberStream *)gc->proto_data, txt, -1);
 
 	} else {
-		purple_debug_error("raw", "Unknown protocol ID %s\n", prpl_id);
+		purple_debug_error("raw", "Unknown protocol ID %s\n", protocol_id);
 	}
 
 	gtk_entry_set_text(entry, "");
--- a/pidgin/plugins/ticker/Makefile.am	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/ticker/Makefile.am	Sun Aug 18 01:53:00 2013 +0530
@@ -24,4 +24,5 @@
 	-I$(top_builddir)/libpurple \
 	-I$(top_srcdir)/pidgin \
 	$(DEBUG_CFLAGS) \
-	$(GTK_CFLAGS)
+	$(GTK_CFLAGS) \
+	$(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/ticker/ticker.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/ticker/ticker.c	Sun Aug 18 01:53:00 2013 +0530
@@ -30,7 +30,7 @@
 #include "buddylist.h"
 #include "conversation.h"
 #include "debug.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "signals.h"
 #include "version.h"
 
--- a/pidgin/plugins/xmppconsole.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/plugins/xmppconsole.c	Sun Aug 18 01:53:00 2013 +0530
@@ -22,7 +22,7 @@
 #include "internal.h"
 #include "gtkplugin.h"
 #include "version.h"
-#include "prpl.h"
+#include "protocol.h"
 #include "xmlnode.h"
 
 #include "gtkimhtml.h"
@@ -194,7 +194,7 @@
 static gboolean
 message_send_cb(GtkWidget *widget, GdkEventKey *event, gpointer p)
 {
-	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleConnection *gc;
 	gchar *text;
 
@@ -204,12 +204,12 @@
 	gc = console->gc;
 
 	if (gc)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
+		protocol = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_protocol_info(gc));
 
 	text = gtk_webview_get_body_text(GTK_WEBVIEW(widget));
 
-	if (prpl_info && prpl_info->send_raw != NULL)
-		prpl_info->send_raw(gc, text, strlen(text));
+	if (protocol && protocol->send_raw != NULL)
+		protocol->send_raw(gc, text, strlen(text));
 
 	g_free(text);
 	gtk_webview_load_html_string(GTK_WEBVIEW(console->entry), "");
@@ -711,7 +711,7 @@
 {
 	PurplePlugin *jabber;
 
-	jabber = purple_find_prpl("prpl-jabber");
+	jabber = purple_find_protocol_info("prpl-jabber");
 	if (!jabber)
 		return FALSE;
 
--- a/pidgin/smileyparser.c	Sun Aug 18 01:52:32 2013 +0530
+++ b/pidgin/smileyparser.c	Sun Aug 18 01:53:00 2013 +0530
@@ -138,9 +138,9 @@
 	const char *proto_name = "default";
 
 	if (proto_id != NULL) {
-		PurplePlugin *proto;
-		proto = purple_find_prpl(proto_id);
-		proto_name = proto->info->name;
+		PurpleProtocol *protocol;
+		protocol = purple_find_protocol_info(proto_id);
+		proto_name = protocol->name;
 	}
 
 	/* unnecessarily slow, but lets manage for now. */

mercurial