diff -ru extract/pidgin-2.10.9/libpurple/account.c libpurple/account.c
--- extract/pidgin-2.10.9/libpurple/account.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/account.c	2015-05-04 13:42:04.464970479 +0200
@@ -30,7 +30,6 @@
 #include "debug.h"
 #include "network.h"
 #include "notify.h"
-#include "pounce.h"
 #include "prefs.h"
 #include "privacy.h"
 #include "prpl.h"
@@ -41,6 +40,8 @@
 #include "util.h"
 #include "xmlnode.h"
 
+#define schedule_accounts_save()
+
 typedef struct
 {
 	PurpleConnectionErrorInfo *current_error;
@@ -89,6 +90,7 @@
 static void set_current_error(PurpleAccount *account,
 	PurpleConnectionErrorInfo *new_err);
 
+#if 0
 /*********************************************************************
  * Writing to disk                                                   *
  *********************************************************************/
@@ -961,6 +963,7 @@
 
 	return ret;
 }
+#endif
 
 static void
 load_accounts(void)
@@ -969,6 +972,7 @@
 
 	accounts_loaded = TRUE;
 
+#if 0
 	node = purple_util_read_xml_from_file("accounts.xml", _("accounts"));
 
 	if (node == NULL)
@@ -985,6 +989,7 @@
 	xmlnode_free(node);
 
 	_purple_buddy_icons_account_loaded_cb();
+#endif
 }
 
 
@@ -1097,8 +1102,10 @@
 
 	purple_presence_destroy(account->presence);
 
+#if 0
 	if(account->system_log)
 		purple_log_free(account->system_log);
+#endif
 
 	while (account->deny) {
 		g_free(account->deny->data);
@@ -1282,8 +1289,13 @@
 
 	gc = purple_account_get_connection(account);
 	_purple_connection_destroy(gc);
+
+	/* 
+	XXXFlo: disable this until the UI for requesting a password
+	        from the user works in Instantbird
 	if (!purple_account_get_remember_password(account))
 		purple_account_set_password(account, NULL);
+	*/
 	purple_account_set_connection(account, NULL);
 
 	account->disconnecting = FALSE;
@@ -1977,6 +1989,7 @@
 purple_account_set_int(PurpleAccount *account, const char *name, int value)
 {
 	PurpleAccountSetting *setting;
+	PurpleAccountUiOps *ui_ops;
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(name    != NULL);
@@ -1988,6 +2001,11 @@
 
 	g_hash_table_insert(account->settings, g_strdup(name), setting);
 
+	ui_ops = purple_accounts_get_ui_ops();
+
+	if (ui_ops != NULL && ui_ops->set_int != NULL)
+		ui_ops->set_int(account, name, value);
+
 	schedule_accounts_save();
 }
 
@@ -1996,6 +2014,7 @@
 						const char *value)
 {
 	PurpleAccountSetting *setting;
+	PurpleAccountUiOps *ui_ops;
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(name    != NULL);
@@ -2007,6 +2026,11 @@
 
 	g_hash_table_insert(account->settings, g_strdup(name), setting);
 
+	ui_ops = purple_accounts_get_ui_ops();
+
+	if (ui_ops != NULL && ui_ops->set_string != NULL)
+		ui_ops->set_string(account, name, value);
+
 	schedule_accounts_save();
 }
 
@@ -2014,6 +2038,7 @@
 purple_account_set_bool(PurpleAccount *account, const char *name, gboolean value)
 {
 	PurpleAccountSetting *setting;
+	PurpleAccountUiOps *ui_ops;
 
 	g_return_if_fail(account != NULL);
 	g_return_if_fail(name    != NULL);
@@ -2025,6 +2050,11 @@
 
 	g_hash_table_insert(account->settings, g_strdup(name), setting);
 
+	ui_ops = purple_accounts_get_ui_ops();
+
+	if (ui_ops != NULL && ui_ops->set_bool != NULL)
+		ui_ops->set_bool(account, name, value);
+
 	schedule_accounts_save();
 }
 
@@ -2204,7 +2234,7 @@
 
 	p = purple_find_prpl(purple_account_get_protocol_id(account));
 
-	return ((p && p->info->name) ? _(p->info->name) : _("Unknown"));
+	return ((p && p->info->name) ? p->info->name : _("Unknown"));
 }
 
 PurpleConnection *
@@ -2396,6 +2426,7 @@
 						const char *default_value)
 {
 	PurpleAccountSetting *setting;
+	const char *value;
 
 	g_return_val_if_fail(account != NULL, default_value);
 	g_return_val_if_fail(name    != NULL, default_value);
@@ -2407,7 +2438,11 @@
 
 	g_return_val_if_fail(setting->type == PURPLE_PREF_STRING, default_value);
 
-	return setting->value.string;
+	value = setting->value.string;
+	if (value == NULL || !*value)
+		return default_value;
+
+	return value;
 }
 
 gboolean
@@ -2495,6 +2530,7 @@
 	return setting->value.boolean;
 }
 
+#if 0
 PurpleLog *
 purple_account_get_log(PurpleAccount *account, gboolean create)
 {
@@ -2525,6 +2561,7 @@
 		account->system_log = NULL;
 	}
 }
+#endif
 
 void
 purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy)
@@ -2963,9 +3000,6 @@
 			purple_conversation_destroy(conv);
 	}
 
-	/* Remove this account's pounces */
-	purple_pounce_destroy_all_by_account(account);
-
 	/* This will cause the deletion of an old buddy icon. */
 	purple_buddy_icons_set_account_icon(account, NULL, 0);
 
@@ -3147,6 +3181,15 @@
 						 purple_marshal_VOID__POINTER, NULL, 1,
 						 purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT));
 
+	purple_signal_register(handle, "account-status-changing",
+						 purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3,
+						 purple_value_new(PURPLE_TYPE_SUBTYPE,
+										PURPLE_SUBTYPE_ACCOUNT),
+						 purple_value_new(PURPLE_TYPE_SUBTYPE,
+										PURPLE_SUBTYPE_STATUS),
+						 purple_value_new(PURPLE_TYPE_SUBTYPE,
+										PURPLE_SUBTYPE_STATUS));
+
 	purple_signal_register(handle, "account-status-changed",
 						 purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3,
 						 purple_value_new(PURPLE_TYPE_SUBTYPE,
@@ -3232,13 +3275,14 @@
 purple_accounts_uninit(void)
 {
 	gpointer handle = purple_accounts_get_handle();
+#if 0
 	if (save_timer != 0)
 	{
 		purple_timeout_remove(save_timer);
 		save_timer = 0;
 		sync_accounts();
 	}
-
+#endif
 	for (; accounts; accounts = g_list_delete_link(accounts, accounts))
 		purple_account_destroy(accounts->data);
 
diff -ru extract/pidgin-2.10.9/libpurple/account.h libpurple/account.h
--- extract/pidgin-2.10.9/libpurple/account.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/account.h	2015-05-04 13:42:04.464970479 +0200
@@ -115,6 +115,10 @@
 	 */
 	void (*close_account_request)(void *ui_handle);
 
+	void (*set_int)(PurpleAccount *account, const char *name, int value);
+	void (*set_string)(PurpleAccount *account, const char *name, const char *value);
+	void (*set_bool)(PurpleAccount *account, const char *name, gboolean value);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
@@ -944,14 +948,14 @@
  *       if the log has already been closed, which not all loggers deal
  *       with appropriately.
  */
-PurpleLog *purple_account_get_log(PurpleAccount *account, gboolean create);
+/* PurpleLog *purple_account_get_log(PurpleAccount *account, gboolean create); */
 
 /**
  * Frees the system log of an account
  *
  * @param account The account.
  */
-void purple_account_destroy_log(PurpleAccount *account);
+/* void purple_account_destroy_log(PurpleAccount *account); */
 
 /**
  * Adds a buddy to the server-side buddy list for the specified account.
diff -ru extract/pidgin-2.10.9/libpurple/blist.c libpurple/blist.c
--- extract/pidgin-2.10.9/libpurple/blist.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/blist.c	2015-05-04 13:42:04.464970479 +0200
@@ -28,7 +28,6 @@
 #include "dbus-maybe.h"
 #include "debug.h"
 #include "notify.h"
-#include "pounce.h"
 #include "prefs.h"
 #include "privacy.h"
 #include "prpl.h"
@@ -126,6 +125,7 @@
 }
 
 
+#if 0
 /*********************************************************************
  * Writing to disk                                                   *
  *********************************************************************/
@@ -600,15 +600,19 @@
 			parse_chat(group, cnode);
 	}
 }
+#endif
 
 /* TODO: Make static and rename to load_blist */
 void
 purple_blist_load()
 {
+#if 0
 	xmlnode *purple, *blist, *privacy;
+#endif
 
 	blist_loaded = TRUE;
 
+#if 0
 	purple = purple_util_read_xml_from_file("blist.xml", _("buddy list"));
 
 	if (purple == NULL)
@@ -670,6 +674,7 @@
 
 	/* This tells the buddy icon code to do its thing. */
 	_purple_buddy_icons_blist_loaded_cb();
+#endif
 }
 
 
@@ -1623,8 +1628,10 @@
 		((PurpleContact*)bnode->parent)->totalsize--;
 		/* the group totalsize will be taken care of by remove_contact below */
 
-		if (bnode->parent->parent != (PurpleBlistNode*)g)
+		if (bnode->parent->parent != (PurpleBlistNode*)g) {
+			purple_signal_emit(purple_blist_get_handle(), "buddy-removed-from-group", buddy);
 			serv_move_buddy(buddy, (PurpleGroup *)bnode->parent->parent, g);
+		}
 
 		if (bnode->next)
 			bnode->next->prev = bnode->prev;
@@ -2185,9 +2192,6 @@
 	if (ops && ops->remove_node)
 		ops->remove_node(node);
 
-	/* Remove this buddy's pounces */
-	purple_pounce_destroy_all_by_buddy(buddy);
-
 	/* Signal that the buddy has been removed before freeing the memory for it */
 	purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy);
 
@@ -3091,7 +3095,7 @@
 
 	if (!ops)
 		return;
-
+#if 0
 	if (!ops->save_node) {
 		ops->save_node = purple_blist_save_node;
 		overrode = TRUE;
@@ -3111,6 +3115,7 @@
 		purple_debug_warning("blist", "Only some of the blist saving UI ops "
 				"were overridden. This probably is not what you want!\n");
 	}
+#endif
 }
 
 PurpleBlistUiOps *
@@ -3192,6 +3197,11 @@
 						 purple_value_new(PURPLE_TYPE_SUBTYPE,
 										PURPLE_SUBTYPE_BLIST_BUDDY));
 
+	purple_signal_register(handle, "buddy-removed-from-group",
+						 purple_marshal_VOID__POINTER, NULL, 1,
+						 purple_value_new(PURPLE_TYPE_SUBTYPE,
+										PURPLE_SUBTYPE_BLIST_BUDDY));
+
 	purple_signal_register(handle, "buddy-icon-changed",
 						 purple_marshal_VOID__POINTER, NULL, 1,
 						 purple_value_new(PURPLE_TYPE_SUBTYPE,
@@ -3238,11 +3248,13 @@
 	if (purplebuddylist == NULL)
 		return;
 
+#if 0
 	if (save_timer != 0) {
 		purple_timeout_remove(save_timer);
 		save_timer = 0;
 		purple_blist_sync();
 	}
+#endif
 
 	purple_blist_destroy();
 
diff -ru extract/pidgin-2.10.9/libpurple/blist.h libpurple/blist.h
--- extract/pidgin-2.10.9/libpurple/blist.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/blist.h	2015-05-04 13:42:04.468970479 +0200
@@ -106,9 +106,35 @@
  */
 #define PURPLE_CHAT(obj) ((PurpleChat *)(obj))
 
+#if 0
+#include "media.h"
+#else
+/** extracted from media.h */
+/** Media caps */
+typedef enum {
+	PURPLE_MEDIA_CAPS_NONE = 0,
+	PURPLE_MEDIA_CAPS_AUDIO = 1,
+	PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION = 1 << 1,
+	PURPLE_MEDIA_CAPS_VIDEO = 1 << 2,
+	PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION = 1 << 3,
+	PURPLE_MEDIA_CAPS_AUDIO_VIDEO = 1 << 4,
+	PURPLE_MEDIA_CAPS_MODIFY_SESSION = 1 << 5,
+	PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6
+} PurpleMediaCaps;
+
+/** Media session types */
+typedef enum {
+	PURPLE_MEDIA_NONE	= 0,
+	PURPLE_MEDIA_RECV_AUDIO = 1 << 0,
+	PURPLE_MEDIA_SEND_AUDIO = 1 << 1,
+	PURPLE_MEDIA_RECV_VIDEO = 1 << 2,
+	PURPLE_MEDIA_SEND_VIDEO = 1 << 3,
+	PURPLE_MEDIA_AUDIO = PURPLE_MEDIA_RECV_AUDIO | PURPLE_MEDIA_SEND_AUDIO,
+	PURPLE_MEDIA_VIDEO = PURPLE_MEDIA_RECV_VIDEO | PURPLE_MEDIA_SEND_VIDEO
+} PurpleMediaSessionType;
+#endif
 #include "account.h"
 #include "buddyicon.h"
-#include "media.h"
 #include "status.h"
 
 /**************************************************************************/
@@ -1088,7 +1114,7 @@
  * the buddy list is saved automatically, so you should not need to
  * call this.
  */
-void purple_blist_schedule_save(void);
+/* void purple_blist_schedule_save(void); */
 
 /**
  * Requests from the user information needed to add a buddy to the
diff -ru extract/pidgin-2.10.9/libpurple/buddyicon.c libpurple/buddyicon.c
--- extract/pidgin-2.10.9/libpurple/buddyicon.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/buddyicon.c	2015-05-04 13:42:04.468970479 +0200
@@ -187,6 +187,9 @@
 
 	g_return_if_fail(filename != NULL);
 
+	if (!purple_buddy_icons_is_caching())
+		return;
+
 	/* It's possible that there are other references to this icon
 	 * cache file that are not currently loaded into memory. */
 	if (GPOINTER_TO_INT(g_hash_table_lookup(icon_file_cache, filename)))
@@ -1123,31 +1126,34 @@
 }
 
 void
-_purple_buddy_icons_account_loaded_cb()
+purple_buddy_icons_account_loaded(PurpleAccount *account)
 {
-	const char *dirname = purple_buddy_icons_get_cache_dir();
-	GList *cur;
+	const char *account_icon_file = purple_account_get_string(account, "buddy_icon", NULL);
 
-	for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next)
+	if (account_icon_file != NULL)
 	{
-		PurpleAccount *account = cur->data;
-		const char *account_icon_file = purple_account_get_string(account, "buddy_icon", NULL);
-
-		if (account_icon_file != NULL)
+		const char *dirname = purple_buddy_icons_get_cache_dir();
+		char *path = g_build_filename(dirname, account_icon_file, NULL);
+		if (!g_file_test(path, G_FILE_TEST_EXISTS))
 		{
-			char *path = g_build_filename(dirname, account_icon_file, NULL);
-			if (!g_file_test(path, G_FILE_TEST_EXISTS))
-			{
-				purple_account_set_string(account, "buddy_icon", NULL);
-			} else {
-				ref_filename(account_icon_file);
-			}
-			g_free(path);
+			purple_account_set_string(account, "buddy_icon", NULL);
+		} else {
+			ref_filename(account_icon_file);
 		}
+		g_free(path);
 	}
 }
 
 void
+_purple_buddy_icons_account_loaded_cb()
+{
+	GList *cur;
+
+	for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next)
+		purple_buddy_icons_account_loaded(cur->data);
+}
+
+void
 _purple_buddy_icons_blist_loaded_cb()
 {
 	PurpleBlistNode *node = purple_blist_get_root();
diff -ru extract/pidgin-2.10.9/libpurple/buddyicon.h libpurple/buddyicon.h
--- extract/pidgin-2.10.9/libpurple/buddyicon.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/buddyicon.h	2015-05-04 13:42:04.468970479 +0200
@@ -270,6 +270,17 @@
 purple_buddy_icons_get_account_icon_timestamp(PurpleAccount *account);
 
 /**
+ * References the current icon of the loaded account.
+ *
+ * UIs should call this after loading an account, if the accounts
+ * aren't stored in the accounts.xml libpurple file.
+ *
+ * @param account The account
+ */
+void
+purple_buddy_icons_account_loaded(PurpleAccount *account);
+
+/**
  * Returns a boolean indicating if a given blist node has a custom buddy icon.
  *
  * @param node The blist node.
Only in extract/pidgin-2.10.9/libpurple: certificate.c
Only in extract/pidgin-2.10.9/libpurple: certificate.h
diff -ru extract/pidgin-2.10.9/libpurple/cmds.c libpurple/cmds.c
--- extract/pidgin-2.10.9/libpurple/cmds.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/cmds.c	2015-05-04 13:42:04.476970478 +0200
@@ -27,10 +27,11 @@
 #include "util.h"
 #include "cmds.h"
 
+static PurpleCommandsUiOps *cmds_ui_ops = NULL;
 static GList *cmds = NULL;
 static guint next_id = 1;
 
-typedef struct _PurpleCmd {
+struct _PurpleCmd {
 	PurpleCmdId id;
 	gchar *cmd;
 	gchar *args;
@@ -40,7 +41,7 @@
 	PurpleCmdFunc func;
 	gchar *help;
 	void *data;
-} PurpleCmd;
+};
 
 
 static gint cmds_compare_func(const PurpleCmd *a, const PurpleCmd *b)
@@ -59,6 +60,7 @@
 {
 	PurpleCmdId id;
 	PurpleCmd *c;
+	PurpleCommandsUiOps *ops;
 
 	g_return_val_if_fail(cmd != NULL && *cmd != '\0', 0);
 	g_return_val_if_fail(args != NULL, 0);
@@ -79,6 +81,10 @@
 
 	cmds = g_list_insert_sorted(cmds, c, (GCompareFunc)cmds_compare_func);
 
+	ops = purple_cmds_get_ui_ops();
+	if (ops && ops->register_command)
+		ops->register_command(cmd, p, f, prpl_id, helpstr, c);
+
 	purple_signal_emit(purple_cmds_get_handle(), "cmd-added", cmd, p, f);
 
 	return id;
@@ -102,6 +108,10 @@
 		c = l->data;
 
 		if (c->id == id) {
+			PurpleCommandsUiOps *ops = purple_cmds_get_ui_ops();
+			if (ops && ops->unregister_command)
+				ops->unregister_command(c->cmd, c->prpl_id);
+
 			cmds = g_list_remove(cmds, c);
 			purple_signal_emit(purple_cmds_get_handle(), "cmd-removed", c->cmd);
 			purple_cmd_free(c);
@@ -301,6 +311,39 @@
 
 }
 
+gboolean purple_cmd_execute(PurpleCmd *c, PurpleConversation *conv,
+			    const gchar *cmdline)
+{
+	gchar *err = NULL;
+	gchar **args = NULL;
+	PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE;
+
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
+		if (!(c->flags & PURPLE_CMD_FLAG_IM))
+			return FALSE;
+	}
+	else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
+		if (!(c->flags & PURPLE_CMD_FLAG_CHAT))
+			return FALSE;
+	}
+	else
+		return FALSE;
+
+	/* XXX: Don't worry much about the markup version of the command
+	   line, there's not a single use case... */
+	/* this checks the allow bad args flag for us */
+	if (!purple_cmd_parse_args(c, cmdline, cmdline, &args)) {
+		g_strfreev(args);
+		return FALSE;
+	}
+
+	ret = c->func(conv, c->cmd, args, &err, c->data);
+
+	g_free(err);
+	g_strfreev(args);
+
+	return ret == PURPLE_CMD_RET_OK;
+}
 
 GList *purple_cmd_list(PurpleConversation *conv)
 {
@@ -368,6 +411,21 @@
 	return &handle;
 }
 
+void
+purple_cmds_set_ui_ops(PurpleCommandsUiOps *ops)
+{
+	cmds_ui_ops = ops;
+}
+
+PurpleCommandsUiOps *
+purple_cmds_get_ui_ops(void)
+{
+	/* It is perfectly acceptable for cmds_ui_ops to be NULL; this just
+	 * means that the default libpurple implementation will be used.
+	 */
+	return cmds_ui_ops;
+}
+
 void purple_cmds_init(void)
 {
 	gpointer handle = purple_cmds_get_handle();
diff -ru extract/pidgin-2.10.9/libpurple/cmds.h libpurple/cmds.h
--- extract/pidgin-2.10.9/libpurple/cmds.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/cmds.h	2015-05-04 13:42:04.476970478 +0200
@@ -31,6 +31,8 @@
 /**************************************************************************/
 /*@{*/
 
+typedef struct _PurpleCmd PurpleCmd;
+
 /** The possible results of running a command with purple_cmd_do_command(). */
 typedef enum _PurpleCmdStatus {
 	PURPLE_CMD_STATUS_OK,
@@ -96,6 +98,31 @@
 	PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS = 0x08
 } PurpleCmdFlag;
 
+/**
+ * Command UI operations;  UIs should implement this if they want to handle
+ * commands themselves, rather than relying on the core.
+ *
+ * @see @ref ui-ops
+ */
+typedef struct
+{
+	/** If implemented, the UI is responsible for handling commands. */
+	/* @see purple_cmd_register for the argument values. */
+	void (*register_command)(const gchar *name, PurpleCmdPriority p,
+				 PurpleCmdFlag f, const gchar *prpl_id,
+				 const gchar *helpstr, PurpleCmd *cmd);
+
+	/** Should be implemented if register_command is implemented.
+	 *  name and prpl_id should have the same value that were used
+	 *  for the register_command call.
+	 */
+	void (*unregister_command)(const gchar *name, const gchar *prpl_id);
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+} PurpleCommandsUiOps;
 
 /*@}*/
 
@@ -194,6 +221,23 @@
                                   const gchar *markup, gchar **errormsg);
 
 /**
+ * Execute a specific command.
+ *
+ * The UI calls this to execute a command, after parsing the
+ * command name.
+ *
+ * @param c The command to execute.
+ * @param conv The conversation the command was typed in.
+ * @param cmdline The command the user typed (only the arguments).
+ *            The caller should remove the prefix and the command name.
+ *            It should not contain any formatting, and should be
+ *            in plain text (no html entities).
+ * @return TRUE if the command handled the cmdline, FALSE otherwise.
+ */
+gboolean purple_cmd_execute(PurpleCmd *c, PurpleConversation *conv,
+			    const gchar *cmdline);
+
+/**
  * List registered commands.
  *
  * Returns a <tt>GList</tt> (which must be freed by the caller) of all commands
@@ -230,6 +274,23 @@
 gpointer purple_cmds_get_handle(void);
 
 /**
+ * Sets the UI operations structure to be used when registering and
+ * unregistering commands.  The UI operations need only be set if the
+ * UI wants to handle the commands itself; otherwise, leave it as NULL.
+ *
+ * @param ops The UI operations structure.
+ */
+void purple_cmds_set_ui_ops(PurpleCommandsUiOps *ops);
+
+/**
+ * Returns the UI operations structure to be used when registering and
+ * unregistering commands.
+ *
+ * @return The UI operations structure.
+ */
+PurpleCommandsUiOps *purple_cmds_get_ui_ops(void);
+
+/**
  * Initialize the commands subsystem.
  * @since 2.5.0
  */
Only in libpurple: config.h
diff -ru extract/pidgin-2.10.9/libpurple/connection.c libpurple/connection.c
--- extract/pidgin-2.10.9/libpurple/connection.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/connection.c	2015-05-04 13:42:04.476970478 +0200
@@ -350,6 +350,7 @@
 		/* Set the time the account came online */
 		purple_presence_set_login_time(presence, time(NULL));
 
+#if 0
 		if (purple_prefs_get_bool("/purple/logging/log_system"))
 		{
 			PurpleLog *log = purple_account_get_log(account, TRUE);
@@ -365,6 +366,7 @@
 				g_free(msg);
 			}
 		}
+#endif
 
 		if (ops != NULL && ops->connected != NULL)
 			ops->connected(gc);
@@ -381,6 +383,7 @@
 	else if (gc->state == PURPLE_DISCONNECTED) {
 		PurpleAccount *account = purple_connection_get_account(gc);
 
+#if 0
 		if (purple_prefs_get_bool("/purple/logging/log_system"))
 		{
 			PurpleLog *log = purple_account_get_log(account, FALSE);
@@ -397,6 +400,7 @@
 		}
 
 		purple_account_destroy_log(account);
+#endif
 
 		if (ops != NULL && ops->disconnected != NULL)
 			ops->disconnected(gc);
diff -ru extract/pidgin-2.10.9/libpurple/conversation.c libpurple/conversation.c
--- extract/pidgin-2.10.9/libpurple/conversation.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/conversation.c	2015-05-04 13:42:04.480970478 +0200
@@ -153,6 +153,7 @@
 
 	type = purple_conversation_get_type(conv);
 
+#if 0
 	/* Always linkfy the text for display, unless we're
 	 * explicitly asked to do otheriwse*/
 	if (!(msgflags & PURPLE_MESSAGE_INVISIBLE)) {
@@ -167,6 +168,12 @@
 		sent = g_strdup(displayed);
 	} else
 		sent = g_strdup(message);
+#else
+	/* send and display as is, linkification has already been
+	   handled by the conversation binding */
+	displayed = g_strdup(message);
+	sent = g_strdup(message);
+#endif
 
 	msgflags |= PURPLE_MESSAGE_SEND;
 
@@ -238,6 +245,7 @@
 	g_free(sent);
 }
 
+#if 0
 static void
 open_log(PurpleConversation *conv)
 {
@@ -245,6 +253,7 @@
 							   PURPLE_LOG_IM, conv->name, conv->account,
 							   conv, time(NULL), NULL));
 }
+#endif
 
 /* Functions that deal with PurpleConvMessage */
 
@@ -307,8 +316,10 @@
 
 	account = purple_conversation_get_account(conv);
 
+#if 0
 	purple_conversation_close_logs(conv);
 	open_log(conv);
+#endif
 
 	gc = purple_account_get_connection(account);
 
@@ -398,11 +409,13 @@
 			purple_buddy_icon_unref(icon);
 		}
 
+#if 0
 		if (purple_prefs_get_bool("/purple/logging/log_ims"))
 		{
 			purple_conversation_set_logging(conv, TRUE);
 			open_log(conv);
 		}
+#endif
 	}
 	else if (type == PURPLE_CONV_TYPE_CHAT)
 	{
@@ -422,11 +435,13 @@
 			purple_conv_chat_set_nick(conv->u.chat,
 									purple_account_get_username(account));
 
+#if 0
 		if (purple_prefs_get_bool("/purple/logging/log_chats"))
 		{
 			purple_conversation_set_logging(conv, TRUE);
 			open_log(conv);
 		}
+#endif
 	}
 
 	conversations = g_list_prepend(conversations, conv);
@@ -598,7 +613,9 @@
 		ops->destroy_conversation(conv);
 	conv->ui_data = NULL;
 
+#if 0
 	purple_conversation_close_logs(conv);
+#endif
 
 	purple_conversation_clear_message_history(conv);
 
@@ -800,6 +817,7 @@
 	return conv->name;
 }
 
+#if 0
 void
 purple_conversation_set_logging(PurpleConversation *conv, gboolean log)
 {
@@ -829,6 +847,7 @@
 	g_list_free(conv->logs);
 	conv->logs = NULL;
 }
+#endif
 
 PurpleConvIm *
 purple_conversation_get_im_data(const PurpleConversation *conv)
@@ -1008,6 +1027,7 @@
 		}
 	}
 
+#if 0
 	if (!(flags & PURPLE_MESSAGE_NO_LOG) && purple_conversation_is_logging(conv)) {
 		GList *log;
 
@@ -1020,6 +1040,7 @@
 			log = log->next;
 		}
 	}
+#endif
 
 	if (ops && ops->write_conv)
 		ops->write_conv(conv, who, alias, displayed, flags, mtime);
@@ -1242,6 +1263,7 @@
 
 	if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) {
 		purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING);
+		purple_conv_im_update_typing(im);
 	}
 
 	/* Pass this on to either the ops structure or the default write func. */
diff -ru extract/pidgin-2.10.9/libpurple/conversation.h libpurple/conversation.h
--- extract/pidgin-2.10.9/libpurple/conversation.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/conversation.h	2015-05-04 13:42:04.480970478 +0200
@@ -568,7 +568,7 @@
  * @param conv The conversation.
  * @param log  @c TRUE if logging should be enabled, or @c FALSE otherwise.
  */
-void purple_conversation_set_logging(PurpleConversation *conv, gboolean log);
+/* void purple_conversation_set_logging(PurpleConversation *conv, gboolean log); */
 
 /**
  * Returns whether or not logging is enabled for this conversation.
@@ -577,7 +577,7 @@
  *
  * @return @c TRUE if logging is enabled, or @c FALSE otherwise.
  */
-gboolean purple_conversation_is_logging(const PurpleConversation *conv);
+/* gboolean purple_conversation_is_logging(const PurpleConversation *conv); */
 
 /**
  * Closes any open logs for this conversation.
@@ -588,7 +588,7 @@
  *
  * @param conv The conversation.
  */
-void purple_conversation_close_logs(PurpleConversation *conv);
+/* void purple_conversation_close_logs(PurpleConversation *conv); */
 
 /**
  * Returns the specified conversation's IM-specific data.
diff -ru extract/pidgin-2.10.9/libpurple/core.c libpurple/core.c
--- extract/pidgin-2.10.9/libpurple/core.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/core.c	2015-05-04 13:42:04.480970478 +0200
@@ -25,7 +25,6 @@
  */
 #include "internal.h"
 #include "cipher.h"
-#include "certificate.h"
 #include "cmds.h"
 #include "connection.h"
 #include "conversation.h"
@@ -38,19 +37,14 @@
 #include "network.h"
 #include "notify.h"
 #include "plugin.h"
-#include "pounce.h"
 #include "prefs.h"
 #include "privacy.h"
 #include "proxy.h"
-#include "savedstatuses.h"
 #include "signals.h"
 #include "smiley.h"
-#include "sound.h"
-#include "sound-theme-loader.h"
 #include "sslconn.h"
 #include "status.h"
 #include "stun.h"
-#include "theme-manager.h"
 #include "util.h"
 
 #ifdef HAVE_DBUS
@@ -63,6 +57,8 @@
 #  include "dbus-bindings.h"
 #endif
 
+#include <libxml/parser.h>
+
 struct PurpleCore
 {
 	char *ui;
@@ -73,7 +69,9 @@
 static PurpleCoreUiOps *_ops  = NULL;
 static PurpleCore      *_core = NULL;
 
+#ifdef STATIC_PROTO_INIT
 STATIC_PROTO_INIT
+#endif
 
 gboolean
 purple_core_init(const char *ui)
@@ -117,8 +115,6 @@
 	 * for protocol prefs to work. */
 	purple_prefs_init();
 
-	purple_debug_init();
-
 	if (ops != NULL)
 	{
 		if (ops->ui_prefs_init != NULL)
@@ -140,12 +136,15 @@
 	 */
 	purple_plugins_init();
 
+#ifdef STATIC_PROTO_INIT
 	/* Initialize all static protocols. */
 	static_proto_init();
+#endif
 
-	purple_plugins_probe(G_MODULE_SUFFIX);
+	if (ops != NULL && ops->register_plugins != NULL)
+		ops->register_plugins();
 
-	purple_theme_manager_init();
+	purple_plugins_probe(G_MODULE_SUFFIX);
 
 	/* The buddy icon code uses the imgstore, so init it early. */
 	purple_imgstore_init();
@@ -158,18 +157,14 @@
 	purple_connections_init();
 
 	purple_accounts_init();
-	purple_savedstatuses_init();
 	purple_notify_init();
-	purple_certificate_init();
 	purple_conversations_init();
 	purple_blist_init();
 	purple_log_init();
 	purple_network_init();
 	purple_privacy_init();
-	purple_pounces_init();
 	purple_proxy_init();
 	purple_dnsquery_init();
-	purple_sound_init();
 	purple_ssl_init();
 	purple_stun_init();
 	purple_xfers_init();
@@ -184,9 +179,6 @@
 	if (ops != NULL && ops->ui_init != NULL)
 		ops->ui_init();
 
-	/* The UI may have registered some theme types, so refresh them */
-	purple_theme_manager_refresh();
-
 	return TRUE;
 }
 
@@ -204,6 +196,7 @@
 	/* Transmission ends */
 	purple_connections_disconnect_all();
 
+#if 0
 	/*
 	 * Certificates must be destroyed before the SSL plugins, because
 	 * PurpleCertificates contain pointers to PurpleCertificateSchemes,
@@ -211,6 +204,7 @@
 	 * SSL plugin is uninit.
 	 */
 	purple_certificate_uninit();
+#endif
 
 	/* The SSL plugins must be uninit before they're unloaded */
 	purple_ssl_uninit();
@@ -223,18 +217,14 @@
 	/* Save .xml files, remove signals, etc. */
 	purple_smileys_uninit();
 	purple_idle_uninit();
-	purple_pounces_uninit();
 	purple_blist_uninit();
 	purple_ciphers_uninit();
 	purple_notify_uninit();
 	purple_conversations_uninit();
 	purple_connections_uninit();
 	purple_buddy_icons_uninit();
-	purple_savedstatuses_uninit();
 	purple_status_uninit();
 	purple_accounts_uninit();
-	purple_sound_uninit();
-	purple_theme_manager_uninit();
 	purple_xfers_uninit();
 	purple_proxy_uninit();
 	purple_dnsquery_uninit();
@@ -271,6 +261,8 @@
 	wpurple_cleanup();
 #endif
 
+        xmlCleanupParser();
+
 	_core = NULL;
 }
 
@@ -403,6 +395,7 @@
 	return TRUE;
 }
 
+#if 0
 gboolean
 purple_core_migrate(void)
 {
@@ -750,6 +743,7 @@
 	g_free(status_file);
 	return TRUE;
 }
+#endif
 
 GHashTable* purple_core_get_ui_info() {
 	PurpleCoreUiOps *ops = purple_core_get_ui_ops();
diff -ru extract/pidgin-2.10.9/libpurple/core.h libpurple/core.h
--- extract/pidgin-2.10.9/libpurple/core.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/core.h	2015-05-04 13:42:04.480970478 +0200
@@ -71,6 +71,11 @@
 	 */
 	GHashTable* (*get_ui_info)(void);
 
+	/** Called during the initialization of the core to give the
+	 *  UI a chance to register static plugins.
+	 */
+	void (*register_plugins)(void);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
@@ -164,7 +169,7 @@
  * @return A boolean indicating success or migration failure. On failure,
  *         the application must display an error to the user and then exit.
  */
-gboolean purple_core_migrate(void);
+/* gboolean purple_core_migrate(void); */
 
 /**
  * Ensures that only one instance is running.  If libpurple is built with D-Bus
Only in extract/pidgin-2.10.9/libpurple: dbus-analyze-functions.py
Only in extract/pidgin-2.10.9/libpurple: dbus-analyze-signals.py
Only in extract/pidgin-2.10.9/libpurple: dbus-analyze-types.py
Only in extract/pidgin-2.10.9/libpurple: dbus-bindings.h
Only in extract/pidgin-2.10.9/libpurple: dbus-define-api.h
Only in extract/pidgin-2.10.9/libpurple: dbus-purple.h
Only in extract/pidgin-2.10.9/libpurple: dbus-server.c
Only in extract/pidgin-2.10.9/libpurple: dbus-server.h
Only in extract/pidgin-2.10.9/libpurple: dbus-types.h
Only in extract/pidgin-2.10.9/libpurple: dbus-useful.c
Only in extract/pidgin-2.10.9/libpurple: dbus-useful.h
diff -ru extract/pidgin-2.10.9/libpurple/debug.c libpurple/debug.c
--- extract/pidgin-2.10.9/libpurple/debug.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/debug.c	2015-05-04 13:42:04.480970478 +0200
@@ -31,18 +31,6 @@
 static PurpleDebugUiOps *debug_ui_ops = NULL;
 
 /*
- * This determines whether debug info should be written to the
- * console or not.
- *
- * It doesn't make sense to make this a normal Purple preference
- * because it's a command line option.  This will always be FALSE,
- * unless the user explicitly started the UI with the -d flag.
- * It doesn't matter what this value was the last time Purple was
- * started, so it doesn't make sense to save it in prefs.
- */
-static gboolean debug_enabled = FALSE;
-
-/*
  * These determine whether verbose or unsafe debugging are desired.  I
  * don't want to make these purple preferences because their values should
  * not be remembered across instances of the UI.
@@ -50,10 +38,12 @@
 static gboolean debug_verbose = FALSE;
 static gboolean debug_unsafe = FALSE;
 
-static void
-purple_debug_vargs(PurpleDebugLevel level, const char *category,
-				 const char *format, va_list args)
+void
+purple_debug_with_location(PurpleDebugLevel level, const char *category,
+			   const char *file, int line, const char *function,
+			   const char *format, ...)
 {
+	va_list args;
 	PurpleDebugUiOps *ops;
 	char *arg_s = NULL;
 
@@ -61,121 +51,88 @@
 	g_return_if_fail(format != NULL);
 
 	ops = purple_debug_get_ui_ops();
-
-	if (!debug_enabled && ((ops == NULL) || (ops->print == NULL) ||
-			(ops->is_enabled && !ops->is_enabled(level, category))))
+	if ((ops == NULL) ||
+	    (ops->print_with_location == NULL && ops->print == NULL) ||
+	    (ops->is_enabled && !ops->is_enabled(level, category)))
 		return;
 
-	arg_s = g_strdup_vprintf(format, args);
-
-	if (debug_enabled) {
-		gchar *ts_s;
-		const char *mdate;
-		time_t mtime = time(NULL);
-
-
-		mdate = purple_utf8_strftime("%H:%M:%S", localtime(&mtime));
-		ts_s = g_strdup_printf("(%s) ", mdate);
-
-		if (category == NULL)
-			g_print("%s%s", ts_s, arg_s);
-		else
-			g_print("%s%s: %s", ts_s, category, arg_s);
-
-		g_free(ts_s);
-	}
+	va_start(args, format);
 
-	if (ops != NULL && ops->print != NULL)
+	arg_s = g_strdup_vprintf(format, args);
+	if (ops->print_with_location != NULL)
+		ops->print_with_location(level, category, file, line, function, arg_s);
+	else
 		ops->print(level, category, arg_s);
-
 	g_free(arg_s);
-}
-
-void
-purple_debug(PurpleDebugLevel level, const char *category,
-		   const char *format, ...)
-{
-	va_list args;
-
-	g_return_if_fail(level != PURPLE_DEBUG_ALL);
-	g_return_if_fail(format != NULL);
-
-	va_start(args, format);
-	purple_debug_vargs(level, category, format, args);
-	va_end(args);
-}
 
-void
-purple_debug_misc(const char *category, const char *format, ...)
-{
-	va_list args;
-
-	g_return_if_fail(format != NULL);
-
-	va_start(args, format);
-	purple_debug_vargs(PURPLE_DEBUG_MISC, category, format, args);
 	va_end(args);
 }
 
-void
-purple_debug_info(const char *category, const char *format, ...)
-{
-	va_list args;
+/* This is kept for ABI compatibility only. Should be removed once we
+ * change the version number and thus can safely assume that all old
+ * plugins will be disabled.
+ * New code uses purple_debug_with_location. */
+#undef purple_debug
+#undef purple_debug_misc
+#undef purple_debug_info
+#undef purple_debug_warning
+#undef purple_debug_error
+#undef purple_debug_fatal
 
-	g_return_if_fail(format != NULL);
-
-	va_start(args, format);
-	purple_debug_vargs(PURPLE_DEBUG_INFO, category, format, args);
-	va_end(args);
-}
-
-void
-purple_debug_warning(const char *category, const char *format, ...)
+static void
+purple_debug_vargs(PurpleDebugLevel level, const char *category,
+				 const char *format, va_list args)
 {
-	va_list args;
+	PurpleDebugUiOps *ops;
+	char *arg_s = NULL;
 
+	g_return_if_fail(level != PURPLE_DEBUG_ALL);
 	g_return_if_fail(format != NULL);
 
-	va_start(args, format);
-	purple_debug_vargs(PURPLE_DEBUG_WARNING, category, format, args);
-	va_end(args);
-}
-
-void
-purple_debug_error(const char *category, const char *format, ...)
-{
-	va_list args;
+	ops = purple_debug_get_ui_ops();
 
-	g_return_if_fail(format != NULL);
+	if ((ops == NULL) || (ops->print == NULL) ||
+	    (ops->is_enabled && !ops->is_enabled(level, category)))
+		return;
 
-	va_start(args, format);
-	purple_debug_vargs(PURPLE_DEBUG_ERROR, category, format, args);
-	va_end(args);
+	arg_s = g_strdup_vprintf(format, args);
+	ops->print(level, category, arg_s);
+	g_free(arg_s);
 }
 
 void
-purple_debug_fatal(const char *category, const char *format, ...)
+purple_debug(PurpleDebugLevel level, const char *category,
+		   const char *format, ...)
 {
 	va_list args;
 
+	g_return_if_fail(level != PURPLE_DEBUG_ALL);
 	g_return_if_fail(format != NULL);
 
 	va_start(args, format);
-	purple_debug_vargs(PURPLE_DEBUG_FATAL, category, format, args);
+	purple_debug_vargs(level, category, format, args);
 	va_end(args);
 }
 
-void
-purple_debug_set_enabled(gboolean enabled)
-{
-	debug_enabled = enabled;
-}
-
-gboolean
-purple_debug_is_enabled()
-{
-	return debug_enabled;
-}
+#define PURPLE_IMPL_DEBUG_HELPER(name, NAME)				  \
+ void									  \
+ purple_debug_##name(const char *category, const char *format, ...)	  \
+ {									  \
+	 va_list args;							  \
+									  \
+	 g_return_if_fail(format != NULL);				  \
+									  \
+	 va_start(args, format);					  \
+	 purple_debug_vargs(PURPLE_DEBUG_##NAME, category, format, args); \
+	 va_end(args);							  \
+ }
+
+PURPLE_IMPL_DEBUG_HELPER(misc, MISC)
+PURPLE_IMPL_DEBUG_HELPER(info, INFO)
+PURPLE_IMPL_DEBUG_HELPER(warning, WARNING)
+PURPLE_IMPL_DEBUG_HELPER(error, ERROR)
+PURPLE_IMPL_DEBUG_HELPER(fatal, FATAL)
+/* End of the code kept for ABI compatibility */
 
 void
 purple_debug_set_ui_ops(PurpleDebugUiOps *ops)
@@ -212,24 +169,3 @@
 {
 	return debug_ui_ops;
 }
-
-void
-purple_debug_init(void)
-{
-	/* Read environment variables once per init */
-	if(g_getenv("PURPLE_UNSAFE_DEBUG"))
-		purple_debug_set_unsafe(TRUE);
-
-	if(g_getenv("PURPLE_VERBOSE_DEBUG"))
-		purple_debug_set_verbose(TRUE);
-
-	purple_prefs_add_none("/purple/debug");
-
-	/*
-	 * This pref is obsolete and no longer referenced anywhere. It only
-	 * survives here because it would be an API break if we removed it.
-	 * Remove this when we get to 3.0.0 :)
-	 */
-	purple_prefs_add_bool("/purple/debug/timestamps", TRUE);
-}
-
diff -ru extract/pidgin-2.10.9/libpurple/debug.h libpurple/debug.h
--- extract/pidgin-2.10.9/libpurple/debug.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/debug.h	2015-05-04 13:42:04.484970478 +0200
@@ -50,6 +50,9 @@
 {
 	void (*print)(PurpleDebugLevel level, const char *category,
 				  const char *arg_s);
+	void (*print_with_location)(PurpleDebugLevel level, const char *category,
+				    const char *file, int line,
+				    const char *function, const char *arg_s);
 	gboolean (*is_enabled)(PurpleDebugLevel level,
 			const char *category);
 
@@ -66,15 +69,43 @@
 /**************************************************************************/
 /** @name Debug API                                                       */
 /**************************************************************************/
+
 /**
  * Outputs debug information.
  *
  * @param level    The debug level.
  * @param category The category (or @c NULL).
+ * @param file     The file containing the calling code.
+ * @param line     The line number.
+ * @param function The calling function.
  * @param format   The format string.
  */
+void purple_debug_with_location(PurpleDebugLevel level, const char *category,
+				const char *file, int line,
+				const char *function, const char *format, ...);
+
+#ifndef _MSC_VER
+/* The use of __VA_ARGS__ will cause gcc to annoyingly output this warning:
+ *  warning: anonymous variadic macros were introduced in C99
+ * Tell it to shut up...
+ */
+#pragma GCC system_header
+#endif
+
+/**
+ * Outputs debug information.
+ *
+ * @param level    The debug level.
+ * @param category The category (or @c NULL).
+ * @param format   The format string.
+ */
+/*
 void purple_debug(PurpleDebugLevel level, const char *category,
 				const char *format, ...) G_GNUC_PRINTF(3, 4);
+*/
+#define purple_debug(level, category, ...)				\
+	purple_debug_with_location(level, category, __FILE__, __LINE__, \
+	                           __FUNCTION__, __VA_ARGS__)
 
 /**
  * Outputs misc. level debug information.
@@ -87,7 +118,11 @@
  *
  * @see purple_debug()
  */
+/*
 void purple_debug_misc(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+*/
+#define purple_debug_misc(category, ...) \
+	purple_debug(PURPLE_DEBUG_MISC, category, __VA_ARGS__)
 
 /**
  * Outputs info level debug information.
@@ -100,7 +135,11 @@
  *
  * @see purple_debug()
  */
+/*
 void purple_debug_info(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+*/
+#define purple_debug_info(category, ...) \
+	purple_debug(PURPLE_DEBUG_INFO, category, __VA_ARGS__)
 
 /**
  * Outputs warning level debug information.
@@ -113,7 +152,11 @@
  *
  * @see purple_debug()
  */
+/*
 void purple_debug_warning(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+*/
+#define purple_debug_warning(category, ...) \
+	purple_debug(PURPLE_DEBUG_WARNING, category, __VA_ARGS__)
 
 /**
  * Outputs error level debug information.
@@ -126,12 +169,16 @@
  *
  * @see purple_debug()
  */
+/*
 void purple_debug_error(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+*/
+#define purple_debug_error(category, ...) \
+	purple_debug(PURPLE_DEBUG_ERROR, category, __VA_ARGS__)
 
 /**
  * Outputs fatal error level debug information.
  *
- * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_ERROR as
+ * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_FATAL as
  * the level.
  *
  * @param category The category (or @c NULL).
@@ -139,21 +186,11 @@
  *
  * @see purple_debug()
  */
+/*
 void purple_debug_fatal(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
-
-/**
- * Enable or disable printing debug output to the console.
- *
- * @param enabled TRUE to enable debug output or FALSE to disable it.
- */
-void purple_debug_set_enabled(gboolean enabled);
-
-/**
- * Check if console debug output is enabled.
- *
- * @return TRUE if debugging is enabled, FALSE if it is not.
- */
-gboolean purple_debug_is_enabled(void);
+*/
+#define purple_debug_fatal(category, ...) \
+	purple_debug(PURPLE_DEBUG_FATAL, category, __VA_ARGS__)
 
 /**
  * Enable or disable verbose debugging.  This ordinarily should only be called
@@ -224,18 +261,6 @@
 
 /*@}*/
 
-/**************************************************************************/
-/** @name Debug Subsystem                                                 */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Initializes the debug subsystem.
- */
-void purple_debug_init(void);
-
-/*@}*/
-
 #ifdef __cplusplus
 }
 #endif
Only in extract/pidgin-2.10.9/libpurple: desktopitem.c
Only in extract/pidgin-2.10.9/libpurple: desktopitem.h
diff -ru extract/pidgin-2.10.9/libpurple/dnsquery.c libpurple/dnsquery.c
--- extract/pidgin-2.10.9/libpurple/dnsquery.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/dnsquery.c	2015-05-04 13:42:04.484970478 +0200
@@ -38,9 +38,6 @@
 #include <resolv.h>
 #endif
 
-#if (defined(__APPLE__) || defined (__unix__)) && !defined(__osf__)
-#define PURPLE_DNSQUERY_USE_FORK
-#endif
 /**************************************************************************
  * DNS query API
  **************************************************************************/
@@ -900,12 +897,8 @@
 		return FALSE;
 	}
 
-	if (purple_dnsquery_ui_resolve(query_data))
-		/* The UI is handling the resolve; we're done */
-		return FALSE;
-
-	resolve_host(query_data);
-
+	g_return_val_if_fail(purple_dnsquery_ui_resolve(query_data), FALSE);
+	/* The UI is handling the resolve; we're done */
 	return FALSE;
 }
 
diff -ru extract/pidgin-2.10.9/libpurple/eventloop.c libpurple/eventloop.c
--- extract/pidgin-2.10.9/libpurple/eventloop.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/eventloop.c	2015-05-04 13:42:04.484970478 +0200
@@ -25,6 +25,7 @@
  */
 #include "internal.h"
 #include "eventloop.h"
+#include "debug.h"
 
 static PurpleEventLoopUiOps *eventloop_ui_ops = NULL;
 
@@ -56,18 +57,30 @@
 }
 
 guint
-purple_input_add(int source, PurpleInputCondition condition, PurpleInputFunction func, gpointer user_data)
+purple_input_add_with_location(int source, PurpleInputCondition condition,
+			       PurpleInputFunction func, gpointer user_data,
+			       const char *file, int line, const char *function)
 {
 	PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops();
 
+	purple_debug_with_location(PURPLE_DEBUG_MISC, "eventloop",
+				   file, line, function,
+				   "purple_input_add, fd = %i", source);
 	return ops->input_add(source, condition, func, user_data);
 }
 
+
+
 gboolean
-purple_input_remove(guint tag)
+purple_input_remove_with_location(guint tag, const char *file, int line,
+				  const char *function)
 {
 	PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops();
 
+	purple_debug_with_location(PURPLE_DEBUG_MISC, "eventloop",
+				   file, line, function,
+				   "purple_input_remove, handle = %i", tag);
+
 	return ops->input_remove(tag);
 }
 
diff -ru extract/pidgin-2.10.9/libpurple/eventloop.h libpurple/eventloop.h
--- extract/pidgin-2.10.9/libpurple/eventloop.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/eventloop.h	2015-05-04 13:42:04.484970478 +0200
@@ -217,8 +217,17 @@
  * @return The resulting handle (will be greater than 0).
  * @see g_io_add_watch_full
  */
-guint purple_input_add(int fd, PurpleInputCondition cond,
-                       PurpleInputFunction func, gpointer user_data);
+/* guint purple_input_add(int fd, PurpleInputCondition cond,
+                       PurpleInputFunction func, gpointer user_data); */
+guint purple_input_add_with_location(int fd, PurpleInputCondition cond,
+				     PurpleInputFunction func,
+				     gpointer user_data,
+				     const char *file, int line,
+				     const char *function);
+
+#define purple_input_add(fd, cond, func, user_data)		      \
+  purple_input_add_with_location(fd, cond, func, user_data, __FILE__, \
+				 __LINE__, __FUNCTION__)
 
 /**
  * Removes an input handler.
@@ -226,7 +235,12 @@
  * @param handle The handle of the input handler. Note that this is the return
  *               value from purple_input_add(), <i>not</i> the file descriptor.
  */
-gboolean purple_input_remove(guint handle);
+/* gboolean purple_input_remove(guint handle); */
+gboolean purple_input_remove_with_location(guint handle, const char *file,
+					   int line, const char *function);
+
+#define purple_input_remove(handle)					     \
+  purple_input_remove_with_location(handle, __FILE__, __LINE__, __FUNCTION__)
 
 /**
  * Get the current error status for an input.
Only in extract/pidgin-2.10.9/libpurple: example
diff -ru extract/pidgin-2.10.9/libpurple/ft.c libpurple/ft.c
--- extract/pidgin-2.10.9/libpurple/ft.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/ft.c	2015-05-04 13:42:04.488970478 +0200
@@ -279,7 +279,7 @@
 	const char *message, gboolean is_error, gboolean print_thumbnail)
 {
 	PurpleConversation *conv = NULL;
-	PurpleMessageFlags flags = PURPLE_MESSAGE_SYSTEM;
+	PurpleMessageFlags flags = PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY;
 	char *escaped;
 	gconstpointer thumbnail_data;
 	gsize size;
Only in extract/pidgin-2.10.9/libpurple: gaim-compat.h
Only in extract/pidgin-2.10.9/libpurple: gconf
Only in libpurple: gettext.c
Only in libpurple: gettext.h
diff -ru extract/pidgin-2.10.9/libpurple/idle.c libpurple/idle.c
--- extract/pidgin-2.10.9/libpurple/idle.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/idle.c	2015-05-04 13:42:04.488970478 +0200
@@ -24,23 +24,9 @@
 
 #include "connection.h"
 #include "debug.h"
-#include "eventloop.h"
 #include "idle.h"
-#include "log.h"
-#include "prefs.h"
-#include "savedstatuses.h"
 #include "signals.h"
 
-typedef enum
-{
-	PURPLE_IDLE_NOT_AWAY = 0,
-	PURPLE_IDLE_AUTO_AWAY,
-	PURPLE_IDLE_AWAY_BUT_NOT_AUTO_AWAY
-
-} PurpleAutoAwayState;
-
-static PurpleIdleUiOps *idle_ui_ops = NULL;
-
 /**
  * This is needed for the I'dle Mak'er plugin to work correctly.  We
  * use it to determine if we're the ones who set our accounts idle
@@ -51,10 +37,6 @@
  */
 static GList *idled_accts = NULL;
 
-static guint idle_timer = 0;
-
-static time_t last_active_time = 0;
-
 static void
 set_account_idle(PurpleAccount *account, int time_idle)
 {
@@ -90,112 +72,11 @@
 	purple_presence_set_idle(presence, FALSE, 0);
 }
 
-
-static gboolean no_away = FALSE;
-static gint time_until_next_idle_event;
-/*
- * This function should be called when you think your idle state
- * may have changed.  Maybe you're over the 10-minute mark and
- * Purple should start reporting idle time to the server.  Maybe
- * you've returned from being idle.  Maybe your auto-away message
- * should be set.
- *
- * There is no harm to calling this many many times, other than
- * it will be kinda slow.  This is called by a timer set when
- * Purple starts.  It is also called when you send an IM, a chat, etc.
- *
- * This function has 3 sections.
- * 1. Get your idle time.  It will query XScreenSaver or Windows
- *    or use the Purple idle time.  Whatever.
- * 2. Set or unset your auto-away message.
- * 3. Report your current idle time to the IM server.
- */
-
-static void
-check_idleness(void)
+static time_t global_time_idle = 0;
+void
+purple_idle_set(time_t time_idle)
 {
-	time_t time_idle;
-	gboolean auto_away;
-	const gchar *idle_reporting;
-	gboolean report_idle = TRUE;
-	gint away_seconds = 0;
-	gint idle_recheck_interval = 0;
-	gint idle_poll_seconds = purple_prefs_get_int("/purple/away/mins_before_away") * 60;
-	purple_signal_emit(purple_blist_get_handle(), "update-idle");
-
-	idle_reporting = purple_prefs_get_string("/purple/away/idle_reporting");
-	auto_away = purple_prefs_get_bool("/purple/away/away_when_idle");
-
-	if (purple_strequal(idle_reporting, "system") &&
-		(idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
-	{
-		/* Use system idle time (mouse or keyboard movement, etc.) */
-		time_idle = idle_ui_ops->get_time_idle();
-		idle_recheck_interval = 1;
-	}
-	else if (purple_strequal(idle_reporting, "purple"))
-	{
-		/* Use 'Purple idle' */
-		time_idle = time(NULL) - last_active_time;
-		idle_recheck_interval = 0;
-	}
-	else
-	{
-		/* Don't report idle time */
-		time_idle = 0;
-		report_idle = FALSE;
-
-		/* If we're not reporting idle, we can still do auto-away.
-		 * First try "system" and if that isn't possible, use "purple" */
-		if (auto_away)
-		{
-			if ((idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
-			{
-				time_idle = idle_ui_ops->get_time_idle();
-				idle_recheck_interval = 1;
-			}
-			else
-			{
-				time_idle = time(NULL) - last_active_time;
-				idle_recheck_interval = 0;
-			}
-		}
-		else
-		{
-			if (!no_away)
-			{
-				no_away = TRUE;
-				purple_savedstatus_set_idleaway(FALSE);
-			}
-			time_until_next_idle_event = 0;
-			return;
-		}
-	}
-
-	time_until_next_idle_event = idle_poll_seconds - time_idle;
-	if (time_until_next_idle_event < 0)
-	{
-		/* If we're already idle, check again as appropriate. */
-		time_until_next_idle_event = idle_recheck_interval;
-	}
-
-	if (auto_away || !no_away)
-		away_seconds = 60 * purple_prefs_get_int("/purple/away/mins_before_away");
-
-	if (auto_away && time_idle > away_seconds)
-	{
-		purple_savedstatus_set_idleaway(TRUE);
-		no_away = FALSE;
-	}
-	else if (purple_savedstatus_is_idleaway() && time_idle < away_seconds)
-	{
-		purple_savedstatus_set_idleaway(FALSE);
-		if (time_until_next_idle_event == 0 || (away_seconds - time_idle) < time_until_next_idle_event)
-			time_until_next_idle_event = away_seconds - time_idle;
-	}
-
-	/* Idle reporting stuff */
-	if (report_idle && (time_idle >= idle_poll_seconds))
+	if (time_idle)
 	{
 		GList *l;
 		for (l = purple_connections_get_all(); l != NULL; l = l->next)
@@ -204,94 +85,27 @@
 			set_account_idle(purple_connection_get_account(gc), time_idle);
 		}
 	}
-	else if (!report_idle || (time_idle < idle_poll_seconds ))
+	else
 	{
 		while (idled_accts != NULL)
 			set_account_unidle(idled_accts->data);
 	}
+	global_time_idle = time_idle;
 }
 
 
-/*
- * Check idle and set the timer to fire at the next idle-worth event
- */
-static gboolean
-check_idleness_timer(void)
-{
-	check_idleness();
-	if (time_until_next_idle_event == 0)
-		idle_timer = 0;
-	else
-	{
-		/* +1 for the boundary,
-		 * +1 more for g_timeout_add_seconds rounding. */
-		idle_timer = purple_timeout_add_seconds(time_until_next_idle_event + 2, (GSourceFunc)check_idleness_timer, NULL);
-	}
-	return FALSE;
-}
-
-static void
-im_msg_sent_cb(PurpleAccount *account, const char *receiver,
-			   const char *message, void *data)
-{
-	/* Check our idle time after an IM is sent */
-	check_idleness();
-}
-
 static void
 signing_on_cb(PurpleConnection *gc, void *data)
 {
 	/* When signing on a new account, check if the account should be idle */
-	check_idleness();
+	if (global_time_idle)
+		set_account_idle(purple_connection_get_account(gc), global_time_idle);
 }
 
 static void
 signing_off_cb(PurpleConnection *gc, void *data)
 {
-	PurpleAccount *account;
-
-	account = purple_connection_get_account(gc);
-	set_account_unidle(account);
-}
-
-static void
-idle_reporting_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data)
-{
-	if (idle_timer)
-		purple_timeout_remove(idle_timer);
-	idle_timer = 0;
-	check_idleness_timer();
-}
-
-void
-purple_idle_touch()
-{
-	time(&last_active_time);
-	if (!no_away)
-	{
-		if (idle_timer)
-			purple_timeout_remove(idle_timer);
-		idle_timer = 0;
-		check_idleness_timer();
-	}
-}
-
-void
-purple_idle_set(time_t time)
-{
-	last_active_time = time;
-}
-
-void
-purple_idle_set_ui_ops(PurpleIdleUiOps *ops)
-{
-	idle_ui_ops = ops;
-}
-
-PurpleIdleUiOps *
-purple_idle_get_ui_ops(void)
-{
-	return idle_ui_ops;
+	set_account_unidle(purple_connection_get_account(gc));
 }
 
 static void *
@@ -302,49 +116,19 @@
 	return &handle;
 }
 
-static gboolean _do_purple_idle_touch_cb(gpointer data)
-{
-	int idle_poll_minutes = purple_prefs_get_int("/purple/away/mins_before_away");
-
-	 /* +1 more for g_timeout_add_seconds rounding. */
-	idle_timer = purple_timeout_add_seconds((idle_poll_minutes * 60) + 2, (GSourceFunc)check_idleness_timer, NULL);
-
-	purple_idle_touch();
-
-	return FALSE;
-}
-
-
 void
 purple_idle_init()
 {
-	purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg",
-						purple_idle_get_handle(),
-						PURPLE_CALLBACK(im_msg_sent_cb), NULL);
 	purple_signal_connect(purple_connections_get_handle(), "signing-on",
 						purple_idle_get_handle(),
 						PURPLE_CALLBACK(signing_on_cb), NULL);
 	purple_signal_connect(purple_connections_get_handle(), "signing-off",
 						purple_idle_get_handle(),
 						PURPLE_CALLBACK(signing_off_cb), NULL);
-
-	purple_prefs_connect_callback(purple_idle_get_handle(), "/purple/away/idle_reporting",
-	                              idle_reporting_cb, NULL);
-
-	/* Initialize the idleness asynchronously so it doesn't check idleness,
-	 * and potentially try to change the status before the UI is initialized */
-	purple_timeout_add(0, _do_purple_idle_touch_cb, NULL);
-
 }
 
 void
 purple_idle_uninit()
 {
 	purple_signals_disconnect_by_handle(purple_idle_get_handle());
-	purple_prefs_disconnect_by_handle(purple_idle_get_handle());
-
-	/* Remove the idle timer */
-	if (idle_timer > 0)
-		purple_timeout_remove(idle_timer);
-	idle_timer = 0;
 }
diff -ru extract/pidgin-2.10.9/libpurple/idle.h libpurple/idle.h
--- extract/pidgin-2.10.9/libpurple/idle.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/idle.h	2015-05-04 13:42:04.488970478 +0200
@@ -28,19 +28,6 @@
 
 #include <time.h>
 
-/**
- * Idle UI operations.
- */
-typedef struct
-{
-	time_t (*get_time_idle)(void);
-
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-} PurpleIdleUiOps;
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -51,16 +38,8 @@
 /*@{*/
 
 /**
- * Touch our idle tracker.  This signifies that the user is
- * 'active'.  The conversation code calls this when the
- * user sends an IM, for example.
- */
-void purple_idle_touch(void);
-
-/**
- * Fake our idle time by setting the time at which our
- * accounts purportedly became idle.  This is used by
- * the I'dle Mak'er plugin.
+ * Set as idle (if the timestamp is provided) or as unidle if the
+ * timestamp is 0.
  */
 void purple_idle_set(time_t time);
 
@@ -72,20 +51,6 @@
 /*@{*/
 
 /**
- * Sets the UI operations structure to be used for idle reporting.
- *
- * @param ops The UI operations structure.
- */
-void purple_idle_set_ui_ops(PurpleIdleUiOps *ops);
-
-/**
- * Returns the UI operations structure used for idle reporting.
- *
- * @return The UI operations structure in use.
- */
-PurpleIdleUiOps *purple_idle_get_ui_ops(void);
-
-/**
  * Initializes the idle system.
  */
 void purple_idle_init(void);
diff -ru extract/pidgin-2.10.9/libpurple/internal.h libpurple/internal.h
--- extract/pidgin-2.10.9/libpurple/internal.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/internal.h	2015-05-04 13:42:04.492970478 +0200
@@ -45,23 +45,21 @@
  * taken from an email to the texinfo mailing list by Manuel Guerrero.
  * Thank you Manuel, and thank you Alex's good friend Google.
  */
+
+#include <locale.h>
+#include "gettext.h"
+
+#define _(String) (purple_get_text(PACKAGE, String))
+#define N_(String) (String)
+#define ngettext(Singular, Plural, Number) dngettext(PACKAGE, Singular, Plural, Number)
+#define dngettext(Domain, Singular, Plural, Number) (purple_get_plural_text(Domain, Singular, Plural, Number))
+
 #ifdef ENABLE_NLS
-#  include <locale.h>
 #  include <libintl.h>
-#  define _(String) ((const char *)dgettext(PACKAGE, String))
 #  ifdef gettext_noop
+#    undef N_
 #    define N_(String) gettext_noop (String)
-#  else
-#    define N_(String) (String)
 #  endif
-#else
-#  include <locale.h>
-#  define N_(String) (String)
-#  ifndef _
-#    define _(String) ((const char *)String)
-#  endif
-#  define ngettext(Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
-#  define dngettext(Domain, Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
 #endif
 
 #ifdef HAVE_ENDIAN_H
@@ -99,9 +97,8 @@
 #include <langinfo.h>
 #endif
 
-#include <gmodule.h>
-
 #ifdef PURPLE_PLUGINS
+# include <gmodule.h>
 # ifdef HAVE_DLFCN_H
 #  include <dlfcn.h>
 # endif
@@ -139,7 +136,7 @@
 #include "win32dep.h"
 #endif
 
-#ifdef HAVE_CONFIG_H
+#ifdef SIZEOF_TIME_T
 #if SIZEOF_TIME_T == 4
 #	define PURPLE_TIME_T_MODIFIER "lu"
 #elif SIZEOF_TIME_T == 8
Only in extract/pidgin-2.10.9/libpurple: log.c
diff -ru extract/pidgin-2.10.9/libpurple/log.h libpurple/log.h
--- extract/pidgin-2.10.9/libpurple/log.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/log.h	2015-05-04 13:42:04.492970478 +0200
@@ -1,583 +1,8 @@
-/**
- * @file log.h Logging API
- * @ingroup core
- * @see @ref log-signals
- */
-
-/* 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_LOG_H_
 #define _PURPLE_LOG_H_
 
-#include <stdio.h>
-
-
-/********************************************************
- * DATA STRUCTURES **************************************
- ********************************************************/
-
-typedef struct _PurpleLog PurpleLog;
-typedef struct _PurpleLogLogger PurpleLogLogger;
-typedef struct _PurpleLogCommonLoggerData PurpleLogCommonLoggerData;
-typedef struct _PurpleLogSet PurpleLogSet;
-
-typedef enum {
-	PURPLE_LOG_IM,
-	PURPLE_LOG_CHAT,
-	PURPLE_LOG_SYSTEM
-} PurpleLogType;
-
-typedef enum {
-	PURPLE_LOG_READ_NO_NEWLINE = 1
-} PurpleLogReadFlags;
-
-#include "account.h"
-#include "conversation.h"
-
-typedef void (*PurpleLogSetCallback) (GHashTable *sets, PurpleLogSet *set);
-
-/**
- * A log logger.
- *
- * This struct gets filled out and is included in the PurpleLog.  It contains everything
- * needed to write and read from logs.
- */
-struct _PurpleLogLogger {
-	char *name;               /**< The logger's name */
-	char *id;                 /**< an identifier to refer to this logger */
-
-	/** This gets called when the log is first created.
-	    I don't think this is actually needed. */
-	void (*create)(PurpleLog *log);
-
-	/** This is used to write to the log file */
-	gsize (*write)(PurpleLog *log,
-		     PurpleMessageFlags type,
-		     const char *from,
-		     time_t time,
-		     const char *message);
-
-	/** Called when the log is destroyed */
-	void (*finalize)(PurpleLog *log);
-
-	/** This function returns a sorted GList of available PurpleLogs */
-	GList *(*list)(PurpleLogType type, const char *name, PurpleAccount *account);
-
-	/** Given one of the logs returned by the logger's list function,
-	 *  this returns the contents of the log in GtkIMHtml markup */
-	char *(*read)(PurpleLog *log, PurpleLogReadFlags *flags);
-
-	/** Given one of the logs returned by the logger's list function,
-	 *  this returns the size of the log in bytes */
-	int (*size)(PurpleLog *log);
-
-	/** Returns the total size of all the logs. If this is undefined a default
-	 *  implementation is used */
-	int (*total_size)(PurpleLogType type, const char *name, PurpleAccount *account);
-
-	/** This function returns a sorted GList of available system PurpleLogs */
-	GList *(*list_syslog)(PurpleAccount *account);
-
-	/** Adds PurpleLogSets to a GHashTable. By passing the data in the PurpleLogSets
-	 *  to list, the caller can get every available PurpleLog from the logger.
-	 *  Loggers using purple_log_common_writer() (or otherwise storing their
-	 *  logs in the same directory structure as the stock loggers) do not
-	 *  need to implement this function.
-	 *
-	 *  Loggers which implement this function must create a PurpleLogSet,
-	 *  then call @a cb with @a sets and the newly created PurpleLogSet. */
-	void (*get_log_sets)(PurpleLogSetCallback cb, GHashTable *sets);
-
-	/* Attempts to delete the specified log, indicating success or failure */
-	gboolean (*remove)(PurpleLog *log);
-
-	/* Tests whether a log is deletable */
-	gboolean (*is_deletable)(PurpleLog *log);
-
-	void (*_purple_reserved1)(void);
-	void (*_purple_reserved2)(void);
-	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
-};
-
-/**
- * A log.  Not the wooden type.
- */
-struct _PurpleLog {
-	PurpleLogType type;                     /**< The type of log this is */
-	char *name;                           /**< The name of this log */
-	PurpleAccount *account;                 /**< The account this log is taking
-	                                           place on */
-	PurpleConversation *conv;               /**< The conversation being logged */
-	time_t time;                          /**< The time this conversation
-	                                           started, converted to the local timezone */
-
-	PurpleLogLogger *logger;                /**< The logging mechanism this log
-	                                           is to use */
-	void *logger_data;                    /**< Data used by the log logger */
-	struct tm *tm;                        /**< The time this conversation
-	                                           started, saved with original
-	                                           timezone data, if available and
-	                                           if struct tm has the BSD
-	                                           timezone fields, else @c NULL.
-	                                           Do NOT modify anything in this struct.*/
-
-	/* IMPORTANT: Some code in log.c allocates these without zeroing them.
-	 * IMPORTANT: Update that code if you add members here. */
-};
-
-/**
- * A common logger_data struct containing a file handle and path, as well
- * as a pointer to something else for additional data.
- */
-struct _PurpleLogCommonLoggerData {
-	char *path;
-	FILE *file;
-	void *extra_data;
-};
-
-/**
- * Describes available logs.
- *
- * By passing the elements of this struct to purple_log_get_logs(), the caller
- * can get all available PurpleLogs.
- */
-struct _PurpleLogSet {
-	PurpleLogType type;                     /**< The type of logs available */
-	char *name;                           /**< The name of the logs available */
-	PurpleAccount *account;                 /**< The account the available logs
-	                                           took place on. This will be
-	                                           @c NULL if the account no longer
-	                                           exists. (Depending on a
-	                                           logger's implementation of
-	                                           list, it may not be possible
-	                                           to load such logs.) */
-	gboolean buddy;                       /**< Is this (account, name) a buddy
-	                                           on the buddy list? */
-	char *normalized_name;                /**< The normalized version of
-	                                           @a name. It must be set, and
-	                                           may be set to the same pointer
-	                                           value as @a name. */
-
-	/* IMPORTANT: Some code in log.c allocates these without zeroing them.
-	 * IMPORTANT: Update that code if you add members here. */
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/***************************************/
-/** @name Log Functions                */
-/***************************************/
-/*@{*/
-
-/**
- * Creates a new log
- *
- * @param type        The type of log this is.
- * @param name        The name of this conversation (buddy name, chat name,
- *                    etc.)
- * @param account     The account the conversation is occurring on
- * @param conv        The conversation being logged
- * @param time        The time this conversation started
- * @param tm          The time this conversation started, with timezone data,
- *                    if available and if struct tm has the BSD timezone fields.
- * @return            The new log
- */
-PurpleLog *purple_log_new(PurpleLogType type, const char *name, PurpleAccount *account,
-                      PurpleConversation *conv, time_t time, const struct tm *tm);
-
-/**
- * Frees a log
- *
- * @param log         The log to destroy
- */
-void purple_log_free(PurpleLog *log);
-
-/**
- * Writes to a log file. Assumes you have checked preferences already.
- *
- * @param log          The log to write to
- * @param type         The type of message being logged
- * @param from         Whom this message is coming from, or @c NULL for
- *                     system messages
- * @param time         A timestamp in UNIX time
- * @param message      The message to log
- */
-void purple_log_write(PurpleLog *log,
-		    PurpleMessageFlags type,
-		    const char *from,
-		    time_t time,
-		    const char *message);
-
-/**
- * Reads from a log
- *
- * @param log   The log to read from
- * @param flags The returned logging flags.
- *
- * @return The contents of this log in Purple Markup.
- */
-char *purple_log_read(PurpleLog *log, PurpleLogReadFlags *flags);
-
-/**
- * Returns a list of all available logs
- *
- * @param type                The type of the log
- * @param name                The name of the log
- * @param account             The account
- * @return                    A sorted list of PurpleLogs
- */
-GList *purple_log_get_logs(PurpleLogType type, const char *name, PurpleAccount *account);
-
-/**
- * Returns a GHashTable of PurpleLogSets.
- *
- * A "log set" here means the information necessary to gather the
- * PurpleLogs for a given buddy/chat. This information would be passed
- * to purple_log_list to get a list of PurpleLogs.
- *
- * The primary use of this function is to get a list of everyone the
- * user has ever talked to (assuming he or she uses logging).
- *
- * The GHashTable that's returned will free all log sets in it when
- * destroyed. If a PurpleLogSet is removed from the GHashTable, it
- * must be freed with purple_log_set_free().
- *
- * @return A GHashTable of all available unique PurpleLogSets
- */
-GHashTable *purple_log_get_log_sets(void);
-
-/**
- * Returns a list of all available system logs
- *
- * @param account The account
- * @return        A sorted list of PurpleLogs
- */
-GList *purple_log_get_system_logs(PurpleAccount *account);
-
-/**
- * Returns the size of a log
- *
- * @param log                 The log
- * @return                    The size of the log, in bytes
- */
-int purple_log_get_size(PurpleLog *log);
-
-/**
- * Returns the size, in bytes, of all available logs in this conversation
- *
- * @param type                The type of the log
- * @param name                The name of the log
- * @param account             The account
- * @return                    The size in bytes
- */
-int purple_log_get_total_size(PurpleLogType type, const char *name, PurpleAccount *account);
-
-/**
- * Returns the activity score of a log, based on total size in bytes,
- * which is then decayed based on age
- *
- * @param type                The type of the log
- * @param name                The name of the log
- * @param account             The account
- * @return                    The activity score
- *
- * @since 2.6.0
- */
-int purple_log_get_activity_score(PurpleLogType type, const char *name, PurpleAccount *account);
-
-/**
- * Tests whether a log is deletable
- *
- * A return value of @c FALSE indicates that purple_log_delete() will fail on this
- * log, unless something changes between the two calls.  A return value of @c TRUE,
- * however, does not guarantee the log can be deleted.
- *
- * @param log                 The log
- * @return                    A boolean indicating if the log is deletable
- */
-gboolean purple_log_is_deletable(PurpleLog *log);
-
-/**
- * Deletes a log
- *
- * @param log                 The log
- * @return                    A boolean indicating success or failure
- */
-gboolean purple_log_delete(PurpleLog *log);
-
-/**
- * Returns the default logger directory Purple uses for a given account
- * and username.  This would be where Purple stores logs created by
- * the built-in text or HTML loggers.
- *
- * @param type                The type of the log.
- * @param name                The name of the log.
- * @param account             The account.
- * @return                    The default logger directory for Purple.
- */
-char *purple_log_get_log_dir(PurpleLogType type, const char *name, PurpleAccount *account);
-
-/**
- * Implements GCompareFunc for PurpleLogs
- *
- * @param y                   A PurpleLog
- * @param z                   Another PurpleLog
- * @return                    A value as specified by GCompareFunc
- */
-gint purple_log_compare(gconstpointer y, gconstpointer z);
-
-/**
- * Implements GCompareFunc for PurpleLogSets
- *
- * @param y                   A PurpleLogSet
- * @param z                   Another PurpleLogSet
- * @return                    A value as specified by GCompareFunc
- */
-gint purple_log_set_compare(gconstpointer y, gconstpointer z);
-
-/**
- * Frees a log set
- *
- * @param set         The log set to destroy
- */
-void purple_log_set_free(PurpleLogSet *set);
-
-/*@}*/
-
-/******************************************/
-/** @name Common Logger Functions         */
-/******************************************/
-/*@{*/
-
-/**
- * Opens a new log file in the standard Purple log location
- * with the given file extension, named for the current time,
- * for writing.  If a log file is already open, the existing
- * file handle is retained.  The log's logger_data value is
- * set to a PurpleLogCommonLoggerData struct containing the log
- * file handle and log path.
- *
- * This function is intended to be used as a "common"
- * implementation of a logger's @c write function.
- * It should only be passed to purple_log_logger_new() and never
- * called directly.
- *
- * @param log   The log to write to.
- * @param ext   The file extension to give to this log file.
- */
-void purple_log_common_writer(PurpleLog *log, const char *ext);
-
-/**
- * Returns a sorted GList of PurpleLogs of the requested type.
- *
- * This function should only be used with logs that are written
- * with purple_log_common_writer().  It's intended to be used as
- * a "common" implementation of a logger's @c list function.
- * It should only be passed to purple_log_logger_new() and never
- * called directly.
- *
- * @param type     The type of the logs being listed.
- * @param name     The name of the log.
- * @param account  The account of the log.
- * @param ext      The file extension this log format uses.
- * @param logger   A reference to the logger struct for this log.
- *
- * @return A sorted GList of PurpleLogs matching the parameters.
- */
-GList *purple_log_common_lister(PurpleLogType type, const char *name,
-							  PurpleAccount *account, const char *ext,
-							  PurpleLogLogger *logger);
-
-/**
- * Returns the total size of all the logs for a given user, with
- * a given extension.
- *
- * This function should only be used with logs that are written
- * with purple_log_common_writer().  It's intended to be used as
- * a "common" implementation of a logger's @c total_size function.
- * It should only be passed to purple_log_logger_new() and never
- * called directly.
- *
- * @param type     The type of the logs being sized.
- * @param name     The name of the logs to size
- *                 (e.g. the username or chat name).
- * @param account  The account of the log.
- * @param ext      The file extension this log format uses.
- *
- * @return The size of all the logs with the specified extension
- *         for the specified user.
- */
-int purple_log_common_total_sizer(PurpleLogType type, const char *name,
-								PurpleAccount *account, const char *ext);
-
-/**
- * Returns the size of a given PurpleLog.
- *
- * This function should only be used with logs that are written
- * with purple_log_common_writer().  It's intended to be used as
- * a "common" implementation of a logger's @c size function.
- * It should only be passed to purple_log_logger_new() and never
- * called directly.
- *
- * @param log      The PurpleLog to size.
- *
- * @return An integer indicating the size of the log in bytes.
- */
-int purple_log_common_sizer(PurpleLog *log);
-
-/**
- * Deletes a log
- *
- * This function should only be used with logs that are written
- * with purple_log_common_writer().  It's intended to be used as
- * a "common" implementation of a logger's @c delete function.
- * It should only be passed to purple_log_logger_new() and never
- * called directly.
- *
- * @param log      The PurpleLog to delete.
- *
- * @return A boolean indicating success or failure.
- */
-gboolean purple_log_common_deleter(PurpleLog *log);
-
-/**
- * Checks to see if a log is deletable
- *
- * This function should only be used with logs that are written
- * with purple_log_common_writer().  It's intended to be used as
- * a "common" implementation of a logger's @c is_deletable function.
- * It should only be passed to purple_log_logger_new() and never
- * called directly.
- *
- * @param log      The PurpleLog to check.
- *
- * @return A boolean indicating if the log is deletable.
- */
-gboolean purple_log_common_is_deletable(PurpleLog *log);
-
-/*@}*/
-
-/******************************************/
-/** @name Logger Functions                */
-/******************************************/
-/*@{*/
-
-/**
- * Creates a new logger
- *
- * @param id           The logger's id.
- * @param name         The logger's name.
- * @param functions    The number of functions being passed. The following
- *                     functions are currently available (in order): @c create,
- *                     @c write, @c finalize, @c list, @c read, @c size,
- *                     @c total_size, @c list_syslog, @c get_log_sets,
- *                     @c remove, @c is_deletable.
- *                     For details on these functions, see PurpleLogLogger.
- *                     Functions may not be skipped. For example, passing
- *                     @c create and @c write is acceptable (for a total of
- *                     two functions). Passing @c create and @c finalize,
- *                     however, is not. To accomplish that, the caller must
- *                     pass @c create, @c NULL (a placeholder for @c write),
- *                     and @c finalize (for a total of 3 functions).
- *
- * @return The new logger
- */
-PurpleLogLogger *purple_log_logger_new(const char *id, const char *name, int functions, ...);
-
-/**
- * Frees a logger
- *
- * @param logger       The logger to free
- */
-void purple_log_logger_free(PurpleLogLogger *logger);
-
-/**
- * Adds a new logger
- *
- * @param logger       The new logger to add
- */
-void purple_log_logger_add (PurpleLogLogger *logger);
-
-/**
- *
- * Removes a logger
- *
- * @param logger       The logger to remove
- */
-void purple_log_logger_remove (PurpleLogLogger *logger);
-
-/**
- *
- * Sets the current logger
- *
- * @param logger       The logger to set
- */
-void purple_log_logger_set (PurpleLogLogger *logger);
-
-/**
- *
- * Returns the current logger
- *
- * @return logger      The current logger
- */
-PurpleLogLogger *purple_log_logger_get (void);
-
-/**
- * Returns a GList containing the IDs and names of the registered
- * loggers.
- *
- * @return The list of IDs and names.
- */
-GList *purple_log_logger_get_options(void);
-
-/**************************************************************************/
-/** @name Log Subsystem                                                   */
-/**************************************************************************/
-/*@{*/
-
-/**
- * Initializes the log subsystem.
- */
-void purple_log_init(void);
-
-/**
- * Returns the log subsystem handle.
- *
- * @return The log subsystem handle.
- */
-void *purple_log_get_handle(void);
-
-/**
- * Uninitializes the log subsystem.
- */
-void purple_log_uninit(void);
-
-/*@}*/
-
-
-#ifdef __cplusplus
-}
-#endif
+#define purple_log_init()
+#define purple_log_uninit()
+#define PurpleLog void
 
 #endif /* _PURPLE_LOG_H_ */
Only in libpurple: Makefile.in
Only in extract/pidgin-2.10.9/libpurple: marshallers.c
Only in extract/pidgin-2.10.9/libpurple: marshallers.h
Only in extract/pidgin-2.10.9/libpurple: marshallers.list
Only in extract/pidgin-2.10.9/libpurple: media
Only in extract/pidgin-2.10.9/libpurple: media.c
Only in extract/pidgin-2.10.9/libpurple: media-gst.h
Only in extract/pidgin-2.10.9/libpurple: media.h
Only in extract/pidgin-2.10.9/libpurple: mediamanager.c
Only in extract/pidgin-2.10.9/libpurple: mediamanager.h
Only in libpurple: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/network.c libpurple/network.c
--- extract/pidgin-2.10.9/libpurple/network.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/network.c	2015-05-04 13:42:04.496970477 +0200
@@ -24,6 +24,12 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#ifdef _WIN32
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#define INCL_WINSOCK_API_TYPEDEFS 1
+#endif
+
 #include "internal.h"
 
 #ifndef _WIN32
@@ -35,7 +41,7 @@
 #ifdef HAVE_GETIFADDRS
 #include <ifaddrs.h>
 #endif
-#else
+#elif 0
 #include <nspapi.h>
 #endif
 
@@ -81,17 +87,16 @@
 static NMState nm_state = NM_STATE_UNKNOWN;
 static gboolean have_nm_state = FALSE;
 
-#elif defined _WIN32
+#elif 0
 static int current_network_count;
 
 /* Mutex for the other global vars */
 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
 static gboolean network_initialized = FALSE;
 static HANDLE network_change_handle = NULL;
-static int (WSAAPI *MyWSANSPIoctl) (
-		HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
-		DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
-		LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL;
+static LPFN_WSANSPIOCTL MyWSANSPIoctl = NULL;
+#else
+static network_available_callback available_callback = NULL;
 #endif
 
 struct _PurpleNetworkListenData {
@@ -611,7 +616,7 @@
 	return ntohs(addr.sin_port);
 }
 
-#ifdef _WIN32
+#if 0
 #ifndef NS_NLA
 #define NS_NLA 15
 #endif
@@ -850,9 +855,12 @@
 
 	return FALSE;
 
-#elif defined _WIN32
+#elif 0
 	return (current_network_count > 0 || force_online);
 #else
+	if (available_callback)
+		return (available_callback());
+
 	return TRUE;
 #endif
 }
@@ -1140,7 +1148,7 @@
 #ifdef HAVE_NETWORKMANAGER
 	GError *error = NULL;
 #endif
-#ifdef _WIN32
+#if 0
 	GError *err = NULL;
 	gint cnt = wpurple_get_connected_network_count();
 
@@ -1161,7 +1169,6 @@
 	purple_prefs_add_string("/purple/network/stun_server", "");
 	purple_prefs_add_string("/purple/network/turn_server", "");
 	purple_prefs_add_int   ("/purple/network/turn_port", 3478);
-	purple_prefs_add_int	 ("/purple/network/turn_port_tcp", 3478);
 	purple_prefs_add_string("/purple/network/turn_username", "");
 	purple_prefs_add_string("/purple/network/turn_password", "");
 	purple_prefs_add_bool  ("/purple/network/auto_ip", TRUE);
@@ -1236,7 +1243,7 @@
 		dbus_g_connection_unref(nm_conn);
 #endif
 
-#ifdef _WIN32
+#if 0
 	g_static_mutex_lock(&mutex);
 	network_initialized = FALSE;
 	if (network_change_handle != NULL) {
@@ -1269,3 +1276,15 @@
 	/* TODO: clean up remaining port mappings, note calling
 	 purple_upnp_remove_port_mapping from here doesn't quite work... */
 }
+
+void
+purple_network_configuration_changed(void)
+{
+	purple_signal_emit(purple_network_get_handle(), "network-configuration-changed", NULL);
+}
+
+void
+purple_network_set_available_callback(network_available_callback cb)
+{
+	available_callback = cb;
+}
diff -ru extract/pidgin-2.10.9/libpurple/network.h libpurple/network.h
--- extract/pidgin-2.10.9/libpurple/network.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/network.h	2015-05-04 13:42:04.496970477 +0200
@@ -350,6 +350,24 @@
  */
 void purple_network_uninit(void);
 
+/**
+ * Emits the network-configuration-changed signal
+ */
+void
+purple_network_configuration_changed(void);
+
+/**
+ * Function pointer to a function indicating if network is available
+ */
+typedef gboolean (*network_available_callback)(void);
+
+/**
+ * Sets the callback function to be used to query the UI about the
+ * availability of the network.
+ */
+void
+purple_network_set_available_callback(network_available_callback cb);
+
 /*@}*/
 
 #ifdef __cplusplus
diff -ru extract/pidgin-2.10.9/libpurple/notify.c libpurple/notify.c
--- extract/pidgin-2.10.9/libpurple/notify.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/notify.c	2015-05-04 13:42:04.496970477 +0200
@@ -28,6 +28,7 @@
 #include "internal.h"
 #include "dbus-maybe.h"
 #include "notify.h"
+#include "debug.h"
 
 static PurpleNotifyUiOps *notify_ui_ops = NULL;
 static GList *handles = NULL;
@@ -85,6 +86,18 @@
 		}
 
 	}
+	else {
+		int level;
+		if (type == PURPLE_NOTIFY_MSG_ERROR)
+			level = PURPLE_DEBUG_ERROR;
+		else if (type == PURPLE_NOTIFY_MSG_WARNING)
+			level = PURPLE_DEBUG_WARNING;
+		else
+			level = PURPLE_DEBUG_INFO;
+		purple_debug(level, "notify", "Notification: %s (%s)",
+			     title ? title : "(null)",
+			     primary ? primary : "(null)");
+	}
 
 	if (cb != NULL)
 		cb(user_data);
diff -ru extract/pidgin-2.10.9/libpurple/plugin.c libpurple/plugin.c
--- extract/pidgin-2.10.9/libpurple/plugin.c	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/plugin.c	2015-05-04 13:42:04.500970477 +0200
@@ -33,7 +33,6 @@
 #include "request.h"
 #include "signals.h"
 #include "util.h"
-#include "valgrind.h"
 #include "version.h"
 
 typedef struct
@@ -73,6 +72,8 @@
 
 #ifdef PURPLE_PLUGINS
 
+#define RUNNING_ON_VALGRIND 0
+
 static gboolean
 has_file_extension(const char *filename, const char *ext)
 {
@@ -283,8 +284,9 @@
 				purple_debug_error("plugins", "%s is not loadable: %s\n",
 						 plugin->path, plugin->error);
 			}
+#if 0
 			plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
-
+#endif
 			if (plugin->handle == NULL)
 			{
 #ifdef _WIN32
@@ -788,9 +790,9 @@
 void
 purple_plugin_destroy(PurplePlugin *plugin)
 {
-#ifdef PURPLE_PLUGINS
 	g_return_if_fail(plugin != NULL);
 
+#ifdef PURPLE_PLUGINS
 	if (purple_plugin_is_loaded(plugin))
 		purple_plugin_unload(plugin);
 
@@ -886,6 +888,17 @@
 				loader_info->destroy(plugin);
 		}
 	}
+#else
+	if (plugin->info != NULL) {
+		if (PURPLE_IS_PROTOCOL_PLUGIN(plugin))
+			protocol_plugins = g_list_remove(protocol_plugins, plugin);
+
+		if (plugin->info->unload)
+			plugin->info->unload(plugin);
+	}
+
+	plugins = g_list_remove(plugins, plugin);
+#endif /* !PURPLE_PLUGINS */
 
 	g_free(plugin->path);
 	g_free(plugin->error);
@@ -893,7 +906,6 @@
 	PURPLE_DBUS_UNREGISTER_POINTER(plugin);
 
 	g_free(plugin);
-#endif /* !PURPLE_PLUGINS */
 }
 
 gboolean
@@ -1179,7 +1191,9 @@
 purple_plugins_init(void) {
 	void *handle = purple_plugins_get_handle();
 
+#ifdef LIBDIR
 	purple_plugins_add_search_path(LIBDIR);
+#endif
 
 	purple_signal_register(handle, "plugin-load",
 						 purple_marshal_VOID__POINTER,
@@ -1256,14 +1270,11 @@
 void
 purple_plugins_destroy_all(void)
 {
-#ifdef PURPLE_PLUGINS
-
 	while (plugins != NULL)
 		purple_plugin_destroy(plugins->data);
-
-#endif /* PURPLE_PLUGINS */
 }
 
+#if 0
 void
 purple_plugins_save_loaded(const char *key)
 {
@@ -1345,6 +1356,7 @@
 	g_list_free(files);
 #endif /* PURPLE_PLUGINS */
 }
+#endif
 
 
 void
diff -ru extract/pidgin-2.10.9/libpurple/plugin.h libpurple/plugin.h
--- extract/pidgin-2.10.9/libpurple/plugin.h	2014-02-02 22:29:17.000000000 +0100
+++ libpurple/plugin.h	2015-05-04 13:42:04.500970477 +0200
@@ -30,7 +30,9 @@
 #define _PURPLE_PLUGIN_H_
 
 #include <glib.h>
-#include <gmodule.h>
+#ifdef PURPLE_PLUGINS
+# include <gmodule.h>
+#endif
 #include "signals.h"
 #include "value.h"
 
@@ -217,6 +219,7 @@
 /**
  * Handles the initialization of modules.
  */
+#if 0
 #if !defined(PURPLE_PLUGINS) || defined(PURPLE_STATIC_PRPL)
 # define _FUNC_NAME(x) purple_init_##x##_plugin
 # define PURPLE_INIT_PLUGIN(pluginname, initfunc, plugininfo) \
@@ -237,7 +240,21 @@
 		return purple_plugin_register(plugin); \
 	}
 #endif
+#endif
 
+#ifdef PURPLE_STATIC_PRPL
+# define _FUNC_NAME(x) purple_init_##x##_plugin
+#else
+# define _FUNC_NAME(x) purple_plugin_register_self
+#endif
+
+#define PURPLE_INIT_PLUGIN(pluginname, initfunc, plugininfo) \
+	gboolean _FUNC_NAME(pluginname)(void) { \
+		PurplePlugin *plugin = purple_plugin_new(TRUE, NULL); \
+		plugin->info = &(plugininfo); \
+		initfunc((plugin)); \
+		return purple_plugin_register(plugin); \
+	}
 
 #ifdef __cplusplus
 extern "C" {
@@ -536,21 +553,6 @@
 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.
Only in extract/pidgin-2.10.9/libpurple: plugins
Only in extract/pidgin-2.10.9/libpurple: pounce.c
Only in extract/pidgin-2.10.9/libpurple: pounce.h
diff -ru extract/pidgin-2.10.9/libpurple/prefs.c libpurple/prefs.c
--- extract/pidgin-2.10.9/libpurple/prefs.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/prefs.c	2015-05-04 13:42:04.500970477 +0200
@@ -40,1342 +40,261 @@
 #include "win32dep.h"
 #endif
 
+static PurplePrefsUiOps *prefs_ui_ops = NULL;
+
 struct pref_cb {
 	PurplePrefCallback func;
 	gpointer data;
 	guint id;
 	void *handle;
-};
-
-/* TODO: This should use PurpleValues? */
-struct purple_pref {
-	PurplePrefType type;
+	void *observer;
 	char *name;
-	union {
-		gpointer generic;
-		gboolean boolean;
-		int integer;
-		char *string;
-		GList *stringlist;
-	} value;
-	GSList *callbacks;
-	struct purple_pref *parent;
-	struct purple_pref *sibling;
-	struct purple_pref *first_child;
-};
-
-
-static struct purple_pref prefs = {
-	PURPLE_PREF_NONE,
-	NULL,
-	{ NULL },
-	NULL,
-	NULL,
-	NULL,
-	NULL
 };
 
-static GHashTable *prefs_hash = NULL;
 static guint       save_timer = 0;
 static gboolean    prefs_loaded = FALSE;
-
-
-/*********************************************************************
- * Private utility functions                                         *
- *********************************************************************/
-
-static struct
-purple_pref *find_pref(const char *name)
-{
-	g_return_val_if_fail(name != NULL && name[0] == '/', NULL);
-
-	if (name[1] == '\0')
-		return &prefs;
-	else
-	{
-		/* When we're initializing, the debug system is
-		 * initialized before the prefs system, but debug
-		 * calls will end up calling prefs functions, so we
-		 * need to deal cleanly here. */
-		if (prefs_hash)
-			return g_hash_table_lookup(prefs_hash, name);
-		else
-			return NULL;
-	}
-}
-
-
-/*********************************************************************
- * Writing to disk                                                   *
- *********************************************************************/
-
-/*
- * This function recursively creates the xmlnode tree from the prefs
- * tree structure.  Yay recursion!
- */
-static void
-pref_to_xmlnode(xmlnode *parent, struct purple_pref *pref)
-{
-	xmlnode *node, *childnode;
-	struct purple_pref *child;
-	char buf[21];
-	GList *cur;
-
-	/* Create a new node */
-	node = xmlnode_new_child(parent, "pref");
-	xmlnode_set_attrib(node, "name", pref->name);
-
-	/* Set the type of this node (if type == PURPLE_PREF_NONE then do nothing) */
-	if (pref->type == PURPLE_PREF_INT) {
-		xmlnode_set_attrib(node, "type", "int");
-		g_snprintf(buf, sizeof(buf), "%d", pref->value.integer);
-		xmlnode_set_attrib(node, "value", buf);
-	}
-	else if (pref->type == PURPLE_PREF_STRING) {
-		xmlnode_set_attrib(node, "type", "string");
-		xmlnode_set_attrib(node, "value", pref->value.string ? pref->value.string : "");
-	}
-	else if (pref->type == PURPLE_PREF_STRING_LIST) {
-		xmlnode_set_attrib(node, "type", "stringlist");
-		for (cur = pref->value.stringlist; cur != NULL; cur = cur->next)
-		{
-			childnode = xmlnode_new_child(node, "item");
-			xmlnode_set_attrib(childnode, "value", cur->data ? cur->data : "");
-		}
-	}
-	else if (pref->type == PURPLE_PREF_PATH) {
-		char *encoded = g_filename_to_utf8(pref->value.string ? pref->value.string : "", -1, NULL, NULL, NULL);
-		xmlnode_set_attrib(node, "type", "path");
-		xmlnode_set_attrib(node, "value", encoded);
-		g_free(encoded);
-	}
-	else if (pref->type == PURPLE_PREF_PATH_LIST) {
-		xmlnode_set_attrib(node, "type", "pathlist");
-		for (cur = pref->value.stringlist; cur != NULL; cur = cur->next)
-		{
-			char *encoded = g_filename_to_utf8(cur->data ? cur->data : "", -1, NULL, NULL, NULL);
-			childnode = xmlnode_new_child(node, "item");
-			xmlnode_set_attrib(childnode, "value", encoded);
-			g_free(encoded);
-		}
-	}
-	else if (pref->type == PURPLE_PREF_BOOLEAN) {
-		xmlnode_set_attrib(node, "type", "bool");
-		g_snprintf(buf, sizeof(buf), "%d", pref->value.boolean);
-		xmlnode_set_attrib(node, "value", buf);
-	}
-
-	/* All My Children */
-	for (child = pref->first_child; child != NULL; child = child->sibling)
-		pref_to_xmlnode(node, child);
-}
-
-static xmlnode *
-prefs_to_xmlnode(void)
-{
-	xmlnode *node;
-	struct purple_pref *pref, *child;
-
-	pref = &prefs;
-
-	/* Create the root preference node */
-	node = xmlnode_new("pref");
-	xmlnode_set_attrib(node, "version", "1");
-	xmlnode_set_attrib(node, "name", "/");
-
-	/* All My Children */
-	for (child = pref->first_child; child != NULL; child = child->sibling)
-		pref_to_xmlnode(node, child);
-
-	return node;
-}
-
-static void
-sync_prefs(void)
-{
-	xmlnode *node;
-	char *data;
-
-	if (!prefs_loaded)
-	{
-		/*
-		 * TODO: Call schedule_prefs_save()?  Ideally we wouldn't need to.
-		 * (prefs.xml should be loaded when purple_prefs_init is called)
-		 */
-		purple_debug_error("prefs", "Attempted to save prefs before "
-						 "they were read!\n");
-		return;
-	}
-
-	node = prefs_to_xmlnode();
-	data = xmlnode_to_formatted_str(node, NULL);
-	purple_util_write_data_to_file("prefs.xml", data, -1);
-	g_free(data);
-	xmlnode_free(node);
-}
+static GSList     *callbacks = NULL;
 
 static gboolean
 save_cb(gpointer data)
 {
-	sync_prefs();
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+	g_return_val_if_fail(uiop, FALSE);
+	uiop->save();
+
 	save_timer = 0;
 	return FALSE;
 }
 
-static void
-schedule_prefs_save(void)
-{
-	if (save_timer == 0)
-		save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
-}
-
-
 /*********************************************************************
  * Reading from disk                                                 *
  *********************************************************************/
 
-static GList *prefs_stack = NULL;
-
-static void
-prefs_start_element_handler (GMarkupParseContext *context,
-		const gchar *element_name,
-		const gchar **attribute_names,
-		const gchar **attribute_values,
-		gpointer user_data,
-		GError **error)
-{
-	PurplePrefType pref_type = PURPLE_PREF_NONE;
-	int i;
-	const char *pref_name = NULL, *pref_value = NULL;
-	GString *pref_name_full;
-	GList *tmp;
-
-	if(!purple_strequal(element_name, "pref") &&
-	   !purple_strequal(element_name, "item"))
-		return;
-
-	for(i = 0; attribute_names[i]; i++) {
-		if(purple_strequal(attribute_names[i], "name")) {
-			pref_name = attribute_values[i];
-		} else if(purple_strequal(attribute_names[i], "type")) {
-			if(purple_strequal(attribute_values[i], "bool"))
-				pref_type = PURPLE_PREF_BOOLEAN;
-			else if(purple_strequal(attribute_values[i], "int"))
-				pref_type = PURPLE_PREF_INT;
-			else if(purple_strequal(attribute_values[i], "string"))
-				pref_type = PURPLE_PREF_STRING;
-			else if(purple_strequal(attribute_values[i], "stringlist"))
-				pref_type = PURPLE_PREF_STRING_LIST;
-			else if(purple_strequal(attribute_values[i], "path"))
-				pref_type = PURPLE_PREF_PATH;
-			else if(purple_strequal(attribute_values[i], "pathlist"))
-				pref_type = PURPLE_PREF_PATH_LIST;
-			else
-				return;
-		} else if(purple_strequal(attribute_names[i], "value")) {
-			pref_value = attribute_values[i];
-		}
-	}
-
-	if ((pref_type == PURPLE_PREF_BOOLEAN || pref_type == PURPLE_PREF_INT) &&
-			pref_value == NULL) {
-		/* Missing a value attribute */
-		return;
-	}
-
-	if(purple_strequal(element_name, "item")) {
-		struct purple_pref *pref;
-
-		pref_name_full = g_string_new("");
-
-		for(tmp = prefs_stack; tmp; tmp = tmp->next) {
-			pref_name_full = g_string_prepend(pref_name_full, tmp->data);
-			pref_name_full = g_string_prepend_c(pref_name_full, '/');
-		}
-
-		pref = find_pref(pref_name_full->str);
-
-		if(pref) {
-			if(pref->type == PURPLE_PREF_STRING_LIST) {
-				pref->value.stringlist = g_list_append(pref->value.stringlist,
-						g_strdup(pref_value));
-			} else if(pref->type == PURPLE_PREF_PATH_LIST) {
-				pref->value.stringlist = g_list_append(pref->value.stringlist,
-						g_filename_from_utf8(pref_value, -1, NULL, NULL, NULL));
-			}
-		}
-		g_string_free(pref_name_full, TRUE);
-	} else {
-		char *decoded;
-
-		if(!pref_name || purple_strequal(pref_name, "/"))
-			return;
-
-		pref_name_full = g_string_new(pref_name);
-
-		for(tmp = prefs_stack; tmp; tmp = tmp->next) {
-			pref_name_full = g_string_prepend_c(pref_name_full, '/');
-			pref_name_full = g_string_prepend(pref_name_full, tmp->data);
-		}
-
-		pref_name_full = g_string_prepend_c(pref_name_full, '/');
-
-		switch(pref_type) {
-			case PURPLE_PREF_NONE:
-				purple_prefs_add_none(pref_name_full->str);
-				break;
-			case PURPLE_PREF_BOOLEAN:
-				purple_prefs_set_bool(pref_name_full->str, atoi(pref_value));
-				break;
-			case PURPLE_PREF_INT:
-				purple_prefs_set_int(pref_name_full->str, atoi(pref_value));
-				break;
-			case PURPLE_PREF_STRING:
-				purple_prefs_set_string(pref_name_full->str, pref_value);
-				break;
-			case PURPLE_PREF_STRING_LIST:
-				purple_prefs_set_string_list(pref_name_full->str, NULL);
-				break;
-			case PURPLE_PREF_PATH:
-				if (pref_value) {
-					decoded = g_filename_from_utf8(pref_value, -1, NULL, NULL, NULL);
-					purple_prefs_set_path(pref_name_full->str, decoded);
-					g_free(decoded);
-				} else {
-					purple_prefs_set_path(pref_name_full->str, NULL);
-				}
-				break;
-			case PURPLE_PREF_PATH_LIST:
-				purple_prefs_set_path_list(pref_name_full->str, NULL);
-				break;
-		}
-		prefs_stack = g_list_prepend(prefs_stack, g_strdup(pref_name));
-		g_string_free(pref_name_full, TRUE);
-	}
-}
-
-static void
-prefs_end_element_handler(GMarkupParseContext *context,
-						  const gchar *element_name,
-						  gpointer user_data, GError **error)
-{
-	if(prefs_stack && purple_strequal(element_name, "pref")) {
-		g_free(prefs_stack->data);
-		prefs_stack = g_list_delete_link(prefs_stack, prefs_stack);
-	}
-}
-
-static GMarkupParser prefs_parser = {
-	prefs_start_element_handler,
-	prefs_end_element_handler,
-	NULL,
-	NULL,
-	NULL
-};
-
 gboolean
 purple_prefs_load()
 {
-	gchar *filename = g_build_filename(purple_user_dir(), "prefs.xml", NULL);
-	gchar *contents = NULL;
-	gsize length;
-	GMarkupParseContext *context;
-	GError *error = NULL;
-
-	if (!filename) {
-		prefs_loaded = TRUE;
-		return FALSE;
-	}
-
-	purple_debug_info("prefs", "Reading %s\n", filename);
-
-	if(!g_file_get_contents(filename, &contents, &length, &error)) {
-#ifdef _WIN32
-		gchar *common_appdata = wpurple_get_special_folder(CSIDL_COMMON_APPDATA);
-#endif
-		g_free(filename);
-		g_error_free(error);
-
-		error = NULL;
-
-#ifdef _WIN32
-		filename = g_build_filename(common_appdata ? common_appdata : "", "purple", "prefs.xml", NULL);
-		g_free(common_appdata);
-#else
-		filename = g_build_filename(SYSCONFDIR, "purple", "prefs.xml", NULL);
-#endif
-
-		purple_debug_info("prefs", "Reading %s\n", filename);
-
-		if (!g_file_get_contents(filename, &contents, &length, &error)) {
-			purple_debug_error("prefs", "Error reading prefs: %s\n",
-					error->message);
-			g_error_free(error);
-			g_free(filename);
-			prefs_loaded = TRUE;
-
-			return FALSE;
-		}
-	}
-
-	context = g_markup_parse_context_new(&prefs_parser, 0, NULL, NULL);
-
-	if(!g_markup_parse_context_parse(context, contents, length, NULL)) {
-		g_markup_parse_context_free(context);
-		g_free(contents);
-		g_free(filename);
-		prefs_loaded = TRUE;
-
-		return FALSE;
-	}
-
-	if(!g_markup_parse_context_end_parse(context, NULL)) {
-		purple_debug_error("prefs", "Error parsing %s\n", filename);
-		g_markup_parse_context_free(context);
-		g_free(contents);
-		g_free(filename);
-		prefs_loaded = TRUE;
-
-		return FALSE;
-	}
-
-	purple_debug_info("prefs", "Finished reading %s\n", filename);
-	g_markup_parse_context_free(context);
-	g_free(contents);
-	g_free(filename);
 	prefs_loaded = TRUE;
 
 	return TRUE;
 }
 
-
-
 static void
 prefs_save_cb(const char *name, PurplePrefType type, gconstpointer val,
 			  gpointer user_data)
 {
-
-	if(!prefs_loaded)
+	if (!prefs_loaded)
 		return;
 
 	purple_debug_misc("prefs", "%s changed, scheduling save.\n", name);
 
-	schedule_prefs_save();
-}
-
-static char *
-get_path_dirname(const char *name)
-{
-	char *c, *str;
-
-	str = g_strdup(name);
-
-	if ((c = strrchr(str, '/')) != NULL) {
-		*c = '\0';
-
-		if (*str == '\0') {
-			g_free(str);
-
-			str = g_strdup("/");
-		}
-	}
-	else {
-		g_free(str);
-
-		str = g_strdup(".");
-	}
-
-	return str;
-}
-
-static char *
-get_path_basename(const char *name)
-{
-	const char *c;
-
-	if ((c = strrchr(name, '/')) != NULL)
-		return g_strdup(c + 1);
-
-	return g_strdup(name);
-}
-
-static char *
-pref_full_name(struct purple_pref *pref)
-{
-	GString *name;
-	struct purple_pref *parent;
-
-	if(!pref)
-		return NULL;
-
-	if(pref == &prefs)
-		return g_strdup("/");
-
-	name = g_string_new(pref->name);
-
-	for(parent = pref->parent; parent && parent->name; parent = parent->parent) {
-		name = g_string_prepend_c(name, '/');
-		name = g_string_prepend(name, parent->name);
-	}
-	name = g_string_prepend_c(name, '/');
-	return g_string_free(name, FALSE);
-}
-
-static struct purple_pref *
-find_pref_parent(const char *name)
-{
-	char *parent_name = get_path_dirname(name);
-	struct purple_pref *ret = &prefs;
-
-	if(!purple_strequal(parent_name, "/")) {
-		ret = find_pref(parent_name);
-	}
-
-	g_free(parent_name);
-	return ret;
-}
-
-static void
-free_pref_value(struct purple_pref *pref)
-{
-	switch(pref->type) {
-		case PURPLE_PREF_BOOLEAN:
-			pref->value.boolean = FALSE;
-			break;
-		case PURPLE_PREF_INT:
-			pref->value.integer = 0;
-			break;
-		case PURPLE_PREF_STRING:
-		case PURPLE_PREF_PATH:
-			g_free(pref->value.string);
-			pref->value.string = NULL;
-			break;
-		case PURPLE_PREF_STRING_LIST:
-		case PURPLE_PREF_PATH_LIST:
-			{
-				g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL);
-				g_list_free(pref->value.stringlist);
-			} break;
-		case PURPLE_PREF_NONE:
-			break;
-	}
+	if (save_timer == 0)
+		save_timer = purple_timeout_add_seconds(6, save_cb, NULL);
 }
 
-static struct purple_pref *
-add_pref(PurplePrefType type, const char *name)
-{
-	struct purple_pref *parent;
-	struct purple_pref *me;
-	struct purple_pref *sibling;
-	char *my_name;
-
-	parent = find_pref_parent(name);
-
-	if(!parent)
-		return NULL;
-
-	my_name = get_path_basename(name);
-
-	for(sibling = parent->first_child; sibling; sibling = sibling->sibling) {
-		if(purple_strequal(sibling->name, my_name)) {
-			g_free(my_name);
-			return NULL;
-		}
-	}
-
-	me = g_new0(struct purple_pref, 1);
-	me->type = type;
-	me->name = my_name;
-
-	me->parent = parent;
-	if(parent->first_child) {
-		/* blatant abuse of a for loop */
-		for(sibling = parent->first_child; sibling->sibling;
-				sibling = sibling->sibling);
-		sibling->sibling = me;
-	} else {
-		parent->first_child = me;
+#define UIOP(aCall)						    \
+	{							    \
+		PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); \
+		g_return_if_fail(uiop);				    \
+								    \
+		uiop->aCall;					    \
+	}
+
+#define UIOP_return(aCall, aDefault)				    \
+	{							    \
+		PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); \
+		g_return_val_if_fail(uiop, aDefault);		    \
+								    \
+		return uiop->aCall;				    \
 	}
 
-	g_hash_table_insert(prefs_hash, g_strdup(name), (gpointer)me);
-
-	return me;
-}
-
 void
 purple_prefs_add_none(const char *name)
-{
-	add_pref(PURPLE_PREF_NONE, name);
-}
+	UIOP(add_none(name))
 
 void
 purple_prefs_add_bool(const char *name, gboolean value)
-{
-	struct purple_pref *pref = add_pref(PURPLE_PREF_BOOLEAN, name);
-
-	if(!pref)
-		return;
-
-	pref->value.boolean = value;
-}
+	UIOP(add_bool(name, value))
 
 void
 purple_prefs_add_int(const char *name, int value)
-{
-	struct purple_pref *pref = add_pref(PURPLE_PREF_INT, name);
-
-	if(!pref)
-		return;
-
-	pref->value.integer = value;
-}
+	UIOP(add_int(name, value))
 
 void
 purple_prefs_add_string(const char *name, const char *value)
-{
-	struct purple_pref *pref;
-
-	if(value != NULL && !g_utf8_validate(value, -1, NULL)) {
-		purple_debug_error("prefs", "purple_prefs_add_string: Cannot store invalid UTF8 for string pref %s\n", name);
-		return;
-	}
-
-	pref = add_pref(PURPLE_PREF_STRING, name);
-
-	if(!pref)
-		return;
-
-	pref->value.string = g_strdup(value);
-}
-
-void
-purple_prefs_add_string_list(const char *name, GList *value)
-{
-	struct purple_pref *pref = add_pref(PURPLE_PREF_STRING_LIST, name);
-	GList *tmp;
-
-	if(!pref)
-		return;
-
-	for(tmp = value; tmp; tmp = tmp->next) {
-		if(tmp->data != NULL && !g_utf8_validate(tmp->data, -1, NULL)) {
-			purple_debug_error("prefs", "purple_prefs_add_string_list: Skipping invalid UTF8 for string list pref %s\n", name);
-			continue;
-		}
-		pref->value.stringlist = g_list_append(pref->value.stringlist,
-				g_strdup(tmp->data));
-	}
-}
-
-void
-purple_prefs_add_path(const char *name, const char *value)
-{
-	struct purple_pref *pref = add_pref(PURPLE_PREF_PATH, name);
-
-	if(!pref)
-		return;
-
-	pref->value.string = g_strdup(value);
-}
-
-void
-purple_prefs_add_path_list(const char *name, GList *value)
-{
-	struct purple_pref *pref = add_pref(PURPLE_PREF_PATH_LIST, name);
-	GList *tmp;
-
-	if(!pref)
-		return;
-
-	for(tmp = value; tmp; tmp = tmp->next)
-		pref->value.stringlist = g_list_append(pref->value.stringlist,
-				g_strdup(tmp->data));
-}
-
-
-static void
-remove_pref(struct purple_pref *pref)
-{
-	char *name;
-	GSList *l;
-
-	if(!pref)
-		return;
-
-	while(pref->first_child)
-		remove_pref(pref->first_child);
-
-	if(pref == &prefs)
-		return;
-
-	if(pref->parent->first_child == pref) {
-		pref->parent->first_child = pref->sibling;
-	} else {
-		struct purple_pref *sib = pref->parent->first_child;
-		while(sib && sib->sibling != pref)
-			sib = sib->sibling;
-		if(sib)
-			sib->sibling = pref->sibling;
-	}
-
-	name = pref_full_name(pref);
-
-	if (prefs_loaded)
-		purple_debug_info("prefs", "removing pref %s\n", name);
-
-	g_hash_table_remove(prefs_hash, name);
-	g_free(name);
-
-	free_pref_value(pref);
-
-	while((l = pref->callbacks) != NULL) {
-		pref->callbacks = pref->callbacks->next;
-		g_free(l->data);
-		g_slist_free_1(l);
-	}
-	g_free(pref->name);
-	g_free(pref);
-}
+	UIOP(add_string(name, value))
 
 void
 purple_prefs_remove(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(!pref)
-		return;
-
-	remove_pref(pref);
-}
-
-void
-purple_prefs_destroy()
-{
-	purple_prefs_remove("/");
-}
-
-static void
-do_callbacks(const char* name, struct purple_pref *pref)
-{
-	GSList *cbs;
-	struct purple_pref *cb_pref;
-	for(cb_pref = pref; cb_pref; cb_pref = cb_pref->parent) {
-		for(cbs = cb_pref->callbacks; cbs; cbs = cbs->next) {
-			struct pref_cb *cb = cbs->data;
-			cb->func(name, pref->type, pref->value.generic, cb->data);
-		}
-	}
-}
+	UIOP(remove(name))
 
 void
 purple_prefs_trigger_callback(const char *name)
 {
-	struct purple_pref *pref = find_pref(name);
-
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_trigger_callback: Unknown pref %s\n", name);
-		return;
-	}
-
-	do_callbacks(name, pref);
-}
+	GSList *cbs;
 
-void
-purple_prefs_set_generic(const char *name, gpointer value)
-{
-	struct purple_pref *pref = find_pref(name);
+	purple_debug_misc("prefs", "trigger callback %s\n", name);
 
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_set_generic: Unknown pref %s\n", name);
-		return;
+	for (cbs = callbacks; cbs; cbs = cbs->next) {
+		const char *cb_name = ((struct pref_cb *)cbs->data)->name;
+		size_t len = strlen(cb_name);
+		if (!strncmp(cb_name, name, len) &&
+		    (name[len] == 0 || name[len] == '/' ||
+		     (len && name[len - 1] == '/'))) {
+			/* This test should behave like this:
+			 * name    = /toto/tata
+			 * cb_name = /toto/tata --> true
+			 * cb_name = /toto/tatatiti --> false
+			 * cb_name = / --> true
+			 * cb_name = /toto --> true
+			 * cb_name = /toto/ --> true
+			 */
+			purple_prefs_observe(cbs->data);
+		}
 	}
-
-	pref->value.generic = value;
-	do_callbacks(name, pref);
 }
 
 void
 purple_prefs_set_bool(const char *name, gboolean value)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(pref) {
-		if(pref->type != PURPLE_PREF_BOOLEAN) {
-			purple_debug_error("prefs",
-					"purple_prefs_set_bool: %s not a boolean pref\n", name);
-			return;
-		}
-
-		if(pref->value.boolean != value) {
-			pref->value.boolean = value;
-			do_callbacks(name, pref);
-		}
-	} else {
-		purple_prefs_add_bool(name, value);
-	}
-}
+	UIOP(set_bool(name, value))
 
 void
 purple_prefs_set_int(const char *name, int value)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(pref) {
-		if(pref->type != PURPLE_PREF_INT) {
-			purple_debug_error("prefs",
-					"purple_prefs_set_int: %s not an integer pref\n", name);
-			return;
-		}
-
-		if(pref->value.integer != value) {
-			pref->value.integer = value;
-			do_callbacks(name, pref);
-		}
-	} else {
-		purple_prefs_add_int(name, value);
-	}
-}
+	UIOP(set_int(name, value))
 
 void
 purple_prefs_set_string(const char *name, const char *value)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(value != NULL && !g_utf8_validate(value, -1, NULL)) {
-		purple_debug_error("prefs", "purple_prefs_set_string: Cannot store invalid UTF8 for string pref %s\n", name);
-		return;
-	}
-
-	if(pref) {
-		if(pref->type != PURPLE_PREF_STRING && pref->type != PURPLE_PREF_PATH) {
-			purple_debug_error("prefs",
-					"purple_prefs_set_string: %s not a string pref\n", name);
-			return;
-		}
-
-		if (!purple_strequal(pref->value.string, value)) {
-			g_free(pref->value.string);
-			pref->value.string = g_strdup(value);
-			do_callbacks(name, pref);
-		}
-	} else {
-		purple_prefs_add_string(name, value);
-	}
-}
-
-void
-purple_prefs_set_string_list(const char *name, GList *value)
-{
-	struct purple_pref *pref = find_pref(name);
-	if(pref) {
-		GList *tmp;
-
-		if(pref->type != PURPLE_PREF_STRING_LIST) {
-			purple_debug_error("prefs",
-					"purple_prefs_set_string_list: %s not a string list pref\n",
-					name);
-			return;
-		}
-
-		g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL);
-		g_list_free(pref->value.stringlist);
-		pref->value.stringlist = NULL;
-
-		for(tmp = value; tmp; tmp = tmp->next) {
-			if(tmp->data != NULL && !g_utf8_validate(tmp->data, -1, NULL)) {
-				purple_debug_error("prefs", "purple_prefs_set_string_list: Skipping invalid UTF8 for string list pref %s\n", name);
-				continue;
-			}
-			pref->value.stringlist = g_list_prepend(pref->value.stringlist,
-					g_strdup(tmp->data));
-		}
-		pref->value.stringlist = g_list_reverse(pref->value.stringlist);
-
-		do_callbacks(name, pref);
-
-	} else {
-		purple_prefs_add_string_list(name, value);
-	}
-}
-
-void
-purple_prefs_set_path(const char *name, const char *value)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(pref) {
-		if(pref->type != PURPLE_PREF_PATH) {
-			purple_debug_error("prefs",
-					"purple_prefs_set_path: %s not a path pref\n", name);
-			return;
-		}
-
-		if (!purple_strequal(pref->value.string, value)) {
-			g_free(pref->value.string);
-			pref->value.string = g_strdup(value);
-			do_callbacks(name, pref);
-		}
-	} else {
-		purple_prefs_add_path(name, value);
-	}
-}
-
-void
-purple_prefs_set_path_list(const char *name, GList *value)
-{
-	struct purple_pref *pref = find_pref(name);
-	if(pref) {
-		GList *tmp;
-
-		if(pref->type != PURPLE_PREF_PATH_LIST) {
-			purple_debug_error("prefs",
-					"purple_prefs_set_path_list: %s not a path list pref\n",
-					name);
-			return;
-		}
-
-		g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL);
-		g_list_free(pref->value.stringlist);
-		pref->value.stringlist = NULL;
-
-		for(tmp = value; tmp; tmp = tmp->next)
-			pref->value.stringlist = g_list_prepend(pref->value.stringlist,
-					g_strdup(tmp->data));
-		pref->value.stringlist = g_list_reverse(pref->value.stringlist);
-
-		do_callbacks(name, pref);
-
-	} else {
-		purple_prefs_add_path_list(name, value);
-	}
-}
-
+	UIOP(set_string(name, value))
 
 gboolean
 purple_prefs_exists(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if (pref != NULL)
-		return TRUE;
-
-	return FALSE;
-}
+	UIOP_return(exists(name), FALSE)
 
 PurplePrefType
 purple_prefs_get_type(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if (pref == NULL)
-		return PURPLE_PREF_NONE;
-
-	return (pref->type);
-}
+	UIOP_return(get_type(name), PURPLE_PREF_NONE)
 
 gboolean
 purple_prefs_get_bool(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_bool: Unknown pref %s\n", name);
-		return FALSE;
-	} else if(pref->type != PURPLE_PREF_BOOLEAN) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_bool: %s not a boolean pref\n", name);
-		return FALSE;
-	}
-
-	return pref->value.boolean;
-}
+	UIOP_return(get_bool(name), FALSE)
 
 int
 purple_prefs_get_int(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_int: Unknown pref %s\n", name);
-		return 0;
-	} else if(pref->type != PURPLE_PREF_INT) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_int: %s not an integer pref\n", name);
-		return 0;
-	}
-
-	return pref->value.integer;
-}
+	UIOP_return(get_int(name), 0)
 
 const char *
 purple_prefs_get_string(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_string: Unknown pref %s\n", name);
-		return NULL;
-	} else if(pref->type != PURPLE_PREF_STRING) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_string: %s not a string pref\n", name);
-		return NULL;
-	}
+	UIOP_return(get_string(name), NULL)
 
-	return pref->value.string;
-}
-
-GList *
-purple_prefs_get_string_list(const char *name)
+guint
+purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data)
 {
-	struct purple_pref *pref = find_pref(name);
-	GList *ret = NULL, *tmp;
-
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_string_list: Unknown pref %s\n", name);
-		return NULL;
-	} else if(pref->type != PURPLE_PREF_STRING_LIST) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_string_list: %s not a string list pref\n", name);
-		return NULL;
-	}
-
-	for(tmp = pref->value.stringlist; tmp; tmp = tmp->next)
-		ret = g_list_prepend(ret, g_strdup(tmp->data));
-	ret = g_list_reverse(ret);
+	struct pref_cb *cb;
+	static guint cb_id = 0;
+	PurplePrefsUiOps *uiop = NULL;
 
-	return ret;
-}
+	g_return_val_if_fail(name != NULL, 0);
+	g_return_val_if_fail(func != NULL, 0);
 
-const char *
-purple_prefs_get_path(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
+	uiop = purple_prefs_get_ui_ops();
+	g_return_val_if_fail(uiop, 0);
 
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_path: Unknown pref %s\n", name);
-		return NULL;
-	} else if(pref->type != PURPLE_PREF_PATH) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_path: %s not a path pref\n", name);
-		return NULL;
-	}
+	cb = g_new0(struct pref_cb, 1);
 
-	return pref->value.string;
-}
+	cb->func = func;
+	cb->data = data;
+	cb->id = ++cb_id;
+	cb->handle = handle;
+	cb->name = g_strdup(name);
 
-GList *
-purple_prefs_get_path_list(const char *name)
-{
-	struct purple_pref *pref = find_pref(name);
-	GList *ret = NULL, *tmp;
+	cb->observer = uiop->add_observer(name, cb);
 
-	if(!pref) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_path_list: Unknown pref %s\n", name);
-		return NULL;
-	} else if(pref->type != PURPLE_PREF_PATH_LIST) {
-		purple_debug_error("prefs",
-				"purple_prefs_get_path_list: %s not a path list pref\n", name);
-		return NULL;
+	if (cb->observer == NULL) {
+		purple_debug_error("prefs", "purple_prefs_connect_callback: add observer failed for %s\n", name);
+		g_free(cb->name);
+		g_free(cb);
+		return 0;
 	}
 
-	for(tmp = pref->value.stringlist; tmp; tmp = tmp->next)
-		ret = g_list_prepend(ret, g_strdup(tmp->data));
-	ret = g_list_reverse(ret);
-
-	return ret;
+	callbacks = g_slist_append(callbacks, cb);
+	return cb->id;
 }
 
-static void
-purple_prefs_rename_node(struct purple_pref *oldpref, struct purple_pref *newpref)
+void purple_prefs_observe(gpointer data)
 {
-	struct purple_pref *child, *next;
-	char *oldname, *newname;
+	struct pref_cb *cb = data;
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+	gconstpointer value = NULL;
+	PurplePrefType type = PURPLE_PREF_NONE;
+	type = uiop->get_type(cb->name);
 
-	/* if we're a parent, rename the kids first */
-	for(child = oldpref->first_child; child != NULL; child = next)
-	{
-		struct purple_pref *newchild;
-		next = child->sibling;
-		for(newchild = newpref->first_child; newchild != NULL; newchild = newchild->sibling)
-		{
-			if(purple_strequal(child->name, newchild->name))
-			{
-				purple_prefs_rename_node(child, newchild);
-				break;
-			}
-		}
-		if(newchild == NULL) {
-			/* no rename happened, we weren't able to find the new pref */
-			char *tmpname = pref_full_name(child);
-			purple_debug_error("prefs", "Unable to find rename pref for %s\n", tmpname);
-			g_free(tmpname);
-		}
-	}
-
-	oldname = pref_full_name(oldpref);
-	newname = pref_full_name(newpref);
-
-	if (oldpref->type != newpref->type)
-	{
-		purple_debug_error("prefs", "Unable to rename %s to %s: differing types\n", oldname, newname);
-		g_free(oldname);
-		g_free(newname);
-		return;
-	}
+	purple_debug_misc("prefs", "observe name = %s\n", cb->name);
 
-	purple_debug_info("prefs", "Renaming %s to %s\n", oldname, newname);
-	g_free(oldname);
-
-	switch(oldpref->type) {
-		case PURPLE_PREF_NONE:
+	switch (type) {
+		case PURPLE_PREF_INT:
+			value = GINT_TO_POINTER(uiop->get_int(cb->name));
 			break;
 		case PURPLE_PREF_BOOLEAN:
-			purple_prefs_set_bool(newname, oldpref->value.boolean);
-			break;
-		case PURPLE_PREF_INT:
-			purple_prefs_set_int(newname, oldpref->value.integer);
+			value = GINT_TO_POINTER(uiop->get_bool(cb->name));
 			break;
 		case PURPLE_PREF_STRING:
-			purple_prefs_set_string(newname, oldpref->value.string);
-			break;
-		case PURPLE_PREF_STRING_LIST:
-			purple_prefs_set_string_list(newname, oldpref->value.stringlist);
+			value = uiop->get_string(cb->name);
 			break;
-		case PURPLE_PREF_PATH:
-			purple_prefs_set_path(newname, oldpref->value.string);
-			break;
-		case PURPLE_PREF_PATH_LIST:
-			purple_prefs_set_path_list(newname, oldpref->value.stringlist);
+		case PURPLE_PREF_NONE:
 			break;
+		default:
+			purple_debug_error("prefs", "Unexpected type = %i\n", type);
 	}
-	g_free(newname);
-
-	remove_pref(oldpref);
+	cb->func(cb->name, type, value, cb->data);
 }
 
 void
-purple_prefs_rename(const char *oldname, const char *newname)
-{
-	struct purple_pref *oldpref, *newpref;
-
-	oldpref = find_pref(oldname);
-
-	/* it's already been renamed, call off the dogs */
-	if(!oldpref)
-		return;
-
-	newpref = find_pref(newname);
-
-	if (newpref == NULL)
-	{
-		purple_debug_error("prefs", "Unable to rename %s to %s: new pref not created\n", oldname, newname);
-		return;
-	}
-
-	purple_prefs_rename_node(oldpref, newpref);
-}
-
-void
-purple_prefs_rename_boolean_toggle(const char *oldname, const char *newname)
-{
-		struct purple_pref *oldpref, *newpref;
-
-		oldpref = find_pref(oldname);
-
-		/* it's already been renamed, call off the cats */
-		if(!oldpref)
-			return;
-
-		if (oldpref->type != PURPLE_PREF_BOOLEAN)
-		{
-			purple_debug_error("prefs", "Unable to rename %s to %s: old pref not a boolean\n", oldname, newname);
-			return;
-		}
-
-		if (oldpref->first_child != NULL) /* can't rename parents */
-		{
-			purple_debug_error("prefs", "Unable to rename %s to %s: can't rename parents\n", oldname, newname);
-			return;
-		}
-
-
-		newpref = find_pref(newname);
-
-		if (newpref == NULL)
-		{
-			purple_debug_error("prefs", "Unable to rename %s to %s: new pref not created\n", oldname, newname);
-			return;
-		}
-
-		if (oldpref->type != newpref->type)
-		{
-			purple_debug_error("prefs", "Unable to rename %s to %s: differing types\n", oldname, newname);
-			return;
-		}
-
-		purple_debug_info("prefs", "Renaming and toggling %s to %s\n", oldname, newname);
-		purple_prefs_set_bool(newname, !(oldpref->value.boolean));
-
-		remove_pref(oldpref);
-}
-
-guint
-purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data)
-{
-	struct purple_pref *pref;
-	struct pref_cb *cb;
-	static guint cb_id = 0;
-
-	g_return_val_if_fail(name != NULL, 0);
-	g_return_val_if_fail(func != NULL, 0);
-
-	pref = find_pref(name);
-	if (pref == NULL) {
-		purple_debug_error("prefs", "purple_prefs_connect_callback: Unknown pref %s\n", name);
-		return 0;
-	}
-
-	cb = g_new0(struct pref_cb, 1);
-
-	cb->func = func;
-	cb->data = data;
-	cb->id = ++cb_id;
-	cb->handle = handle;
-
-	pref->callbacks = g_slist_append(pref->callbacks, cb);
-
-	return cb->id;
-}
-
-static gboolean
-disco_callback_helper(struct purple_pref *pref, guint callback_id)
+purple_prefs_disconnect_callback(guint callback_id)
 {
 	GSList *cbs;
-	struct purple_pref *child;
-
-	if(!pref)
-		return FALSE;
 
-	for(cbs = pref->callbacks; cbs; cbs = cbs->next) {
+	for (cbs = callbacks; cbs; cbs = cbs->next) {
 		struct pref_cb *cb = cbs->data;
-		if(cb->id == callback_id) {
-			pref->callbacks = g_slist_delete_link(pref->callbacks, cbs);
+		if (cb->id == callback_id) {
+			PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+			uiop->remove_observer(cb->name, cb->observer);
+
+			callbacks = g_slist_delete_link(callbacks, cbs);
+			g_free(cb->name);
 			g_free(cb);
-			return TRUE;
+			return;
 		}
 	}
-
-	for(child = pref->first_child; child; child = child->sibling) {
-		if(disco_callback_helper(child, callback_id))
-			return TRUE;
-	}
-
-	return FALSE;
 }
 
 void
-purple_prefs_disconnect_callback(guint callback_id)
-{
-	disco_callback_helper(&prefs, callback_id);
-}
-
-static void
-disco_callback_helper_handle(struct purple_pref *pref, void *handle)
+purple_prefs_disconnect_by_handle(void *handle)
 {
 	GSList *cbs;
-	struct purple_pref *child;
 
-	if(!pref)
-		return;
+	g_return_if_fail(handle != NULL);
 
-	cbs = pref->callbacks;
+	cbs = callbacks;
 	while (cbs != NULL) {
+		PurplePrefsUiOps *uiop;
 		struct pref_cb *cb = cbs->data;
-		if(cb->handle == handle) {
-			pref->callbacks = g_slist_delete_link(pref->callbacks, cbs);
-			g_free(cb);
-			cbs = pref->callbacks;
-		} else
+		if (cb->handle != handle) {
 			cbs = cbs->next;
-	}
-
-	for(child = pref->first_child; child; child = child->sibling)
-		disco_callback_helper_handle(child, handle);
-}
+			continue;
+		}
 
-void
-purple_prefs_disconnect_by_handle(void *handle)
-{
-	g_return_if_fail(handle != NULL);
+		uiop = purple_prefs_get_ui_ops();
+		uiop->remove_observer(cb->name, cb->observer);
 
-	disco_callback_helper_handle(&prefs, handle);
+		callbacks = g_slist_delete_link(callbacks, cbs);
+		g_free(cb->name);
+		g_free(cb);
+		cbs = callbacks;
+	}
 }
 
 GList *
 purple_prefs_get_children_names(const char *name)
-{
-	GList * list = NULL;
-	struct purple_pref *pref = find_pref(name), *child;
-	char sep[2] = "\0\0";;
-
-	if (pref == NULL)
-		return NULL;
-
-	if (name[strlen(name) - 1] != '/')
-		sep[0] = '/';
-	for (child = pref->first_child; child; child = child->sibling) {
-		list = g_list_append(list, g_strdup_printf("%s%s%s", name, sep, child->name));
-	}
-	return list;
-}
-
-void
-purple_prefs_update_old()
-{
-	purple_prefs_rename("/core", "/purple");
-
-	/* Remove some no-longer-used prefs */
-	purple_prefs_remove("/purple/away/auto_response/enabled");
-	purple_prefs_remove("/purple/away/auto_response/idle_only");
-	purple_prefs_remove("/purple/away/auto_response/in_active_conv");
-	purple_prefs_remove("/purple/away/auto_response/sec_before_resend");
-	purple_prefs_remove("/purple/away/auto_response");
-	purple_prefs_remove("/purple/away/default_message");
-	purple_prefs_remove("/purple/buddies/use_server_alias");
-	purple_prefs_remove("/purple/conversations/away_back_on_send");
-	purple_prefs_remove("/purple/conversations/send_urls_as_links");
-	purple_prefs_remove("/purple/conversations/im/show_login");
-	purple_prefs_remove("/purple/conversations/chat/show_join");
-	purple_prefs_remove("/purple/conversations/chat/show_leave");
-	purple_prefs_remove("/purple/conversations/combine_chat_im");
-	purple_prefs_remove("/purple/conversations/use_alias_for_title");
-	purple_prefs_remove("/purple/logging/log_signon_signoff");
-	purple_prefs_remove("/purple/logging/log_idle_state");
-	purple_prefs_remove("/purple/logging/log_away_state");
-	purple_prefs_remove("/purple/logging/log_own_states");
-	purple_prefs_remove("/purple/status/scores/hidden");
-	purple_prefs_remove("/plugins/core/autorecon/hide_connected_error");
-	purple_prefs_remove("/plugins/core/autorecon/hide_connecting_error");
-	purple_prefs_remove("/plugins/core/autorecon/hide_reconnecting_dialog");
-	purple_prefs_remove("/plugins/core/autorecon/restore_state");
-	purple_prefs_remove("/plugins/core/autorecon");
-
-	/* Convert old sounds while_away pref to new 3-way pref. */
-	if (purple_prefs_exists("/purple/sound/while_away") &&
-	    purple_prefs_get_bool("/purple/sound/while_away"))
-	{
-		purple_prefs_set_int("/purple/sound/while_status", 3);
-	}
-	purple_prefs_remove("/purple/sound/while_away");
-}
+	UIOP_return(get_children_names(name), NULL)
 
 void *
 purple_prefs_get_handle(void)
@@ -1390,8 +309,6 @@
 {
 	void *handle = purple_prefs_get_handle();
 
-	prefs_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
 	purple_prefs_connect_callback(handle, "/", prefs_save_cb, NULL);
 
 	purple_prefs_add_none("/purple");
@@ -1402,34 +319,7 @@
 
 	/* Away */
 	purple_prefs_add_none("/purple/away");
-	purple_prefs_add_string("/purple/away/idle_reporting", "system");
-	purple_prefs_add_bool("/purple/away/away_when_idle", TRUE);
-	purple_prefs_add_int("/purple/away/mins_before_away", 5);
-
-	/* Away -> Auto-Reply */
-	if (!purple_prefs_exists("/purple/away/auto_response/enabled") ||
-	    !purple_prefs_exists("/purple/away/auto_response/idle_only"))
-	{
-		purple_prefs_add_string("/purple/away/auto_reply", "awayidle");
-	}
-	else
-	{
-		if (!purple_prefs_get_bool("/purple/away/auto_response/enabled"))
-		{
-			purple_prefs_add_string("/purple/away/auto_reply", "never");
-		}
-		else
-		{
-			if (purple_prefs_get_bool("/purple/away/auto_response/idle_only"))
-			{
-				purple_prefs_add_string("/purple/away/auto_reply", "awayidle");
-			}
-			else
-			{
-				purple_prefs_add_string("/purple/away/auto_reply", "away");
-			}
-		}
-	}
+	purple_prefs_add_string("/purple/away/auto_reply", "awayidle");
 
 	/* Buddies */
 	purple_prefs_add_none("/purple/buddies");
@@ -1442,7 +332,6 @@
 	purple_prefs_remove("/purple/contact/idle_score");
 
 	purple_prefs_load();
-	purple_prefs_update_old();
 }
 
 void
@@ -1451,15 +340,22 @@
 	if (save_timer != 0)
 	{
 		purple_timeout_remove(save_timer);
-		save_timer = 0;
-		sync_prefs();
+		save_cb(NULL);
 	}
 
 	purple_prefs_disconnect_by_handle(purple_prefs_get_handle());
 
 	prefs_loaded = FALSE;
-	purple_prefs_destroy();
-	g_hash_table_destroy(prefs_hash);
-	prefs_hash = NULL;
+}
 
+void
+purple_prefs_set_ui_ops(PurplePrefsUiOps *ops)
+{
+	prefs_ui_ops = ops;
+}
+
+PurplePrefsUiOps *
+purple_prefs_get_ui_ops(void)
+{
+	return prefs_ui_ops;
 }
diff -ru extract/pidgin-2.10.9/libpurple/prefs.h libpurple/prefs.h
--- extract/pidgin-2.10.9/libpurple/prefs.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/prefs.h	2015-05-04 13:42:04.500970477 +0200
@@ -38,6 +38,8 @@
 	PURPLE_PREF_BOOLEAN,     /**< Boolean.         */
 	PURPLE_PREF_INT,         /**< Integer.         */
 	PURPLE_PREF_STRING,      /**< String.          */
+	/* The 3 following types are unused in libpurple,
+	   and not implemented in Instantbird */
 	PURPLE_PREF_STRING_LIST, /**< List of strings. */
 	PURPLE_PREF_PATH,        /**< Path.            */
 	PURPLE_PREF_PATH_LIST    /**< List of paths.   */
@@ -62,11 +64,71 @@
 typedef void (*PurplePrefCallback) (const char *name, PurplePrefType type,
 		gconstpointer val, gpointer data);
 
+
+/** @copydoc _PurplePrefsUiOps */
+typedef struct _PurplePrefsUiOps PurplePrefsUiOps;
+
+
+/**  Prefs UI operations
+ */
+struct _PurplePrefsUiOps
+{
+	void (*add_none)(const char *name);
+	void (*add_bool)(const char *name, gboolean value);
+	void (*add_int)(const char *name, int value);
+	void (*add_string)(const char *name, const char *value);
+
+	void (*set_bool)(const char *name, gboolean value);
+	void (*set_int)(const char *name, int value);
+	void (*set_string)(const char *name, const char *value);
+
+	gboolean (*get_bool)(const char *name);
+	int (*get_int)(const char *name);
+	const char *(*get_string)(const char *name);
+
+	PurplePrefType (*get_type)(const char *name);
+	GList *(*get_children_names)(const char *name);
+
+	gboolean (*exists)(const char *name);
+	void (*remove)(const char *name);
+
+	void (*save)(void);
+
+	void *(*add_observer)(const char *name, gpointer data);
+	void (*remove_observer)(const char *name, void *observer);
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**************************************************************************/
+/** @name UI Registration Functions                                       */
+/**************************************************************************/
+/*@{*/
+/**
+ * Sets the UI operations structure to be used for preferences.
+ *
+ * @param ops The UI operations structure.
+ */
+void purple_prefs_set_ui_ops(PurplePrefsUiOps *ops);
+
+/**
+ * Returns the UI operations structure used for preferences.
+ *
+ * @return The UI operations structure in use.
+ */
+PurplePrefsUiOps *purple_prefs_get_ui_ops(void);
+
+/*@}*/
+
+/**************************************************************************/
 /** @name Prefs API
     Preferences are named according to a directory-like structure.
     Example: "/plugins/core/potato/is_from_idaho" (probably a boolean)    */
@@ -122,37 +184,6 @@
 void purple_prefs_add_string(const char *name, const char *value);
 
 /**
- * Add a new string list pref.
- *
- * @param name  The name of the pref
- * @param value The initial value to set
- * @note This function takes a copy of the strings in the value list. The list
- *       itself and original copies of the strings are up to the caller to
- *       free.
- */
-void purple_prefs_add_string_list(const char *name, GList *value);
-
-/**
- * Add a new path pref.
- *
- * @param name  The name of the pref
- * @param value The initial value to set
- */
-void purple_prefs_add_path(const char *name, const char *value);
-
-/**
- * Add a new path list pref.
- *
- * @param name  The name of the pref
- * @param value The initial value to set
- * @note This function takes a copy of the strings in the value list. The list
- *       itself and original copies of the strings are up to the caller to
- *       free.
- */
-void purple_prefs_add_path_list(const char *name, GList *value);
-
-
-/**
  * Remove a pref.
  *
  * @param name The name of the pref
@@ -160,44 +191,6 @@
 void purple_prefs_remove(const char *name);
 
 /**
- * Rename a pref
- *
- * @param oldname The old name of the pref
- * @param newname The new name for the pref
- */
-void purple_prefs_rename(const char *oldname, const char *newname);
-
-/**
- * Rename a boolean pref, toggling it's value
- *
- * @param oldname The old name of the pref
- * @param newname The new name for the pref
- */
-void purple_prefs_rename_boolean_toggle(const char *oldname, const char *newname);
-
-/**
- * Remove all prefs.
- */
-void purple_prefs_destroy(void);
-
-/**
- * Set raw pref value
- *
- * @param name  The name of the pref
- * @param value The value to set
- *
- * @deprecated We're not really sure what purpose this function serves, so it
- *             will be removed in 3.0.0.  Preferences values set using this
- *             function aren't serialized to prefs.xml, which could be
- *             misleading.  There is also no purple_prefs_get_generic, which
- *             means that if you can't really get the value (other in a
- *             connected callback).  If you think you have a use for this then
- *             please let us know.
- */
-/* TODO: When this is removed, also remove struct purple_pref->value.generic */
-void purple_prefs_set_generic(const char *name, gpointer value);
-
-/**
  * Set boolean pref value
  *
  * @param name  The name of the pref
@@ -221,30 +214,6 @@
  */
 void purple_prefs_set_string(const char *name, const char *value);
 
-/**
- * Set string list pref value
- *
- * @param name  The name of the pref
- * @param value The value to set
- */
-void purple_prefs_set_string_list(const char *name, GList *value);
-
-/**
- * Set path pref value
- *
- * @param name  The name of the pref
- * @param value The value to set
- */
-void purple_prefs_set_path(const char *name, const char *value);
-
-/**
- * Set path list pref value
- *
- * @param name  The name of the pref
- * @param value The value to set
- */
-void purple_prefs_set_path_list(const char *name, GList *value);
-
 
 /**
  * Check if a pref exists
@@ -287,30 +256,6 @@
 const char *purple_prefs_get_string(const char *name);
 
 /**
- * Get string list pref value
- *
- * @param name The name of the pref
- * @return The value of the pref
- */
-GList *purple_prefs_get_string_list(const char *name);
-
-/**
- * Get path pref value
- *
- * @param name The name of the pref
- * @return The value of the pref
- */
-const char *purple_prefs_get_path(const char *name);
-
-/**
- * Get path list pref value
- *
- * @param name The name of the pref
- * @return The value of the pref
- */
-GList *purple_prefs_get_path_list(const char *name);
-
-/**
  * Returns a list of children for a pref
  *
  * @param name The parent pref
@@ -338,6 +283,11 @@
 		gpointer data);
 
 /**
+ * Call the callback of the observer
+ */
+void purple_prefs_observe(gpointer data);
+
+/**
  * Remove a callback to a pref
  */
 void purple_prefs_disconnect_callback(guint callback_id);
@@ -357,11 +307,6 @@
  */
 gboolean purple_prefs_load(void);
 
-/**
- * Rename legacy prefs and delete some that no longer exist.
- */
-void purple_prefs_update_old(void);
-
 /*@}*/
 
 #ifdef __cplusplus
Only in libpurple/protocols/bonjour: Makefile.in
Only in libpurple/protocols/bonjour: moz.build
Only in libpurple/protocols/bonjour: win32
Only in libpurple/protocols: create-cid.sh
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/common.c libpurple/protocols/gg/lib/common.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/common.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/common.c	2015-05-04 13:42:04.544970475 +0200
@@ -44,7 +44,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 
 #include "libgadu.h"
 
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/dcc7.c libpurple/protocols/gg/lib/dcc7.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/dcc7.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/dcc7.c	2015-05-04 13:42:04.544970475 +0200
@@ -49,7 +49,9 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 
 #include "compat.h"
 #include "libgadu.h"
@@ -58,8 +60,8 @@
 #include "libgadu-internal.h"
 #include "libgadu-debug.h"
 
-#define gg_debug_dcc(dcc, level, fmt...) \
-	gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt)
+#define gg_debug_dcc(dcc, level, ...) \
+	gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, __VA_ARGS__)
 
 #define gg_debug_dump_dcc(dcc, level, buf, len) \
 	gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len)
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/events.c libpurple/protocols/gg/lib/events.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/events.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/events.c	2015-05-04 13:42:04.548970475 +0200
@@ -50,7 +50,9 @@
 #include <string.h>
 #include <stdlib.h>
 #include <time.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 #include <ctype.h>
 #ifdef GG_CONFIG_HAVE_GNUTLS
 #  include <gnutls/gnutls.h>
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/handlers.c libpurple/protocols/gg/lib/handlers.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/handlers.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/handlers.c	2015-05-04 13:42:04.548970475 +0200
@@ -59,7 +59,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 #include <time.h>
 #ifdef GG_CONFIG_HAVE_OPENSSL
 #  include <openssl/err.h>
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/http.c libpurple/protocols/gg/lib/http.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/http.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/http.c	2015-05-04 13:42:04.548970475 +0200
@@ -45,7 +45,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 
 #define GG_HTTP_MAX_LENGTH 1000000000
 
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/libgadu.c libpurple/protocols/gg/lib/libgadu.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/libgadu.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/libgadu.c	2015-05-04 13:42:04.552970475 +0200
@@ -65,7 +65,9 @@
 #include <string.h>
 #include <signal.h>
 #include <time.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 #ifdef GG_CONFIG_HAVE_GNUTLS
 #  include <gnutls/gnutls.h>
 #endif
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/libgadu-config.h libpurple/protocols/gg/lib/libgadu-config.h
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/libgadu-config.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/libgadu-config.h	2015-05-04 13:42:04.552970475 +0200
@@ -1,6 +1,6 @@
 /* Local libgadu configuration. */
 
-#include "config.h"
+/*#include "config.h" */
 
 #ifndef __GG_LIBGADU_CONFIG_H
 #define __GG_LIBGADU_CONFIG_H
@@ -11,11 +11,13 @@
 #define __GG_LIBGADU_BIGENDIAN
 #endif /* WORDS_BIGENDIAN */
 
+#ifndef _WIN32
 /* Defined if this machine has va_copy(). */
 #define __GG_LIBGADU_HAVE_VA_COPY
 
 /* Defined if this machine has __va_copy(). */
 #define __GG_LIBGADU_HAVE___VA_COPY
+#endif
 
 /* Defined if this machine supports long long. */
 #undef __GG_LIBGADU_HAVE_LONG_LONG
@@ -56,4 +58,18 @@
 #define random (long) rand
 #endif
 
+#ifdef _MSC_VER
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8  uint8_t;
+#define snprintf _snprintf
+#include <win32dep.h>
+#define EINPROGRESS WSAEINPROGRESS
+#define ECONNRESET WSAECONNRESET
+#define ENOTCONN WSAENOTCONN
+#define strncasecmp strnicmp
+#define strcasecmp stricmp
+#define ssize_t SSIZE_T
+#endif
+
 #endif /* __GG_LIBGADU_CONFIG_H */
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/libgadu.h libpurple/protocols/gg/lib/libgadu.h
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/libgadu.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/libgadu.h	2015-05-04 13:42:04.556970475 +0200
@@ -41,6 +41,8 @@
 extern "C" {
 #endif
 
+#include "libgadu-config.h"
+
 #include <sys/types.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -2288,9 +2290,11 @@
 
 #define GG_DCC7_DUNNO1 0x24
 
+#if 0
 struct gg_dcc7_dunno1 {
 	// XXX
 } GG_PACKED;
+#endif
 
 #define GG_DCC7_TIMEOUT_CONNECT 10	/* 10 sekund */
 #define GG_DCC7_TIMEOUT_SEND 1800	/* 30 minut */
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/message.h libpurple/protocols/gg/lib/message.h
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/message.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/message.h	2015-05-04 13:42:04.556970475 +0200
@@ -20,7 +20,6 @@
 #define LIBGADU_MESSAGE_H
 
 #include <sys/types.h>
-#include <inttypes.h>
 #include "libgadu.h"
 
 #if 0
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/pubdir.c libpurple/protocols/gg/lib/pubdir.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/pubdir.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/pubdir.c	2015-05-04 13:42:04.556970475 +0200
@@ -32,7 +32,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#ifndef _MSC_VER
 #include <unistd.h>
+#endif
 
 #include "libgadu.h"
 #include "libgadu-config.h"
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/resolver.c libpurple/protocols/gg/lib/resolver.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/resolver.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/resolver.c	2015-05-04 13:42:04.556970475 +0200
@@ -33,7 +33,9 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#ifndef _MSC_VER
+#  include <unistd.h>
+#endif
 #ifndef _WIN32
 #  include <signal.h>
 #  include <netinet/in.h>
diff -ru extract/pidgin-2.10.9/libpurple/protocols/gg/lib/sha1.c libpurple/protocols/gg/lib/sha1.c
--- extract/pidgin-2.10.9/libpurple/protocols/gg/lib/sha1.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/gg/lib/sha1.c	2015-05-04 13:42:04.560970475 +0200
@@ -28,7 +28,9 @@
 
 #include <string.h>
 #include <sys/types.h>
+#ifndef _MSC_VER
 #include <unistd.h>
+#endif
 
 #include "libgadu.h"
 
Only in libpurple/protocols/gg: Makefile.in
Only in libpurple/protocols/gg: moz.build
Only in extract/pidgin-2.10.9/libpurple/protocols: irc
Only in extract/pidgin-2.10.9/libpurple/protocols/jabber: auth_cyrus.c
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/buddy.c libpurple/protocols/jabber/buddy.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/buddy.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/buddy.c	2015-05-04 13:42:04.568970474 +0200
@@ -131,9 +131,6 @@
 	const JabberBuddyResource *jbrb = b;
 	JabberBuddyState state_a, state_b;
 
-	if (jbra->priority != jbrb->priority)
-		return jbra->priority > jbrb->priority ? -1 : 1;
-
 	/* Fold the states for easier comparison */
 	/* TODO: Differentiate online/chat and away/dnd? */
 	switch (jbra->state) {
@@ -177,6 +174,9 @@
 	}
 
 	if (state_a == state_b) {
+		if (jbra->priority != jbrb->priority)
+			return jbra->priority > jbrb->priority ? -1 : 1;
+
 		if (jbra->idle == jbrb->idle)
 			return 0;
 		else if ((jbra->idle && !jbrb->idle) ||
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/disco.c libpurple/protocols/jabber/disco.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/disco.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/disco.c	2015-05-04 13:42:04.572970474 +0200
@@ -35,7 +35,9 @@
 #include "google/jingleinfo.h"
 #include "iq.h"
 #include "jabber.h"
+#ifdef USE_JINGLE
 #include "jingle/jingle.h"
+#endif
 #include "pep.h"
 #include "presence.h"
 #include "roster.h"
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/google/google_session.c libpurple/protocols/jabber/google/google_session.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/google/google_session.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/google/google_session.c	2015-05-04 13:42:04.576970474 +0200
@@ -23,10 +23,10 @@
 #include "google_session.h"
 #include "relay.h"
 
-#include "jingle/jingle.h"
-
 #ifdef USE_VV
 
+#include "jingle/jingle.h"
+
 typedef struct {
 	PurpleMedia *media;
 	gboolean video;
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/iq.c libpurple/protocols/jabber/iq.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/iq.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/iq.c	2015-05-04 13:42:04.580970474 +0200
@@ -33,7 +33,9 @@
 #include "google/jingleinfo.h"
 #include "google/google_session.h"
 #include "iq.h"
+#ifdef USE_JINGLE
 #include "jingle/jingle.h"
+#endif
 #include "oob.h"
 #include "roster.h"
 #include "si.h"
@@ -43,7 +45,7 @@
 #include "ibb.h"
 
 #ifdef _WIN32
-#include "utsname.h"
+#include "win32/utsname.h"
 #endif
 
 static GHashTable *iq_handlers = NULL;
@@ -552,7 +554,9 @@
 	iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 	signal_iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 
+#ifdef USE_JINGLE
 	jabber_iq_register_handler("jingle", JINGLE, jingle_parse);
+#endif
 	jabber_iq_register_handler("mailbox", NS_GOOGLE_MAIL_NOTIFY,
 			jabber_gmail_poke);
 	jabber_iq_register_handler("new-mail", NS_GOOGLE_MAIL_NOTIFY,
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jabber.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/jabber.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/jabber.c	2015-05-04 13:42:04.584970474 +0200
@@ -69,8 +69,10 @@
 #include "pep.h"
 #include "adhoccommands.h"
 
+#ifdef USE_JINGLE
 #include "jingle/jingle.h"
 #include "jingle/rtp.h"
+#endif
 
 #define PING_TIMEOUT 60
 /* Send a whitespace keepalive to the server if we haven't sent
@@ -1589,8 +1591,10 @@
 {
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 
+#ifdef USE_JINGLE
 	/* Close all of the open Jingle sessions on this stream */
 	jingle_terminate_sessions(js);
+#endif
 
 	if (js->bosh)
 		jabber_bosh_connection_close(js->bosh);
@@ -3866,8 +3870,10 @@
 	/* Bits Of Binary */
 	jabber_add_feature(NS_BOB, 0);
 
+#ifdef USE_JINGLE
 	/* Jingle features! */
 	jabber_add_feature(JINGLE, 0);
+#endif
 
 #ifdef USE_VV
 	jabber_add_feature(NS_GOOGLE_PROTOCOL_SESSION, jabber_audio_enabled);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/jabber.h libpurple/protocols/jabber/jabber.h
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/jabber.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/jabber.h	2015-05-04 13:42:04.584970474 +0200
@@ -60,8 +60,10 @@
 #include "connection.h"
 #include "dnsquery.h"
 #include "dnssrv.h"
+#ifdef USE_VV
 #include "media.h"
 #include "mediamanager.h"
+#endif
 #include "roomlist.h"
 #include "sslconn.h"
 
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/libxmpp.c libpurple/protocols/jabber/libxmpp.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/libxmpp.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/libxmpp.c	2015-05-04 13:42:04.584970474 +0200
@@ -258,11 +258,11 @@
 	GList *encryption_values = NULL;
 
 	/* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
-	split = purple_account_user_split_new(_("Domain"), NULL, '@');
+	split = purple_account_user_split_new(_("Domain"), "jabber.org", '@');
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 
-	split = purple_account_user_split_new(_("Resource"), "", '/');
+	split = purple_account_user_split_new(_("Resource"), "Instantbird", '/');
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 
@@ -315,13 +315,6 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.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,
-		option);
-
 	my_protocol = plugin;
 
 	purple_prefs_remove("/plugins/prpl/jabber");
Only in libpurple/protocols/jabber: Makefile.in
diff -ru extract/pidgin-2.10.9/libpurple/protocols/jabber/message.c libpurple/protocols/jabber/message.c
--- extract/pidgin-2.10.9/libpurple/protocols/jabber/message.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/jabber/message.c	2015-05-04 13:42:04.588970474 +0200
@@ -106,7 +106,8 @@
 					 * this should be able to be implemented by removing the
 					 * user from the conversation like we do with chats now. */
 					purple_conversation_write(conv, "", buf,
-					                        PURPLE_MESSAGE_SYSTEM, time(NULL));
+					                          PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY,
+					                          time(NULL));
 				}
 			}
 			serv_got_typing_stopped(gc, jm->from);
@@ -602,7 +603,7 @@
 				GList *smiley_refs = NULL;
 				gchar *reformatted_xhtml;
 
-				if (purple_account_get_bool(account, "custom_smileys", TRUE)) {
+				if (purple_account_get_bool(account, "custom_smileys", FALSE)) {
 					/* find a list of smileys ("cid" and "alt" text pairs)
 					  occuring in the message */
 					smiley_refs = jabber_message_get_refs_from_xmlnode(child);
@@ -1303,5 +1304,5 @@
 	const PurpleConnection *gc = js->gc;
 	PurpleAccount *account = purple_connection_get_account(gc);
 
-	return purple_account_get_bool(account, "custom_smileys", TRUE);
+	return purple_account_get_bool(account, "custom_smileys", FALSE);
 }
Only in libpurple/protocols/jabber: moz.build
Only in libpurple/protocols: module.ver.in
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/cmdproc.c libpurple/protocols/msn/cmdproc.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/cmdproc.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/cmdproc.c	2015-05-04 13:42:04.452970479 +0200
@@ -109,22 +109,21 @@
 	g_free(show);
 }
 
-gboolean
+void
 msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
 {
 	MsnServConn *servconn;
 	char *data;
 	size_t len;
-	gboolean ret;
 
-	g_return_val_if_fail(cmdproc != NULL, TRUE);
-	g_return_val_if_fail(trans != NULL, TRUE);
+	g_return_if_fail(cmdproc != NULL);
+	g_return_if_fail(trans != NULL);
 
 	servconn = cmdproc->servconn;
 
 	if (!servconn->connected) {
 		msn_transaction_destroy(trans);
-		return FALSE;
+		return;
 	}
 
 	if (trans->saveable)
@@ -155,12 +154,11 @@
 		trans->payload_len = 0;
 	}
 
-	ret = msn_servconn_write(servconn, data, len) != -1;
+	msn_servconn_write(servconn, data, len);
 
 	if (!trans->saveable)
 		msn_transaction_destroy(trans);
 	g_free(data);
-	return ret;
 }
 
 void
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/cmdproc.h libpurple/protocols/msn/cmdproc.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/cmdproc.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/cmdproc.h	2015-05-04 13:42:04.452970479 +0200
@@ -79,7 +79,7 @@
  * @param cmdproc 	The MsnCmdProc to be used.
  * @param trans 	The MsnTransaction to be sent.
  */
-gboolean msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
+void msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
 
 /**
  * Add a transaction to the queue to be processed latter.
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/contact.c libpurple/protocols/msn/contact.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/contact.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/contact.c	2015-05-04 13:42:04.456970479 +0200
@@ -474,7 +474,7 @@
 }
 
 /*parse contact list*/
-static gboolean
+static void
 msn_parse_contact_list(MsnSession *session, xmlnode *node)
 {
 	xmlnode *fault, *faultnode;
@@ -499,14 +499,13 @@
 			if (g_str_equal(errorcode, "ABDoesNotExist")) {
 				msn_create_address_book(session);
 				g_free(errorcode);
-				return FALSE;
+				return;
 			}
 
 			g_free(errorcode);
 		}
 
 		msn_get_contact_list(session, MSN_PS_INITIAL, NULL);
-		return FALSE;
 	} else {
 		xmlnode *service;
 
@@ -515,7 +514,6 @@
 			 service; service = xmlnode_get_next_twin(service)) {
 			msn_parse_each_service(session, service);
 		}
-		return TRUE;
 	}
 }
 
@@ -536,24 +534,23 @@
 
 		purple_debug_misc("msn", "Got the contact list!\n");
 
-		if (msn_parse_contact_list(session, resp->xml)) {
+		msn_parse_contact_list(session, resp->xml);
 #ifdef MSN_PARTIAL_LISTS
-			abLastChange = purple_account_get_string(session->account,
-				"ablastChange", NULL);
-			dynamicItemLastChange = purple_account_get_string(session->account,
-				"DynamicItemLastChanged", NULL);
+		abLastChange = purple_account_get_string(session->account,
+			"ablastChange", NULL);
+		dynamicItemLastChange = purple_account_get_string(session->account,
+			"DynamicItemLastChanged", NULL);
 #endif
 
-			if (state->partner_scenario == MSN_PS_INITIAL) {
+		if (state->partner_scenario == MSN_PS_INITIAL) {
 #ifdef MSN_PARTIAL_LISTS
-				/* XXX: this should be enabled when we can correctly do partial
-				   syncs with the server. Currently we need to retrieve the whole
-				   list to detect sync issues */
-				msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
+			/* XXX: this should be enabled when we can correctly do partial
+			   syncs with the server. Currently we need to retrieve the whole
+			   list to detect sync issues */
+			msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
 #else
-				msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
+			msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
 #endif
-			}
 		}
 	}
 }
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/directconn.c libpurple/protocols/msn/directconn.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/directconn.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/directconn.c	2015-05-04 13:42:04.456970479 +0200
@@ -51,9 +51,6 @@
 		purple_cipher_context_destroy(context);
 	} else if (type == DC_NONCE_PLAIN) {
 		memcpy(digest, nonce, nonce_len);
-	} else {
-		nonce_hash[0] = '\0';
-		g_return_if_reached();
 	}
 
 	g_sprintf(nonce_hash,
@@ -596,9 +593,7 @@
 
 	case DC_STATE_ESTABLISHED:
 		if (packet_length) {
-			MsnP2PVersion p2p;
-			p2p = msn_slplink_get_p2p_version(dc->slplink);
-			part = msn_slpmsgpart_new_from_data(p2p, dc->in_buffer + 4, packet_length);
+			part = msn_slpmsgpart_new_from_data(dc->in_buffer + 4, packet_length);
 			if (part) {
 				msn_slplink_process_msg(dc->slplink, part);
 				msn_slpmsgpart_unref(part);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/httpconn.c libpurple/protocols/msn/httpconn.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/httpconn.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/httpconn.c	2015-05-04 13:42:04.460970479 +0200
@@ -111,8 +111,8 @@
 			return TRUE;
 		}
 
-		size -= (s - buf);
 		buf = s;
+		size -= (s - buf);
 	}
 
 	if ((s = strstr(buf, "\r\n\r\n")) == NULL)
Only in libpurple/protocols/msn: Makefile.in
Only in libpurple/protocols/msn: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/msg.c libpurple/protocols/msn/msg.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/msg.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/msg.c	2015-05-04 13:42:04.464970479 +0200
@@ -135,6 +135,8 @@
 
 	msn_message_set_header(msg, "User-Agent", NULL);
 
+	msg->msnslp_message = TRUE;
+
 	msn_message_set_flag(msg, 'D');
 	msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
 
@@ -250,6 +252,12 @@
 	/* Now we *should* be at the body. */
 	content_type = msn_message_get_content_type(msg);
 
+	if (content_type != NULL &&
+		!strcmp(content_type, "application/x-msnmsgrp2p")) {
+		msg->msnslp_message = TRUE;
+		msg->part = msn_slpmsgpart_new_from_data(tmp, payload_len - (tmp - tmp_base));
+	}
+
 	if (payload_len - (tmp - tmp_base) > 0) {
 		msg->body_len = payload_len - (tmp - tmp_base);
 		g_free(msg->body);
@@ -371,19 +379,26 @@
 
 	body = msn_message_get_bin_data(msg, &body_len);
 
-	if (body != NULL && (end - n) > body_len)
+	if (msg->msnslp_message)
 	{
-		memcpy(n, body, body_len);
-		n += body_len;
-		*n = '\0';
-	}
+		size_t siz;
+		char *body;
 
-	if (ret_size != NULL)
-	{
-		*ret_size = n - base;
+		body = msn_slpmsgpart_serialize(msg->part, &siz);
 
-		if (*ret_size > 1664)
-			*ret_size = 1664;
+		memcpy(n, body, siz);
+		n += siz;
+
+		g_free(body);
+	}
+	else
+	{
+		if (body != NULL)
+		{
+			memcpy(n, body, body_len);
+			n += body_len;
+			*n = '\0';
+		}
 	}
 
 	return base;
@@ -624,23 +639,43 @@
 
 	body = msn_message_get_bin_data(msg, &body_len);
 
-	if (body != NULL)
+	if (msg->msnslp_message)
 	{
-		if (msg->type == MSN_MSG_TEXT)
-		{
-			g_string_append_len(str, body, body_len);
-			g_string_append(str, "\r\n");
-		}
-		else
+		msn_slpmsgpart_to_string(msg->part, str);
+
+		if (purple_debug_is_verbose() && body != NULL)
 		{
-			size_t i;
-			for (i = 0; i < body_len; i++, body++)
+			if (text_body)
+			{
+				g_string_append_len(str, body, body_len);
+				if (body[body_len - 1] == '\0')
+				{
+					str->len--;
+					g_string_append(str, " 0x00");
+				}
+				g_string_append(str, "\r\n");
+			}
+			else
 			{
-				g_string_append_printf(str, "%02x ", (unsigned char)*body);
-				if (i % 16 == 0 && i != 0)
-					g_string_append_c(str, '\n');
+				int i;
+
+				for (i = 0; i < body_len; i++)
+				{
+					g_string_append_printf(str, "%.2hhX ", body[i]);
+					if ((i % 16) == 15)
+						g_string_append(str, "\r\n");
+				}
+
+				g_string_append(str, "\r\n");
 			}
-			g_string_append_c(str, '\n');
+		}
+	}
+	else
+	{
+		if (body != NULL)
+		{
+			g_string_append_len(str, body, body_len);
+			g_string_append(str, "\r\n");
 		}
 	}
 
@@ -819,6 +854,8 @@
 
 }
 
+#define purple_mkstemp(a, b) NULL
+
 /* TODO: Make these not be such duplicates of each other */
 static void
 got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
@@ -877,7 +914,6 @@
 {
 	MsnSession *session;
 	MsnSlpLink *slplink;
-	MsnP2PVersion p2p;
 
 	session = cmdproc->servconn->session;
 	slplink = msn_session_get_slplink(session, msg->remote_user);
@@ -900,13 +936,11 @@
 		}
 	}
 
-	p2p = msn_slplink_get_p2p_version(slplink);
-	msg->part = msn_slpmsgpart_new_from_data(p2p, msg->body, msg->body_len);
-
-	if (msg->part)
+	if (msg->part) {
 		msn_slplink_process_msg(slplink, msg->part);
-	else
-		purple_debug_warning("msn", "P2P message failed to parse.\n");
+	}
+	else /* This should never happen. */
+		purple_debug_fatal("msn", "P2P message without a Part.\n");
 }
 
 static void
@@ -947,7 +981,7 @@
 
 	session = cmdproc->servconn->session;
 
-	if (!purple_account_get_bool(session->account, "custom_smileys", TRUE))
+	if (!purple_account_get_bool(session->account, "custom_smileys", FALSE))
 		return;
 
 	swboard = cmdproc->data;
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/msg.h libpurple/protocols/msn/msg.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/msg.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/msg.h	2015-05-04 13:42:04.464970479 +0200
@@ -78,6 +78,7 @@
 
 	MsnMsgType type;
 
+	gboolean msnslp_message;
 	MsnSlpMessagePart *part;
 
 	char *remote_user;
@@ -136,6 +137,15 @@
 MsnMessage *msn_message_new_plain(const char *message);
 
 /**
+ * Creates a MSNSLP ack message.
+ *
+ * @param acked_msg The message to acknowledge.
+ *
+ * @return A new MSNSLP ack message.
+ */
+MsnMessage *msn_message_new_msnslp_ack(MsnMessage *acked_msg);
+
+/**
  * Creates a new message based off a command.
  *
  * @param session The MSN session.
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/msn.c libpurple/protocols/msn/msn.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/msn.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/msn.c	2015-05-04 13:42:04.468970479 +0200
@@ -539,7 +539,7 @@
 	for (l = session->user->endpoints; l; l = l->next) {
 		MsnUserEndpoint *ep = l->data;
 
-		if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
+		if (ep->id[0] != '\0' && g_ascii_strncasecmp(ep->id + 1, session->guid, 36) == 0)
 			/* Don't add myself to the list */
 			continue;
 
@@ -608,7 +608,7 @@
 		MsnUserEndpoint *ep = l->data;
 		char *user;
 
-		if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
+		if (ep->id[0] != '\0' && g_ascii_strncasecmp(ep->id + 1, session->guid, 36) == 0)
 			/* Don't kick myself */
 			continue;
 
@@ -3041,11 +3041,6 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.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,
-											   option);
-
 	option = purple_account_option_bool_new(_("Allow direct connections"),
 										  "direct_connect", TRUE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/msnutils.c libpurple/protocols/msn/msnutils.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/msnutils.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/msnutils.c	2015-05-04 13:42:04.468970479 +0200
@@ -265,6 +265,12 @@
 				msg[retcount++] = '\n';
 				c += 4;
 			}
+			else if (!g_ascii_strncasecmp(c + 1, "br/>", 4))
+			{
+				msg[retcount++] = '\r';
+				msg[retcount++] = '\n';
+				c += 5;
+			}
 			else if (!g_ascii_strncasecmp(c + 1, "i>", 2))
 			{
 				if (!has_italic)
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/nexus.c libpurple/protocols/msn/nexus.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/nexus.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/nexus.c	2015-05-04 13:42:04.468970479 +0200
@@ -26,7 +26,6 @@
 #include "cipher.h"
 #include "debug.h"
 
-#include "msnutils.h"
 #include "soap.h"
 #include "nexus.h"
 #include "notification.h"
@@ -165,46 +164,42 @@
 	return out;
 }
 
-#define MSN_USER_KEY_SIZE (7*4 + 8 + 20 + 72)
 #define CRYPT_MODE_CBC 1
 #define CIPHER_TRIPLE_DES 0x6603
 #define HASH_SHA1 0x8004
 static char *
 msn_rps_encrypt(MsnNexus *nexus)
 {
-	char usr_key_base[MSN_USER_KEY_SIZE], *usr_key;
+	MsnUsrKey *usr_key;
 	const char magic1[] = "SESSION KEY HASH";
 	const char magic2[] = "SESSION KEY ENCRYPTION";
 	PurpleCipherContext *hmac;
 	size_t len;
-	guchar *hash;
+	guchar hash[20];
 	char *key1, *key2, *key3;
 	gsize key1_len;
-	const char *iv;
+	int *iv;
 	char *nonce_fixed;
 	char *cipher;
 	char *response;
 
-	usr_key = &usr_key_base[0];
-	/* Header */
-	msn_push32le(usr_key, 28);                  /* Header size */
-	msn_push32le(usr_key, CRYPT_MODE_CBC);      /* Crypt mode */
-	msn_push32le(usr_key, CIPHER_TRIPLE_DES);   /* Cipher type */
-	msn_push32le(usr_key, HASH_SHA1);           /* Hash type */
-	msn_push32le(usr_key, 8);                   /* IV size */
-	msn_push32le(usr_key, 20);                  /* Hash size */
-	msn_push32le(usr_key, 72);                  /* Cipher size */
-	/* Data */
-	iv = usr_key;
-	msn_push32le(usr_key, rand());
-	msn_push32le(usr_key, rand());
-	hash = (guchar *)usr_key;
-	usr_key += 20;  /* Remaining is cipher data */
+	usr_key = g_malloc(sizeof(MsnUsrKey));
+	usr_key->size = GUINT32_TO_LE(28);
+	usr_key->crypt_mode = GUINT32_TO_LE(CRYPT_MODE_CBC);
+	usr_key->cipher_type = GUINT32_TO_LE(CIPHER_TRIPLE_DES);
+	usr_key->hash_type = GUINT32_TO_LE(HASH_SHA1);
+	usr_key->iv_len = GUINT32_TO_LE(8);
+	usr_key->hash_len = GUINT32_TO_LE(20);
+	usr_key->cipher_len = GUINT32_TO_LE(72);
 
 	key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len);
 	key2 = rps_create_key(key1, key1_len, magic1, sizeof(magic1) - 1);
 	key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1);
 
+	iv = (int *)usr_key->iv;
+	iv[0] = rand();
+	iv[1] = rand();
+
 	len = strlen(nexus->nonce);
 	hmac = purple_cipher_context_new_by_name("hmac", NULL);
 	purple_cipher_context_set_option(hmac, "hash", "sha1");
@@ -217,17 +212,20 @@
 	nonce_fixed = g_malloc(len + 8);
 	memcpy(nonce_fixed, nexus->nonce, len);
 	memset(nonce_fixed + len, 0x08, 8);
-	cipher = des3_cbc(key3, iv, nonce_fixed, len + 8, FALSE);
+	cipher = des3_cbc(key3, usr_key->iv, nonce_fixed, len + 8, FALSE);
 	g_free(nonce_fixed);
 
-	memcpy(usr_key, cipher, 72);
+	memcpy(usr_key->hash, hash, 20);
+	memcpy(usr_key->cipher, cipher, 72);
 
 	g_free(key1);
 	g_free(key2);
 	g_free(key3);
 	g_free(cipher);
 
-	response = purple_base64_encode((guchar *)usr_key_base, MSN_USER_KEY_SIZE);
+	response = purple_base64_encode((guchar *)usr_key, sizeof(MsnUsrKey));
+
+	g_free(usr_key);
 
 	return response;
 }
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/nexus.h libpurple/protocols/msn/nexus.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/nexus.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/nexus.h	2015-05-04 13:42:04.468970479 +0200
@@ -28,6 +28,7 @@
 
 typedef struct _MsnNexus MsnNexus;
 typedef struct _MsnTicketToken MsnTicketToken;
+typedef struct _MsnUsrKey MsnUsrKey;
 
 /* Index into ticket_tokens in nexus.c Keep updated! */
 typedef enum
@@ -187,6 +188,21 @@
 	"</Body>"\
 "</Envelope>"
 
+struct _MsnUsrKey
+{
+	int size; /* 28. Does not count data */
+	int crypt_mode; /* CRYPT_MODE_CBC (1) */
+	int cipher_type; /* TripleDES (0x6603) */
+	int hash_type; /* SHA1 (0x8004) */
+	int iv_len;    /* 8 */
+	int hash_len;  /* 20 */
+	int cipher_len; /* 72 */
+	/* Data */
+	char iv[8];
+	char hash[20];
+	char cipher[72];
+};
+
 struct _MsnTicketToken {
 	GHashTable *token;
 	char *secret;
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/notification.c libpurple/protocols/msn/notification.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/notification.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/notification.c	2015-05-04 13:42:04.472970478 +0200
@@ -195,9 +195,6 @@
 	{
 		/* RPS authentication */
 
-		if (session->nexus)
-			msn_nexus_destroy(session->nexus);
-
 		session->nexus = msn_nexus_new(session);
 
 		session->nexus->policy = g_strdup(cmd->params[3]);
@@ -575,7 +572,6 @@
 		payload = xmlnode_to_str(adl_node, &payload_len);
 		msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
 		g_free(payload);
-		xmlnode_free(adl_node);
 	} else {
 		purple_debug_error("msn",
 		                   "Got FQY update for unknown user %s on network %d.\n",
@@ -1592,7 +1588,7 @@
 		/* Disconnect others, if MPOP is disabled */
 		if (is_me
 		 && !session->enable_mpop
-		 && strncasecmp(id + 1, session->guid, 36) != 0) {
+		 && g_ascii_strncasecmp(id + 1, session->guid, 36) != 0) {
 			purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
 
 			tmp = g_strdup_printf("%s;%s", user->passport, id);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/p2p.c libpurple/protocols/msn/p2p.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/p2p.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/p2p.c	2015-05-04 13:42:04.476970478 +0200
@@ -204,43 +204,41 @@
 
 		case MSN_P2P_VERSION_TWO: {
 			MsnP2Pv2Header *header = &info->header.v2;
-			char *header_wire = NULL;
-			char *data_header_wire = NULL;
 
 			if (header->header_tlv != NULL)
-				header_wire = msn_tlvlist_write(header->header_tlv, (size_t *)&header->header_len);
+				header->header_len = msn_tlvlist_size(header->header_tlv) + 8;
 			else
-				header->header_len = 0;
+				header->header_len = 8;
 
 			if (header->data_tlv != NULL)
-				data_header_wire = msn_tlvlist_write(header->data_tlv, (size_t *)&header->data_header_len);
+				header->data_header_len = msn_tlvlist_size(header->data_tlv) + 8;
 			else
-				header->data_header_len = 0;
+				header->data_header_len = 8;
 
-			tmp = wire = g_new(char, 16 + header->header_len + header->data_header_len);
+			tmp = wire = g_new(char, header->header_len + header->data_header_len);
 
-			msn_push8(tmp, header->header_len + 8);
+			msn_push8(tmp, header->header_len);
 			msn_push8(tmp, header->opcode);
-			msn_push16be(tmp, header->data_header_len + 8 + header->message_len);
+			msn_push16be(tmp, header->data_header_len + header->message_len);
 			msn_push32be(tmp, header->base_id);
 
-			if (header_wire != NULL) {
-				memcpy(tmp, header_wire, header->header_len);
-				tmp += header->header_len;
+			if (header->header_tlv != NULL) {
+				msn_tlvlist_write(tmp, header->header_len - 8, header->header_tlv);
+				tmp += header->header_len - 8;
 			}
 
-			msn_push8(tmp, header->data_header_len + 8);
+			msn_push8(tmp, header->data_header_len);
 			msn_push8(tmp, header->data_tf);
 			msn_push16be(tmp, header->package_number);
 			msn_push32be(tmp, header->session_id);
 
-			if (data_header_wire != NULL) {
-				memcpy(tmp, data_header_wire, header->data_header_len);
-				tmp += header->data_header_len;
+			if (header->data_tlv != NULL) {
+				msn_tlvlist_write(tmp, header->data_header_len - 8, header->data_tlv);
+				tmp += header->data_header_len - 8;
 			}
 
 			if (len)
-				*len = header->header_len + header->data_header_len + 16;
+				*len = header->header_len + header->data_header_len;
 
 			break;
 		}
@@ -250,6 +248,7 @@
 	}
 
 	return wire;
+
 }
 
 size_t
@@ -313,28 +312,11 @@
 }
 
 gboolean
-msn_p2p_msg_is_data(const MsnP2PInfo *info)
+msn_p2p_msg_is_data(const MsnP2PHeaderFlag flags)
 {
-	gboolean data = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			guint32 flags = info->header.v1.flags;
-			data = (flags == P2P_MSN_OBJ_DATA ||
-			        flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) ||
-			        flags == P2P_FILE_DATA);
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			data = info->header.v2.message_len > 0;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return data;
+	return (flags == P2P_MSN_OBJ_DATA ||
+	        flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) ||
+	        flags == P2P_FILE_DATA);
 }
 
 gboolean
@@ -349,7 +331,6 @@
 
 		case MSN_P2P_VERSION_TWO:
 			/* Nothing to do! */
-			valid = TRUE;
 			break;
 
 		default:
@@ -360,28 +341,6 @@
 }
 
 gboolean
-msn_p2p_info_is_first(MsnP2PInfo *info)
-{
-	gboolean first = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			first = info->header.v1.offset == 0;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			/* Nothing to do! */
-			first = info->header.v2.data_tf & TF_FIRST;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return first;
-}
-
-gboolean
 msn_p2p_info_is_final(MsnP2PInfo *info)
 {
 	gboolean final = FALSE;
@@ -392,7 +351,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			final = msn_tlv_gettlv(info->header.v2.data_tlv, P2P_DATA_TLV_REMAINING, 1) == NULL;
+			/* Nothing to do! */
 			break;
 
 		default:
@@ -402,116 +361,6 @@
 	return final;
 }
 
-void
-msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info)
-{
-	switch (old_info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			MsnP2PHeader *old = &old_info->header.v1;
-			MsnP2PHeader *new = &new_info->header.v1;
-
-			new->session_id = old->session_id;
-			new->flags = P2P_ACK;
-			new->ack_id = old->id;
-			new->ack_sub_id = old->ack_id;
-			new->ack_size = old->total_size;
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO: {
-			MsnP2Pv2Header *old = &old_info->header.v2;
-			MsnP2Pv2Header *new = &new_info->header.v2;
-
-			msn_tlvlist_add_32(&new->header_tlv, P2P_HEADER_TLV_TYPE_ACK, old->base_id + old->message_len);
-			new->opcode = P2P_OPCODE_NONE;
-
-			if (old->message_len > 0) {
-				if (!msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1)) {
-					if (old->opcode & P2P_OPCODE_SYN) {
-						msn_tlv_t *ack_tlv;
-						new->opcode |= P2P_OPCODE_RAK;
-						
-						ack_tlv = msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_PEER_INFO, 1);
-						if (ack_tlv) {
-							msn_tlvlist_add_tlv(&new->header_tlv, ack_tlv);
-							new->opcode |= P2P_OPCODE_SYN;
-						}
-					}
-				}
-			}
-			break;
-		}
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", old_info->version);
-	}
-}
-
-gboolean
-msn_p2p_info_require_ack(MsnP2PInfo *info)
-{
-	gboolean ret = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			guint32 flags = msn_p2p_info_get_flags(info);
-
-			ret = flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
-			      msn_p2p_msg_is_data(info);
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			ret = (info->header.v2.opcode & P2P_OPCODE_RAK) > 0;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ret;
-}
-
-gboolean
-msn_p2p_info_is_ack(MsnP2PInfo *info)
-{
-	gboolean ret = FALSE;
-
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE: {
-			ret = msn_p2p_info_get_flags(info) == P2P_ACK;
-			break;
-		}
-
-		case MSN_P2P_VERSION_TWO:
-			ret = msn_tlv_gettlv(info->header.v2.header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1) != NULL;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-
-	return ret;
-}
-
-void
-msn_p2p_info_init_first(MsnP2PInfo *info, MsnP2PInfo *old_info)
-{
-	switch (info->version) {
-		case MSN_P2P_VERSION_ONE:
-			info->header.v1.session_id = old_info->header.v1.session_id;
-			info->header.v1.flags = old_info->header.v1.flags;
-			break;
-
-		case MSN_P2P_VERSION_TWO:
-			info->header.v2.data_tf = TF_FIRST;
-			break;
-
-		default:
-			purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-	}
-}
-
 guint32
 msn_p2p_info_get_session_id(MsnP2PInfo *info)
 {
@@ -523,7 +372,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			session_id = info->header.v2.session_id;
+			/* Nothing to do! */
 			break;
 
 		default:
@@ -544,7 +393,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			id = info->header.v2.base_id;
+			/* Nothing to do! */
 			break;
 
 		default:
@@ -628,7 +477,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			flags = info->header.v2.data_tf;
+			/* Nothing to do! */
 			break;
 
 		default:
@@ -716,7 +565,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			info->header.v2.session_id = session_id;
+			/* Nothing to do! */
 			break;
 
 		default:
@@ -734,7 +583,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			info->header.v2.base_id = id;
+			/* Nothing to do! */
 			break;
 
 		default:
@@ -803,7 +652,7 @@
 			break;
 
 		case MSN_P2P_VERSION_TWO:
-			info->header.v2.data_tf = flags;
+			/* Nothing to do! */
 			break;
 
 		default:
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/p2p.h libpurple/protocols/msn/p2p.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/p2p.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/p2p.h	2015-05-04 13:42:04.476970478 +0200
@@ -59,42 +59,6 @@
 /*	guint8  body[1]; */
 } MsnP2Pv2Header;
 
-typedef struct {
-	guint16 protocol_version;
-	guint16 implementation_id;
-	guint16 version;
-	guint16 reserved;
-	guint32 caps;
-} P2PPeerInfo;
-
-typedef enum
-{
-	TF_FIRST    = 0x01,     /**< The first package. */
-	TF_MSNOBJ   = 0x04,     /**< Payload contains binary data for MsnObject. */
-	TF_FILE     = 0x06      /**< Payload contains binary data. */
-} TF;
-
-typedef enum
-{
-	P2P_HEADER_TLV_TYPE_PEER_INFO  = 0x01, /**< Client peer info */
-	P2P_HEADER_TLV_TYPE_ACK        = 0x02, /**< ACK */
-	P2P_HEADER_TLV_TYPE_NAK        = 0x03  /**< NAK */
-} P2PHeaderTLVType;
-
-typedef enum
-{
-	P2P_DATA_TLV_REMAINING  = 0x01, /**< Indicates the remaining data to transfer.*/
-} P2PDataTLVType;
-
-typedef enum
-{
-	P2P_PI_PVER     = 0x0200,
-	P2P_PI_IMP_ID   = 0,
-	P2P_PI_VER      = 0x0e00,
-	P2P_PI_RES      = 0,
-	P2P_PI_CAPS     = 0x0000010f
-} P2PPeerInfoVal;
-
 typedef struct
 {
 	guint32 value;
@@ -178,29 +142,14 @@
 msn_p2p_info_to_string(MsnP2PInfo *info, GString *str);
 
 gboolean
-msn_p2p_msg_is_data(const MsnP2PInfo *info);
+msn_p2p_msg_is_data(const MsnP2PHeaderFlag flags);
 
 gboolean
 msn_p2p_info_is_valid(MsnP2PInfo *info);
 
 gboolean
-msn_p2p_info_is_first(MsnP2PInfo *info);
-
-gboolean
 msn_p2p_info_is_final(MsnP2PInfo *info);
 
-void
-msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info);
-
-gboolean
-msn_p2p_info_require_ack(MsnP2PInfo *info);
-
-gboolean
-msn_p2p_info_is_ack(MsnP2PInfo *info);
-
-void
-msn_p2p_info_init_first(MsnP2PInfo *new_info, MsnP2PInfo *old_info);
-
 guint32
 msn_p2p_info_get_session_id(MsnP2PInfo *info);
 
@@ -262,3 +211,4 @@
 msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id);
 
 #endif /* MSN_P2P_H */
+
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/session.c libpurple/protocols/msn/session.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/session.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/session.c	2015-05-04 13:42:04.484970478 +0200
@@ -263,10 +263,8 @@
 	{
 		swboard = msn_switchboard_new(session);
 		swboard->im_user = g_strdup(username);
-		if (msn_switchboard_request(swboard))
-			msn_switchboard_request_add_user(swboard, username);
-		else
-			return NULL;
+		msn_switchboard_request(swboard);
+		msn_switchboard_request_add_user(swboard, username);
 	}
 
 	swboard->flag |= flag;
@@ -290,8 +288,6 @@
 msn_session_activate_login_timeout(MsnSession *session)
 {
 	if (!session->logged_in && session->connected) {
-		if (session->login_timeout)
-			purple_timeout_remove(session->login_timeout);
 		session->login_timeout =
 			purple_timeout_add_seconds(MSN_LOGIN_FQY_TIMEOUT,
 			                           msn_login_timeout_cb, session);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slp.c libpurple/protocols/msn/slp.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slp.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slp.c	2015-05-04 13:42:04.484970478 +0200
@@ -284,6 +284,7 @@
 	purple_xfer_unref(xfer);
 
 	slpmsg = msn_slpmsg_file_new(slpcall, purple_xfer_get_size(xfer));
+	msn_slpmsg_set_slplink(slpmsg, slpcall->slplink);
 
 	msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
 }
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slpcall.c libpurple/protocols/msn/slpcall.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slpcall.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slpcall.c	2015-05-04 13:42:04.484970478 +0200
@@ -237,7 +237,7 @@
 {
 	GList *smileys;
 
-	if (!purple_account_get_bool(account, "custom_smileys", TRUE))
+	if (!purple_account_get_bool(account, "custom_smileys", FALSE))
 		return NULL;
 
 	smileys = purple_smileys_get_all();
@@ -328,7 +328,7 @@
 			dc->remote_nonce[36] = '\0';
 		}
 
-		if (!strcasecmp(listening, "false")) {
+		if (!g_ascii_strcasecmp(listening, "false")) {
 			if (dc->listen_data != NULL) {
 				/*
 				 * We'll listen for incoming connections but
@@ -490,10 +490,12 @@
 		if (img != NULL) {
 			/* DATA PREP */
 			slpmsg = msn_slpmsg_dataprep_new(slpcall);
+			msn_slpmsg_set_slplink(slpmsg, slplink);
 			msn_slplink_queue_slpmsg(slplink, slpmsg);
 
 			/* DATA */
 			slpmsg = msn_slpmsg_obj_new(slpcall, img);
+			msn_slpmsg_set_slplink(slpmsg, slplink);
 			msn_slplink_queue_slpmsg(slplink, slpmsg);
 			purple_imgstore_unref(img);
 
@@ -1128,7 +1130,7 @@
 		}
 		g_free(body_str);
 	}
-	 else if (msn_p2p_msg_is_data(slpmsg->p2p_info))
+	 else if (msn_p2p_msg_is_data(flags))
 	{
 		slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
 
@@ -1145,7 +1147,7 @@
 			slpcall->wasted = TRUE;
 		}
 	}
-	else if (msn_p2p_info_is_ack(slpmsg->p2p_info))
+	else if (flags == P2P_ACK)
 	{
 		/* Acknowledgement of previous message. Don't do anything currently. */
 	}
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slpcall.h libpurple/protocols/msn/slpcall.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slpcall.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slpcall.h	2015-05-04 13:42:04.484970478 +0200
@@ -65,7 +65,7 @@
 	gboolean wait_for_socket;
 
 	void (*progress_cb)(MsnSlpCall *slpcall,
-						gsize total_length, gsize len);
+						gsize total_length, gsize len, gsize offset);
 	void (*session_init_cb)(MsnSlpCall *slpcall);
 
 	/* Can be checksum, or smile */
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slplink.c libpurple/protocols/msn/slplink.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slplink.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slplink.c	2015-05-04 13:42:04.488970478 +0200
@@ -79,7 +79,6 @@
 	slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4;
 
 	slplink->remote_user = g_strdup(username);
-	slplink->p2p_version = MSN_P2P_VERSION_ONE;
 
 	slplink->slp_msg_queue = g_queue_new();
 
@@ -265,12 +264,6 @@
 	return NULL;
 }
 
-MsnP2PVersion
-msn_slplink_get_p2p_version(MsnSlpLink *slplink)
-{
-	return slplink->p2p_version;
-}
-
 static void
 msn_slplink_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
 {
@@ -299,7 +292,7 @@
 	part = msn_slpmsgpart_new(msn_p2p_info_dup(info));
 	part->ack_data = slpmsg;
 
-	real_size = msn_p2p_info_is_ack(info) ? 0 : slpmsg->size;
+	real_size = (msn_p2p_info_get_flags(info) == P2P_ACK) ? 0 : slpmsg->size;
 
 	offset = msn_p2p_info_get_offset(info);
 	if (offset < real_size)
@@ -337,14 +330,15 @@
 	msn_slplink_send_part(slplink, part);
 
 
-	if (msn_p2p_msg_is_data(info) && slpmsg->slpcall != NULL)
+	if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(info)) &&
+		(slpmsg->slpcall != NULL))
 	{
 		slpmsg->slpcall->progress = TRUE;
 
 		if (slpmsg->slpcall->progress_cb != NULL)
 		{
 			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
-										 len);
+										 len, offset);
 		}
 	}
 
@@ -364,7 +358,7 @@
 	{
 		msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
 	}
-	else if (msn_p2p_msg_is_data(info))
+	else if (msn_p2p_msg_is_data(flags))
 	{
 		MsnSlpCall *slpcall;
 		slpcall = slpmsg->slpcall;
@@ -412,10 +406,21 @@
 	}
 }
 
+static MsnSlpMessage *
+msn_slplink_create_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
+{
+	MsnSlpMessage *slpmsg;
+
+	slpmsg = msn_slpmsg_ack_new(info);
+	msn_slpmsg_set_slplink(slpmsg, slplink);
+
+	return slpmsg;
+}
+
 static void
 msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
 {
-	MsnSlpMessage *slpmsg = msn_slpmsg_ack_new(slplink, info);
+	MsnSlpMessage *slpmsg = msn_slplink_create_ack(slplink, info);
 
 	msn_slplink_send_slpmsg(slplink, slpmsg);
 	msn_slpmsg_destroy(slpmsg);
@@ -442,19 +447,22 @@
 {
 	MsnSlpMessage *slpmsg;
 	guint32 session_id;
+	guint32 flags;
 
-	slpmsg = msn_slpmsg_new(slplink, NULL);
+	slpmsg = msn_slpmsg_new(slplink);
 	slpmsg->id = msn_p2p_info_get_id(info);
 	session_id = msn_p2p_info_get_session_id(info);
+	msn_p2p_info_set_session_id(slpmsg->p2p_info, session_id);
 	slpmsg->size = msn_p2p_info_get_total_size(info);
-	msn_p2p_info_init_first(slpmsg->p2p_info, info);
+	flags = msn_p2p_info_get_flags(info);
+	msn_p2p_info_set_flags(slpmsg->p2p_info, flags);
 
 	if (session_id)
 	{
 		slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
 		if (slpmsg->slpcall != NULL)
 		{
-			if (msn_p2p_msg_is_data(info))
+			if (msn_p2p_msg_is_data(flags))
 			{
 				PurpleXfer *xfer = slpmsg->slpcall->xfer;
 				if (xfer != NULL)
@@ -494,6 +502,7 @@
 process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
 {
 	MsnSlpCall *slpcall;
+	guint32 flags;
 
 	slpcall = msn_slp_process_msg(slplink, slpmsg);
 
@@ -504,7 +513,10 @@
 
 	purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
 
-	if (msn_p2p_info_require_ack(slpmsg->p2p_info))
+	flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
+
+	if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
+	    msn_p2p_msg_is_data(flags))
 	{
 		/* Release all the messages and send the ACK */
 
@@ -517,7 +529,7 @@
 			 */
 			purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
 
-			slpcall->slplink->dc->prev_ack = msn_slpmsg_ack_new(slplink, info);
+			slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, info);
 		} else if (!slpcall->wasted) {
 			purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
 
@@ -561,6 +573,7 @@
 {
 	MsnSlpMessage *slpmsg;
 	MsnP2PInfo *info;
+	guint64 offset;
 
 	info = part->info;
 
@@ -573,7 +586,9 @@
 		return;
 	}
 
-	if (msn_p2p_info_is_first(info))
+	offset = msn_p2p_info_get_offset(info);
+
+	if (offset == 0)
 		slpmsg = init_first_msg(slplink, info);
 	else {
 		guint32 session_id, id;
@@ -590,14 +605,15 @@
 
 	slpmsg_add_part(slpmsg, part);
 
-	if (msn_p2p_msg_is_data(slpmsg->p2p_info) && slpmsg->slpcall != NULL)
+	if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info)) &&
+		(slpmsg->slpcall != NULL))
 	{
 		slpmsg->slpcall->progress = TRUE;
 
 		if (slpmsg->slpcall->progress_cb != NULL)
 		{
 			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
-										 part->size);
+										 part->size, offset);
 		}
 	}
 
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slplink.h libpurple/protocols/msn/slplink.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slplink.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slplink.h	2015-05-04 13:42:04.488970478 +0200
@@ -45,7 +45,6 @@
 	guint refs;
 
 	char *remote_user;
-	MsnP2PVersion p2p_version;
 
 	int slp_seq_id;
 
@@ -76,8 +75,6 @@
 MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink,
 									  const char *id);
 MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id);
-MsnP2PVersion msn_slplink_get_p2p_version(MsnSlpLink *slplink);
-
 void msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
 void msn_slplink_send_slpmsg(MsnSlpLink *slplink,
 							 MsnSlpMessage *slpmsg);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg.c libpurple/protocols/msn/slpmsg.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slpmsg.c	2015-05-04 13:42:04.488970478 +0200
@@ -34,23 +34,21 @@
  **************************************************************************/
 
 MsnSlpMessage *
-msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall)
+msn_slpmsg_new(MsnSlpLink *slplink)
 {
 	MsnSlpMessage *slpmsg;
-	MsnP2PVersion p2p;
-
-	g_return_val_if_fail(slplink != NULL, NULL);
 
 	slpmsg = g_new0(MsnSlpMessage, 1);
 
 	if (purple_debug_is_verbose())
 		purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg);
 
-	msn_slpmsg_set_slplink(slpmsg, slplink);
-	slpmsg->slpcall = slpcall;
+	if (slplink)
+		msn_slpmsg_set_slplink(slpmsg, slplink);
+	else
+		slpmsg->slplink = NULL;
 
-	p2p = msn_slplink_get_p2p_version(slplink);
-	slpmsg->p2p_info = msn_p2p_info_new(p2p);
+	slpmsg->p2p_info = msn_p2p_info_new(MSN_P2P_VERSION_ONE);
 
 	return slpmsg;
 }
@@ -105,6 +103,7 @@
 
 	slplink->slp_msgs =
 		g_list_append(slplink->slp_msgs, slpmsg);
+
 }
 
 void
@@ -189,24 +188,30 @@
 		g_strlcat(body, content, body_len);
 	}
 
-	slpmsg = msn_slpmsg_new(slplink, slpcall);
+	slpmsg = msn_slpmsg_new(slplink);
 	msn_slpmsg_set_body(slpmsg, body, body_len);
 
+	slpmsg->slpcall = slpcall;
+
 	g_free(body);
 
 	return slpmsg;
 }
 
-MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *ack_info)
+MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PInfo *ack_info)
 {
 	MsnSlpMessage *slpmsg;
 	MsnP2PInfo *new_info;
 
-	slpmsg = msn_slpmsg_new(slplink, NULL);
+	slpmsg = msn_slpmsg_new(NULL);
 
 	new_info = slpmsg->p2p_info;
-	msn_p2p_info_create_ack(ack_info, new_info);
+	msn_p2p_info_set_session_id(new_info, msn_p2p_info_get_session_id(ack_info));
 	slpmsg->size = msn_p2p_info_get_total_size(ack_info);
+	msn_p2p_info_set_flags(new_info, P2P_ACK);
+	msn_p2p_info_set_ack_id(new_info, msn_p2p_info_get_id(ack_info));
+	msn_p2p_info_set_ack_sub_id(new_info, msn_p2p_info_get_ack_id(ack_info));
+	msn_p2p_info_set_ack_size(new_info, msn_p2p_info_get_total_size(ack_info));
 	slpmsg->info = "SLP ACK";
 
 	return slpmsg;
@@ -216,7 +221,8 @@
 {
 	MsnSlpMessage *slpmsg;
 
-	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
+	slpmsg = msn_slpmsg_new(NULL);
+	slpmsg->slpcall = slpcall;
 	msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_MSN_OBJ_DATA);
 	slpmsg->info = "SLP DATA";
 
@@ -229,8 +235,9 @@
 {
 	MsnSlpMessage *slpmsg;
 
-	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
+	slpmsg = msn_slpmsg_new(NULL);
 
+	slpmsg->slpcall = slpcall;
 	msn_p2p_info_set_session_id(slpmsg->p2p_info, slpcall->session_id);
 	msn_slpmsg_set_body(slpmsg, NULL, 4);
 	slpmsg->info = "SLP DATA PREP";
@@ -243,8 +250,9 @@
 {
 	MsnSlpMessage *slpmsg;
 
-	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
+	slpmsg = msn_slpmsg_new(NULL);
 
+	slpmsg->slpcall = slpcall;
 	msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_FILE_DATA);
 	slpmsg->info = "SLP FILE";
 	slpmsg->size = size;
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg.h libpurple/protocols/msn/slpmsg.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slpmsg.h	2015-05-04 13:42:04.488970478 +0200
@@ -72,7 +72,7 @@
  * If it's set to NULL, it is a temporary SlpMessage.
  * @return The created slp message.
  */
-MsnSlpMessage *msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall);
+MsnSlpMessage *msn_slpmsg_new(MsnSlpLink *slplink);
 
 /**
  * Destroys a slp message
@@ -104,7 +104,7 @@
  *
  * @return A new SlpMessage with ACK headers
  */
-MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *info);
+MsnSlpMessage *msn_slpmsg_ack_new(MsnP2PInfo *info);
 
 /**
  * Create a new SLP message for MsnObject data.
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg_part.c libpurple/protocols/msn/slpmsg_part.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg_part.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slpmsg_part.c	2015-05-04 13:42:04.488970478 +0200
@@ -42,15 +42,14 @@
 	return msn_slpmsgpart_ref(part);
 }
 
-MsnSlpMessagePart *
-msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len)
+MsnSlpMessagePart *msn_slpmsgpart_new_from_data(const char *data, size_t data_len)
 {
 	MsnSlpMessagePart *part;
 	MsnP2PInfo *info;
 	size_t len;
 	int body_len;
 
-	info = msn_p2p_info_new(p2p);
+	info = msn_p2p_info_new(MSN_P2P_VERSION_ONE);
 
 	/* Extract the binary SLP header */
 	len = msn_p2p_header_from_wire(info, data, data_len);
@@ -176,7 +175,7 @@
 
 	slpmsg = data;
 
-	real_size = msn_p2p_info_is_ack(slpmsg->p2p_info) ? 0 : slpmsg->size;
+	real_size = (msn_p2p_info_get_flags(slpmsg->p2p_info) == P2P_ACK) ? 0 : slpmsg->size;
 
 	offset = msn_p2p_info_get_offset(slpmsg->p2p_info);
 	offset += msn_p2p_info_get_length(part->info);
@@ -198,7 +197,7 @@
 	else
 	{
 		/* The whole message has been sent */
-		if (msn_p2p_msg_is_data(slpmsg->p2p_info))
+		if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info)))
 		{
 			if (slpmsg->slpcall != NULL)
 			{
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg_part.h libpurple/protocols/msn/slpmsg_part.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/slpmsg_part.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/slpmsg_part.h	2015-05-04 13:42:04.488970478 +0200
@@ -46,7 +46,7 @@
 
 MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info);
 
-MsnSlpMessagePart *msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len);
+MsnSlpMessagePart *msn_slpmsgpart_new_from_data(const char *data, size_t data_len);
 
 MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part);
 
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/switchboard.c libpurple/protocols/msn/switchboard.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/switchboard.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/switchboard.c	2015-05-04 13:42:04.492970478 +0200
@@ -421,10 +421,9 @@
 
 	purple_debug_info("msn", "unqueuing unsent message to %s\n", swboard->im_user);
 
-	if (msn_switchboard_request(swboard)) {
-		msn_switchboard_request_add_user(swboard, swboard->im_user);
-		swboard->reconn_timeout_h = 0;
-	}
+	msn_switchboard_request(swboard);
+	msn_switchboard_request_add_user(swboard, swboard->im_user);
+	swboard->reconn_timeout_h = 0;
 	return FALSE;
 }
 
@@ -1073,13 +1072,13 @@
 	swboard_error_helper(swboard, reason, swboard->im_user);
 }
 
-gboolean
+void
 msn_switchboard_request(MsnSwitchBoard *swboard)
 {
 	MsnCmdProc *cmdproc;
 	MsnTransaction *trans;
 
-	g_return_val_if_fail(swboard != NULL, FALSE);
+	g_return_if_fail(swboard != NULL);
 
 	cmdproc = swboard->session->notification->cmdproc;
 
@@ -1089,7 +1088,7 @@
 	msn_transaction_set_data(trans, swboard);
 	msn_transaction_set_error_cb(trans, xfr_error);
 
-	return msn_cmdproc_send_trans(cmdproc, trans);
+	msn_cmdproc_send_trans(cmdproc, trans);
 }
 
 void
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/switchboard.h libpurple/protocols/msn/switchboard.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/switchboard.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/switchboard.h	2015-05-04 13:42:04.492970478 +0200
@@ -250,7 +250,7 @@
 gboolean msn_switchboard_chat_leave(MsnSwitchBoard *swboard);
 gboolean msn_switchboard_chat_invite(MsnSwitchBoard *swboard, const char *who);
 
-gboolean msn_switchboard_request(MsnSwitchBoard *swboard);
+void msn_switchboard_request(MsnSwitchBoard *swboard);
 void msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user);
 
 /**
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/tlv.c libpurple/protocols/msn/tlv.c
--- extract/pidgin-2.10.9/libpurple/protocols/msn/tlv.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/tlv.c	2015-05-04 13:42:04.492970478 +0200
@@ -45,62 +45,51 @@
 	g_free(oldtlv);
 }
 
-GSList *
-msn_tlvlist_read(const char *bs, size_t bs_len)
+static GSList *
+msn_tlv_read(GSList *list, const char *bs, size_t *bs_len)
 {
-	GSList *list = NULL;
+	guint8 type, length;
+	msn_tlv_t *tlv;
 
-	while (bs_len > 0) {
-		guint8 type, length;
-		msn_tlv_t *tlv;
+	type = msn_read8(bs);
+	length = msn_read8(bs);
+	*bs_len -= 2;
 
-		if (bs_len == 3 && *bs == 0) {
-			/* Padding to multiple of 4 */
-			break;
-		} else if (bs_len == 2 && *bs == 0) {
-			/* Padding to multiple of 4 */
-			break;
-		} else if (bs_len == 1) {
-			if (*bs == 0) {
-				/* Padding to multiple of 4 */
-				break;
-			} else {
-				/* TLV is not small enough to fit here */
-				msn_tlvlist_free(list);
-				return NULL;
-			}
-		}
-
-		type = msn_pop8(bs);
-		length = msn_pop8(bs);
-		bs_len -= 2;
+	if (length > *bs_len) {
+		msn_tlvlist_free(list);
+		return NULL;
+	}
 
-		if (length > bs_len) {
+	tlv = createtlv(type, length, NULL);
+	if (length > 0) {
+		tlv->value = g_memdup(bs, length);
+		if (!tlv->value) {
+			freetlv(tlv);
 			msn_tlvlist_free(list);
 			return NULL;
 		}
+	}
 
-		tlv = createtlv(type, length, NULL);
-		if (length > 0) {
-			tlv->value = g_memdup(bs, length);
-			if (!tlv->value) {
-				freetlv(tlv);
-				msn_tlvlist_free(list);
-				return NULL;
-			}
-		}
+	*bs_len -= length;
+
+	return g_slist_prepend(list, tlv);
+}
 
-		bs_len -= length;
-		bs += length;
+GSList *
+msn_tlvlist_read(const char *bs, size_t bs_len)
+{
+	GSList *list = NULL;
 
-		list = g_slist_prepend(list, tlv);
+	while (bs_len > 0) {
+		list = msn_tlv_read(list, bs, &bs_len);
+		if (list == NULL)
+			return NULL;
 	}
 
 	return g_slist_reverse(list);
 }
 
-GSList *
-msn_tlvlist_copy(GSList *orig)
+GSList *msn_tlvlist_copy(GSList *orig)
 {
 	GSList *new = NULL;
 	msn_tlv_t *tlv;
@@ -169,7 +158,7 @@
 }
 
 int
-msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
+msn_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const char *value)
 {
 	msn_tlv_t *tlv;
 
@@ -186,7 +175,7 @@
 }
 
 int
-msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value)
+msn_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value)
 {
 	char v8[1];
 
@@ -196,7 +185,7 @@
 }
 
 int
-msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value)
+msn_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value)
 {
 	char v16[2];
 
@@ -206,7 +195,7 @@
 }
 
 int
-msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value)
+msn_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value)
 {
 	char v32[4];
 
@@ -216,25 +205,19 @@
 }
 
 int
-msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value)
+msn_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
 {
 	return msn_tlvlist_add_raw(list, type, strlen(value), value);
 }
 
 int
-msn_tlvlist_add_empty(GSList **list, const guint8 type)
+msn_tlvlist_add_empty(GSList **list, const guint16 type)
 {
 	return msn_tlvlist_add_raw(list, type, 0, NULL);
 }
 
 int
-msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv)
-{
-	return msn_tlvlist_add_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
-}
-
-int
-msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
+msn_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 length, const char *value)
 {
 	GSList *cur;
 	msn_tlv_t *tlv;
@@ -263,19 +246,19 @@
 }
 
 int
-msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str)
+msn_tlvlist_replace_str(GSList **list, const guint16 type, const char *str)
 {
 	return msn_tlvlist_replace_raw(list, type, strlen(str), str);
 }
 
 int
-msn_tlvlist_replace_empty(GSList **list, const guint8 type)
+msn_tlvlist_replace_empty(GSList **list, const guint16 type)
 {
 	return msn_tlvlist_replace_raw(list, type, 0, NULL);
 }
 
 int
-msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value)
+msn_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value)
 {
 	char v8[1];
 
@@ -285,7 +268,7 @@
 }
 
 int
-msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value)
+msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value)
 {
 	char v32[4];
 
@@ -294,14 +277,8 @@
 	return msn_tlvlist_replace_raw(list, type, 4, v32);
 }
 
-int
-msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv)
-{
-	return msn_tlvlist_replace_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
-}
-
 void
-msn_tlvlist_remove(GSList **list, const guint8 type)
+msn_tlvlist_remove(GSList **list, const guint16 type)
 {
 	GSList *cur, *next;
 	msn_tlv_t *tlv;
@@ -325,50 +302,35 @@
 	}
 }
 
-char *
-msn_tlvlist_write(GSList *list, size_t *out_len)
+int
+msn_tlvlist_write(char *bs, size_t bs_len, GSList *list)
 {
-	char *buf;
-	char *tmp;
-	size_t bytes_left;
-	size_t total_len;
-
-	tmp = buf = g_malloc(256);
-	bytes_left = total_len = 256;
-
-	for (; list; list = g_slist_next(list)) {
-		msn_tlv_t *tlv = (msn_tlv_t *)list->data;
-
-		if (G_UNLIKELY(tlv->length + 2 > bytes_left)) {
-			buf = g_realloc(buf, total_len + 256);
-			bytes_left += 256;
-			total_len += 256;
-			tmp = buf + (total_len - bytes_left);
-		}
-
-		msn_push8(tmp, tlv->type);
-		msn_push8(tmp, tlv->length);
-		memcpy(tmp, tlv->value, tlv->length);
-		tmp += tlv->length;
+#if 0
+	int goodbuflen;
+	GSList *cur;
+	msn_tlv_t *tlv;
 
-		bytes_left -= (tlv->length + 2);
-	}
+	/* do an initial run to test total length */
+	goodbuflen = msn_tlvlist_size(*list);
 
-	/* Align length to multiple of 4 */
-	total_len = total_len - bytes_left;
-	bytes_left = 4 - total_len % 4;
-	if (bytes_left != 4)
-		memset(tmp, 0, bytes_left);
-	else
-		bytes_left = 0;
+	if (goodbuflen > byte_stream_bytes_left(bs))
+		return 0; /* not enough buffer */
 
-	*out_len = total_len + bytes_left;
+	/* do the real write-out */
+	for (cur = *list; cur; cur = cur->next) {
+		tlv = cur->data;
+		byte_stream_put16(bs, tlv->type);
+		byte_stream_put16(bs, tlv->length);
+		if (tlv->length > 0)
+			byte_stream_putraw(bs, tlv->value, tlv->length);
+	}
 
-	return buf;
+#endif
+	return 0; /* TODO: This is a nonsensical return */
 }
 
 msn_tlv_t *
-msn_tlv_gettlv(GSList *list, const guint8 type, const int nth)
+msn_tlv_gettlv(GSList *list, const guint16 type, const int nth)
 {
 	msn_tlv_t *tlv;
 	int i;
@@ -385,7 +347,7 @@
 }
 
 int
-msn_tlv_getlength(GSList *list, const guint8 type, const int nth)
+msn_tlv_getlength(GSList *list, const guint16 type, const int nth)
 {
 	msn_tlv_t *tlv;
 
@@ -409,7 +371,7 @@
 }
 
 char *
-msn_tlv_getstr(GSList *list, const guint8 type, const int nth)
+msn_tlv_getstr(GSList *list, const guint16 type, const int nth)
 {
 	msn_tlv_t *tlv;
 
@@ -421,7 +383,7 @@
 }
 
 guint8
-msn_tlv_get8(GSList *list, const guint8 type, const int nth)
+msn_tlv_get8(GSList *list, const guint16 type, const int nth)
 {
 	msn_tlv_t *tlv;
 
@@ -433,7 +395,7 @@
 }
 
 guint16
-msn_tlv_get16(GSList *list, const guint8 type, const int nth)
+msn_tlv_get16(GSList *list, const guint16 type, const int nth)
 {
 	msn_tlv_t *tlv;
 
@@ -445,7 +407,7 @@
 }
 
 guint32
-msn_tlv_get32(GSList *list, const guint8 type, const int nth)
+msn_tlv_get32(GSList *list, const guint16 type, const int nth)
 {
 	msn_tlv_t *tlv;
 
diff -ru extract/pidgin-2.10.9/libpurple/protocols/msn/tlv.h libpurple/protocols/msn/tlv.h
--- extract/pidgin-2.10.9/libpurple/protocols/msn/tlv.h	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/protocols/msn/tlv.h	2015-05-04 13:42:04.496970477 +0200
@@ -38,12 +38,12 @@
 /* TLV handling functions */
 char *msn_tlv_getvalue_as_string(msn_tlv_t *tlv);
 
-msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint8 type, const int nth);
-int msn_tlv_getlength(GSList *list, const guint8 type, const int nth);
-char *msn_tlv_getstr(GSList *list, const guint8 type, const int nth);
-guint8 msn_tlv_get8(GSList *list, const guint8 type, const int nth);
-guint16 msn_tlv_get16(GSList *list, const guint8 type, const int nth);
-guint32 msn_tlv_get32(GSList *list, const guint8 type, const int nth);
+msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint16 type, const int nth);
+int msn_tlv_getlength(GSList *list, const guint16 type, const int nth);
+char *msn_tlv_getstr(GSList *list, const guint16 type, const int nth);
+guint8 msn_tlv_get8(GSList *list, const guint16 type, const int nth);
+guint16 msn_tlv_get16(GSList *list, const guint16 type, const int nth);
+guint32 msn_tlv_get32(GSList *list, const guint16 type, const int nth);
 
 /* TLV list handling functions */
 GSList *msn_tlvlist_read(const char *bs, size_t bs_len);
@@ -52,26 +52,24 @@
 int msn_tlvlist_count(GSList *list);
 size_t msn_tlvlist_size(GSList *list);
 gboolean msn_tlvlist_equal(GSList *one, GSList *two);
-char *msn_tlvlist_write(GSList *list, size_t *out_len);
+int msn_tlvlist_write(char *bs, size_t bs_len, GSList *list);
 void msn_tlvlist_free(GSList *list);
 
-int msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value);
-int msn_tlvlist_add_empty(GSList **list, const guint8 type);
-int msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value);
-int msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value);
-int msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value);
-int msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value);
-int msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv);
-
-int msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 lenth, const char *value);
-int msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str);
-int msn_tlvlist_replace_empty(GSList **list, const guint8 type);
-int msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value);
-int msn_tlvlist_replace_16(GSList **list, const guint8 type, const guint16 value);
-int msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value);
-int msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv);
+int msn_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const char *value);
+int msn_tlvlist_add_empty(GSList **list, const guint16 type);
+int msn_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value);
+int msn_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value);
+int msn_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value);
+int msn_tlvlist_add_str(GSList **list, const guint16 type, const char *value);
+
+int msn_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 lenth, const char *value);
+int msn_tlvlist_replace_str(GSList **list, const guint16 type, const char *str);
+int msn_tlvlist_replace_empty(GSList **list, const guint16 type);
+int msn_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value);
+int msn_tlvlist_replace_16(GSList **list, const guint16 type, const guint16 value);
+int msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value);
 
-void msn_tlvlist_remove(GSList **list, const guint8 type);
+void msn_tlvlist_remove(GSList **list, const guint16 type);
 
 #endif /* MSN_TLV_H */
 
Only in extract/pidgin-2.10.9/libpurple/protocols: mxit
Only in libpurple/protocols/myspace: Makefile.in
Only in libpurple/protocols/myspace: moz.build
Only in libpurple/protocols: netsoul
Only in libpurple/protocols/novell: Makefile.in
Only in libpurple/protocols/novell: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/protocols/novell/nmconn.c libpurple/protocols/novell/nmconn.c
--- extract/pidgin-2.10.9/libpurple/protocols/novell/nmconn.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/novell/nmconn.c	2015-05-04 13:42:04.544970475 +0200
@@ -19,7 +19,9 @@
  */
 
 #include <glib.h>
+#ifndef _MSC_VER
 #include <unistd.h>
+#endif
 #include <errno.h>
 #include <string.h>
 #include <ctype.h>
Only in libpurple/protocols/null: Makefile.in
Only in libpurple/protocols/null: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/protocols/null/nullprpl.c libpurple/protocols/null/nullprpl.c
--- extract/pidgin-2.10.9/libpurple/protocols/null/nullprpl.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/null/nullprpl.c	2015-05-04 13:42:04.552970475 +0200
@@ -67,6 +67,9 @@
 #include "util.h"
 #include "version.h"
 
+/* Disable gettext for the null-prpl, it will never be translated... */
+#undef _
+#define _(String) (String)
 
 #define NULLPRPL_ID "prpl-null"
 static PurplePlugin *_null_protocol = NULL;
@@ -172,7 +175,8 @@
         !strcmp(status_id, NULL_STATUS_AWAY) ||
         !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);
+                        from_username, to_username, status_id,
+                        message ? message : "");
       purple_prpl_got_user_status(from->account, to_username, status_id,
                                   (message) ? "message" : NULL, message, NULL);
     } else {
@@ -364,6 +368,9 @@
 
   purple_debug_info("nullprpl", "logging in %s\n", acct->username);
 
+  if (!strcmp(acct->username, "crash@test"))
+    *((int *) NULL) = 42;
+
   purple_connection_update_progress(gc, _("Connecting"),
                                     0,   /* which connection step this is */
                                     2);  /* total number of steps */
@@ -522,8 +529,12 @@
 
 static void nullprpl_set_status(PurpleAccount *acct, PurpleStatus *status) {
   const char *msg = purple_status_get_attr_string(status, "message");
-  purple_debug_info("nullprpl", "setting %s's status to %s: %s\n",
-                    acct->username, purple_status_get_name(status), msg);
+  if (msg)
+    purple_debug_info("nullprpl", "setting %s's status to %s: %s\n",
+		      acct->username, purple_status_get_name(status), msg);
+  else
+    purple_debug_info("nullprpl", "setting %s's status to %s\n",
+		      acct->username, purple_status_get_name(status));
 
   foreach_nullprpl_gc(report_status_change, get_nullprpl_gc(acct->username),
                       NULL);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/oscar/authorization.c libpurple/protocols/oscar/authorization.c
--- extract/pidgin-2.10.9/libpurple/protocols/oscar/authorization.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/oscar/authorization.c	2015-05-04 13:42:04.552970475 +0200
@@ -93,12 +93,16 @@
 oscar_auth_dontgrant_msgprompt(gpointer cbdata)
 {
 	struct name_data *data = cbdata;
+#if 0
 	purple_request_input(data->gc, NULL, _("Authorization Denied Message:"),
 					   NULL, _("No reason given."), TRUE, FALSE, NULL,
 					   _("_OK"), G_CALLBACK(oscar_auth_dontgrant),
 					   _("_Cancel"), G_CALLBACK(oscar_free_name_data),
 					   purple_connection_get_account(data->gc), data->name, NULL,
 					   data);
+#else
+	oscar_auth_dontgrant(data, NULL);
+#endif
 }
 
 void
diff -ru extract/pidgin-2.10.9/libpurple/protocols/oscar/family_locate.c libpurple/protocols/oscar/family_locate.c
--- extract/pidgin-2.10.9/libpurple/protocols/oscar/family_locate.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/oscar/family_locate.c	2015-05-04 13:42:04.564970475 +0200
@@ -567,7 +567,7 @@
 aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn) {
 	aim_userinfo_t *cur = NULL;
 
-	if (bn == NULL)
+	if (bn == NULL || od == NULL)
 		return NULL;
 
 	cur = od->locate.userinfo;
diff -ru extract/pidgin-2.10.9/libpurple/protocols/oscar/libaim.c libpurple/protocols/oscar/libaim.c
--- extract/pidgin-2.10.9/libpurple/protocols/oscar/libaim.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/oscar/libaim.c	2015-05-04 13:42:04.568970474 +0200
@@ -142,10 +142,13 @@
 	NULL
 };
 
+gboolean purple_init_icq_plugin(void);
+
 static void
 init_plugin(PurplePlugin *plugin)
 {
 	oscar_init(plugin, FALSE);
+	purple_init_icq_plugin();
 }
 
-PURPLE_INIT_PLUGIN(aim, init_plugin, info);
+PURPLE_INIT_PLUGIN(oscar, init_plugin, info)
diff -ru extract/pidgin-2.10.9/libpurple/protocols/oscar/libicq.c libpurple/protocols/oscar/libicq.c
--- extract/pidgin-2.10.9/libpurple/protocols/oscar/libicq.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/oscar/libicq.c	2015-05-04 13:42:04.568970474 +0200
@@ -24,7 +24,9 @@
  * which contains all the shared implementation code with libaim
  */
 
-
+#ifndef PURPLE_STATIC_PRPL
+#define PURPLE_STATIC_PRPL
+#endif
 #include "oscarcommon.h"
 
 static GHashTable *
Only in libpurple/protocols/oscar: Makefile.in
Only in libpurple/protocols/oscar: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.c
--- extract/pidgin-2.10.9/libpurple/protocols/oscar/oscar.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/oscar/oscar.c	2015-05-04 13:42:04.576970474 +0200
@@ -350,7 +350,7 @@
 		flap_connection_send_version(od, conn);
 	else
 	{
-		if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN))
+		if (purple_account_get_bool(account, "use_clientlogin", od->icq ? ICQ_DEFAULT_USE_CLIENTLOGIN : AIM_DEFAULT_USE_CLIENTLOGIN))
 		{
 			ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM;
 			ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ;
@@ -577,7 +577,7 @@
 
 	gc = data;
 	od = purple_connection_get_protocol_data(gc);
-	report_idle = strcmp((const char *)value, "none") != 0;
+	report_idle = GPOINTER_TO_INT(value);
 	presence = aim_ssi_getpresence(od->ssi.local);
 
 	if (report_idle)
@@ -765,7 +765,7 @@
 	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, "/messenger/status/reportIdle", idle_reporting_pref_cb, gc);
 	purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc);
 
 	/*
@@ -778,7 +778,7 @@
 	 * This authentication method is used for both ICQ and AIM when
 	 * clientLogin is not enabled.
 	 */
-	if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN)) {
+	if (purple_account_get_bool(account, "use_clientlogin", od->icq ? ICQ_DEFAULT_USE_CLIENTLOGIN : AIM_DEFAULT_USE_CLIENTLOGIN)) {
 		send_client_login(od, purple_account_get_username(account));
 	} else {
 		FlapConnection *newconn;
@@ -3982,8 +3982,7 @@
 		const char *idle_reporting_pref;
 		gboolean report_idle;
 
-		idle_reporting_pref = purple_prefs_get_string("/purple/away/idle_reporting");
-		report_idle = strcmp(idle_reporting_pref, "none") != 0;
+		report_idle = purple_prefs_get_bool("/messenger/status/reportIdle");
 
 		if (report_idle)
 			aim_ssi_setpresence(od, tmp | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
@@ -4025,7 +4024,8 @@
 					b = purple_find_buddy_in_group(account, curitem->name, g);
 					if (b) {
 						/* Get server stored alias */
-						purple_blist_alias_buddy(b, alias_utf8);
+						if (!purple_strequal(curitem->name, alias_utf8))
+							purple_blist_alias_buddy(b, alias_utf8);
 					} else {
 						b = purple_buddy_new(account, curitem->name, alias_utf8);
 
@@ -5767,7 +5767,7 @@
 	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
 
 	option = purple_account_option_bool_new(_("Use clientLogin"), "use_clientlogin",
-			OSCAR_DEFAULT_USE_CLIENTLOGIN);
+			is_icq ? ICQ_DEFAULT_USE_CLIENTLOGIN : AIM_DEFAULT_USE_CLIENTLOGIN);
 	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
 
 	option = purple_account_option_bool_new(
diff -ru extract/pidgin-2.10.9/libpurple/protocols/oscar/oscarcommon.h libpurple/protocols/oscar/oscarcommon.h
--- extract/pidgin-2.10.9/libpurple/protocols/oscar/oscarcommon.h	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/oscar/oscarcommon.h	2015-05-04 13:42:04.580970474 +0200
@@ -54,7 +54,8 @@
 #define OSCAR_DEFAULT_WEB_AWARE FALSE
 #define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE
 #define OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS TRUE
-#define OSCAR_DEFAULT_USE_CLIENTLOGIN TRUE
+#define AIM_DEFAULT_USE_CLIENTLOGIN FALSE
+#define ICQ_DEFAULT_USE_CLIENTLOGIN TRUE
 #define OSCAR_DEFAULT_ENCRYPTION OSCAR_OPPORTUNISTIC_ENCRYPTION
 
 #ifdef _WIN32
Only in libpurple/protocols: prpl.mk
Only in libpurple/protocols: prpl.py
Only in libpurple/protocols: prpl-rules.mk
Only in libpurple/protocols/sametime: Makefile.in
Only in libpurple/protocols/sametime: meanwhile
Only in libpurple/protocols/sametime: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/protocols/sametime/sametime.c libpurple/protocols/sametime/sametime.c
--- extract/pidgin-2.10.9/libpurple/protocols/sametime/sametime.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/sametime/sametime.c	2015-05-04 13:42:04.608970473 +0200
@@ -927,11 +927,6 @@
     return NULL;
   }
 
-  if (!name) {
-    DEBUG_WARN("Can't ensure a null group\n");
-    return NULL;
-  }
-
   DEBUG_INFO("attempting to ensure group %s, called %s\n",
 	     NSTR(name), NSTR(alias));
 
Only in extract/pidgin-2.10.9/libpurple/protocols: silc
Only in extract/pidgin-2.10.9/libpurple/protocols: silc10
Only in libpurple/protocols/simple: Makefile.in
Only in libpurple/protocols/simple: moz.build
Only in libpurple/protocols: sipe
Only in libpurple/protocols: xpcomModule.cpp.in
diff -ru extract/pidgin-2.10.9/libpurple/protocols/yahoo/libyahoo.c libpurple/protocols/yahoo/libyahoo.c
--- extract/pidgin-2.10.9/libpurple/protocols/yahoo/libyahoo.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/yahoo/libyahoo.c	2015-05-04 13:42:04.504970477 +0200
@@ -306,6 +306,8 @@
 	NULL
 };
 
+gboolean purple_init_yahoojp_plugin(void);
+
 static void
 init_plugin(PurplePlugin *plugin)
 {
@@ -343,6 +345,7 @@
 
 	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
 		PURPLE_CALLBACK(yahoo_uri_handler), NULL);
+	purple_init_yahoojp_plugin();
 }
 
 PURPLE_INIT_PLUGIN(yahoo, init_plugin, info);
diff -ru extract/pidgin-2.10.9/libpurple/protocols/yahoo/libyahoojp.c libpurple/protocols/yahoo/libyahoojp.c
--- extract/pidgin-2.10.9/libpurple/protocols/yahoo/libyahoojp.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/yahoo/libyahoojp.c	2015-05-04 13:42:04.504970477 +0200
@@ -21,6 +21,9 @@
  *
  */
 
+#ifndef PURPLE_STATIC_PRPL
+#define PURPLE_STATIC_PRPL
+#endif
 #include "internal.h"
 
 #include <account.h>
diff -ru extract/pidgin-2.10.9/libpurple/protocols/yahoo/libymsg.c libpurple/protocols/yahoo/libymsg.c
--- extract/pidgin-2.10.9/libpurple/protocols/yahoo/libymsg.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/yahoo/libymsg.c	2015-05-04 13:42:04.508970477 +0200
@@ -1363,12 +1363,15 @@
 static void
 yahoo_buddy_add_deny_reason_cb(gpointer data) {
 	struct yahoo_add_request *add_req = data;
+	yahoo_buddy_add_deny_cb(add_req, NULL);
+	/*
 	purple_request_input(add_req->gc, NULL, _("Authorization denied message:"),
 			NULL, _("No reason given."), TRUE, FALSE, NULL,
 			_("OK"), G_CALLBACK(yahoo_buddy_add_deny_cb),
 			_("Cancel"), G_CALLBACK(yahoo_buddy_add_deny_noreason_cb),
 			purple_connection_get_account(add_req->gc), add_req->who, NULL,
 			add_req);
+	*/
 }
 
 static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
Only in libpurple/protocols/yahoo: Makefile.in
Only in libpurple/protocols/yahoo: moz.build
diff -ru extract/pidgin-2.10.9/libpurple/protocols/yahoo/util.c libpurple/protocols/yahoo/util.c
--- extract/pidgin-2.10.9/libpurple/protocols/yahoo/util.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/protocols/yahoo/util.c	2015-05-04 13:42:04.508970477 +0200
@@ -498,11 +498,13 @@
 			 */
 			int size, htmlsize;
 			gchar tmp[11];
+			gchar *tmp2 = g_strdup_printf("font-size: %spt", fontsize);
 			size = strtol(fontsize, NULL, 10);
 			htmlsize = point_to_html(size);
 			sprintf(tmp, "%u", htmlsize);
 			xmlnode_set_attrib(*cur, "size", tmp);
-			xmlnode_set_attrib(*cur, "absz", fontsize);
+			xmlnode_set_attrib(*cur, "style", tmp2);
+			g_free(tmp2);
 #endif /* !USE_CSS_FORMATTING */
 			g_free(fontsize);
 		}
Only in extract/pidgin-2.10.9/libpurple/protocols: zephyr
diff -ru extract/pidgin-2.10.9/libpurple/proxy.c libpurple/proxy.c
--- extract/pidgin-2.10.9/libpurple/proxy.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/proxy.c	2015-05-04 13:42:04.544970475 +0200
@@ -285,6 +285,7 @@
 	return param;
 }
 
+#if 0
 static PurpleProxyInfo *
 purple_gnome_proxy_get_info(void)
 {
@@ -415,6 +416,7 @@
 
 	return &info;
 }
+#endif
 
 #ifdef _WIN32
 
@@ -2265,9 +2267,11 @@
 			gpi = NULL;
 	}
 	if (gpi == NULL) {
+#if 0
 		if (purple_running_gnome())
 			gpi = purple_gnome_proxy_get_info();
 		else
+#endif
 			gpi = purple_global_proxy_get_info();
 	}
 
@@ -2589,6 +2593,7 @@
 	}
 }
 
+#if 0
 static void
 proxy_pref_cb(const char *name, PurplePrefType type,
 			  gconstpointer value, gpointer data)
@@ -2624,6 +2629,7 @@
 	else if (purple_strequal(name, "/purple/proxy/password"))
 		purple_proxy_info_set_password(info, value);
 }
+#endif
 
 void *
 purple_proxy_get_handle()
@@ -2643,13 +2649,16 @@
 
 	/* Proxy */
 	purple_prefs_add_none("/purple/proxy");
+#if 0
 	purple_prefs_add_string("/purple/proxy/type", "none");
 	purple_prefs_add_string("/purple/proxy/host", "");
 	purple_prefs_add_int("/purple/proxy/port", 0);
 	purple_prefs_add_string("/purple/proxy/username", "");
 	purple_prefs_add_string("/purple/proxy/password", "");
+#endif
 	purple_prefs_add_bool("/purple/proxy/socks4_remotedns", FALSE);
 
+#if 0
 	/* Setup callbacks for the preferences. */
 	handle = purple_proxy_get_handle();
 	purple_prefs_connect_callback(handle, "/purple/proxy/type", proxy_pref_cb,
@@ -2669,6 +2678,7 @@
 	purple_prefs_trigger_callback("/purple/proxy/port");
 	purple_prefs_trigger_callback("/purple/proxy/username");
 	purple_prefs_trigger_callback("/purple/proxy/password");
+#endif
 }
 
 void
diff -ru extract/pidgin-2.10.9/libpurple/proxy.h libpurple/proxy.h
--- extract/pidgin-2.10.9/libpurple/proxy.h	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/proxy.h	2015-05-04 13:42:04.544970475 +0200
@@ -195,6 +195,13 @@
  */
 void purple_global_proxy_set_info(PurpleProxyInfo *info);
 
+/**
+ * Set purple's global proxy information.
+ *
+ * @param info     The proxy information.
+ */
+void purple_global_proxy_set_info(PurpleProxyInfo *info);
+
 /*@}*/
 
 /**************************************************************************/
diff -ru extract/pidgin-2.10.9/libpurple/prpl.c libpurple/prpl.c
--- extract/pidgin-2.10.9/libpurple/prpl.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/prpl.c	2015-05-04 13:42:04.548970475 +0200
@@ -382,6 +382,9 @@
 	g_return_if_fail(new_status != NULL);
 	g_return_if_fail(!purple_status_is_exclusive(new_status) || old_status != NULL);
 
+	purple_signal_emit(purple_accounts_get_handle(), "account-status-changing",
+					account, old_status, new_status);
+
 	do_prpl_change_account_status(account, old_status, new_status);
 
 	purple_signal_emit(purple_accounts_get_handle(), "account-status-changed",
diff -ru extract/pidgin-2.10.9/libpurple/prpl.h libpurple/prpl.h
--- extract/pidgin-2.10.9/libpurple/prpl.h	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/prpl.h	2015-05-04 13:42:04.548970475 +0200
@@ -72,7 +72,6 @@
 #include "conversation.h"
 #include "ft.h"
 #include "imgstore.h"
-#include "media.h"
 #include "notify.h"
 #include "proxy.h"
 #include "plugin.h"
@@ -80,7 +79,6 @@
 #include "status.h"
 #include "whiteboard.h"
 
-
 /** @copydoc PurpleBuddyIconSpec */
 struct _PurpleBuddyIconSpec {
 	/** This is a comma-delimited list of image formats or @c NULL if icons
Only in extract/pidgin-2.10.9/libpurple: purple.h
Only in extract/pidgin-2.10.9/libpurple: purple.h.in
Only in extract/pidgin-2.10.9/libpurple: purple.pc.in
Only in libpurple: purple-prefs.js
diff -ru extract/pidgin-2.10.9/libpurple/request.c libpurple/request.c
--- extract/pidgin-2.10.9/libpurple/request.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/request.c	2015-05-04 13:42:04.548970475 +0200
@@ -1196,6 +1196,11 @@
 
 /* -- */
 
+#define PURPLE_REQUEST_NO_OPS(type, title, description)		    \
+	purple_debug_error("request", "Requesting "type": %s (%s)", \
+			   title ? title : "(null)",		    \
+			   description ? description : "(null)")
+
 void *
 purple_request_input(void *handle, const char *title, const char *primary,
 				   const char *secondary, const char *default_value,
@@ -1230,6 +1235,8 @@
 
 		return info->ui_handle;
 	}
+	else
+		PURPLE_REQUEST_NO_OPS("input", title, primary);
 
 	return NULL;
 }
@@ -1292,6 +1299,8 @@
 
 		return info->ui_handle;
 	}
+	else
+		PURPLE_REQUEST_NO_OPS("choice", title, primary);
 
 	return NULL;
 }
@@ -1366,6 +1375,8 @@
 
 		return info->ui_handle;
 	}
+	else
+		PURPLE_REQUEST_NO_OPS("action", title, primary);
 
 	return NULL;
 }
@@ -1470,6 +1481,8 @@
 		handles = g_list_append(handles, info);
 		return info->ui_handle;
 	}
+	else
+		PURPLE_REQUEST_NO_OPS("file", title, filename);
 
 	return NULL;
 }
@@ -1497,6 +1510,8 @@
 		handles = g_list_append(handles, info);
 		return info->ui_handle;
 	}
+	else
+		PURPLE_REQUEST_NO_OPS("folder", title, dirname);
 
 	return NULL;
 }
Only in extract/pidgin-2.10.9/libpurple: savedstatuses.c
Only in extract/pidgin-2.10.9/libpurple: savedstatuses.h
diff -ru extract/pidgin-2.10.9/libpurple/server.c libpurple/server.c
--- extract/pidgin-2.10.9/libpurple/server.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/server.c	2015-05-04 13:42:04.552970475 +0200
@@ -126,7 +126,6 @@
 	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	int val = -EINVAL;
-	const gchar *auto_reply_pref = NULL;
 
 	g_return_val_if_fail(gc != NULL, val);
 
@@ -148,10 +147,9 @@
 	 * XXX - If "only auto-reply when away & idle" is set, then shouldn't
 	 * this only reset lar->sent if we're away AND idle?
 	 */
-	auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply");
 	if((gc->flags & PURPLE_CONNECTION_AUTO_RESP) &&
 			!purple_presence_is_available(presence) &&
-			!purple_strequal(auto_reply_pref, "never")) {
+			!purple_strequal(purple_prefs_get_string("/purple/away/auto_reply"), "never")) {
 
 		struct last_auto_response *lar;
 		lar = get_last_auto_response(gc, name);
@@ -645,8 +643,6 @@
 		const char *away_msg = NULL;
 		gboolean mobile = FALSE;
 
-		auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply");
-
 		presence = purple_account_get_presence(account);
 		status = purple_presence_get_active_status(presence);
 		status_type = purple_status_get_type(status);
@@ -655,7 +651,7 @@
 		if ((primitive == PURPLE_STATUS_AVAILABLE) ||
 			(primitive == PURPLE_STATUS_INVISIBLE) ||
 			mobile ||
-		    purple_strequal(auto_reply_pref, "never") ||
+		    purple_strequal((auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply")), "never") ||
 		    (!purple_presence_is_idle(presence) && purple_strequal(auto_reply_pref, "awayidle")))
 		{
 			g_free(name);
diff -ru extract/pidgin-2.10.9/libpurple/smiley.c libpurple/smiley.c
--- extract/pidgin-2.10.9/libpurple/smiley.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/smiley.c	2015-05-04 13:42:04.552970475 +0200
@@ -60,7 +60,7 @@
 static char *smileys_dir = NULL;
 
 #define SMILEYS_DEFAULT_FOLDER			"custom_smiley"
-#define SMILEYS_LOG_ID				"smileys"
+#define SMILEYS_LOG_ID				N_("smileys")
 
 #define XML_FILE_NAME				"smileys.xml"
 
Only in extract/pidgin-2.10.9/libpurple: sound.c
Only in extract/pidgin-2.10.9/libpurple: sound.h
Only in extract/pidgin-2.10.9/libpurple: sound-theme.c
Only in extract/pidgin-2.10.9/libpurple: sound-theme.h
Only in extract/pidgin-2.10.9/libpurple: sound-theme-loader.c
Only in extract/pidgin-2.10.9/libpurple: sound-theme-loader.h
diff -ru extract/pidgin-2.10.9/libpurple/sslconn.c libpurple/sslconn.c
--- extract/pidgin-2.10.9/libpurple/sslconn.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/sslconn.c	2015-05-04 13:42:04.556970475 +0200
@@ -27,11 +27,12 @@
 
 #include "internal.h"
 
-#include "certificate.h"
 #include "debug.h"
 #include "request.h"
 #include "sslconn.h"
 
+extern void purple_nss_init(void);
+
 static gboolean _ssl_initialized = FALSE;
 static PurpleSslOps *_ssl_ops = NULL;
 
@@ -43,11 +44,14 @@
 
 	if (_ssl_initialized)
 		return FALSE;
+#if 0
 
 	plugin = purple_plugins_find_with_id("core-ssl");
 
 	if (plugin != NULL && !purple_plugin_is_loaded(plugin))
 		purple_plugin_load(plugin);
+#endif
+	purple_nss_init();
 
 	ops = purple_ssl_get_ops();
 	if ((ops == NULL) || (ops->init == NULL) || (ops->uninit == NULL) ||
@@ -63,12 +67,8 @@
 gboolean
 purple_ssl_is_supported(void)
 {
-#ifdef HAVE_SSL
 	ssl_init();
 	return (purple_ssl_get_ops() != NULL);
-#else
-	return FALSE;
-#endif
 }
 
 static void
@@ -131,8 +131,10 @@
 	gsc->connect_cb      = func;
 	gsc->error_cb        = error_func;
 
+#if 0
 	/* TODO: Move this elsewhere */
 	gsc->verifier = purple_certificate_find_verifier("x509","tls_cached");
+#endif
 
 	gsc->connect_data = purple_proxy_connect(NULL, account, host, port, purple_ssl_connect_cb, gsc);
 
@@ -222,8 +224,10 @@
     if(host)
         gsc->host            = g_strdup(host);
 
+#if 0
 	/* TODO: Move this elsewhere */
 	gsc->verifier = purple_certificate_find_verifier("x509","tls_cached");
+#endif
 
 
 	ops = purple_ssl_get_ops();
diff -ru extract/pidgin-2.10.9/libpurple/sslconn.h libpurple/sslconn.h
--- extract/pidgin-2.10.9/libpurple/sslconn.h	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/sslconn.h	2015-05-04 13:42:04.556970475 +0200
@@ -34,13 +34,13 @@
 	PURPLE_SSL_CERTIFICATE_INVALID = 3
 } PurpleSslErrorType;
 
-#include "certificate.h"
 #include "proxy.h"
 
 #define PURPLE_SSL_DEFAULT_PORT 443
 
 /** @copydoc _PurpleSslConnection */
 typedef struct _PurpleSslConnection PurpleSslConnection;
+typedef struct _PurpleCertificateVerifier PurpleCertificateVerifier;
 
 typedef void (*PurpleSslInputFunction)(gpointer, PurpleSslConnection *,
 									 PurpleInputCondition);
diff -ru extract/pidgin-2.10.9/libpurple/ssl-nss.c libpurple/ssl-nss.c
--- extract/pidgin-2.10.9/libpurple/ssl-nss.c	2014-02-02 22:29:18.000000000 +0100
+++ libpurple/ssl-nss.c	2015-05-04 13:42:04.556970475 +0200
@@ -21,7 +21,6 @@
  */
 #include "internal.h"
 #include "debug.h"
-#include "certificate.h"
 #include "plugin.h"
 #include "sslconn.h"
 #include "util.h"
@@ -64,9 +63,9 @@
 
 #define PURPLE_SSL_NSS_DATA(gsc) ((PurpleSslNssData *)gsc->private_data)
 
-static const PRIOMethods *_nss_methods = NULL;
-static PRDescIdentity _identity;
-static PurpleCertificateScheme x509_nss;
+/* static const PRIOMethods *_nss_methods = NULL; */
+/* static PRDescIdentity _identity; */
+/* static PurpleCertificateScheme x509_nss; */
 
 /* Thank you, Evolution */
 static void
@@ -133,6 +132,7 @@
 static void
 ssl_nss_init_nss(void)
 {
+#if 0
 	PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
 	NSS_NoDB_Init(".");
 	NSS_SetDomesticPolicy();
@@ -152,6 +152,7 @@
 
 	_identity = PR_GetUniqueIdentity("Purple");
 	_nss_methods = PR_GetDefaultIOMethods();
+#endif
 }
 
 static SECStatus
@@ -183,12 +184,15 @@
 static void
 ssl_nss_uninit(void)
 {
+#if 0
 	NSS_Shutdown();
 	PR_Cleanup();
 
 	_nss_methods = NULL;
+#endif
 }
 
+#if 0
 static void
 ssl_nss_verified_cb(PurpleCertificateVerificationStatus st,
 		       gpointer userdata)
@@ -265,6 +269,7 @@
 
 	return peer_certs;
 }
+#endif
 
 static void
 ssl_nss_handshake_cb(gpointer data, int fd, PurpleInputCondition cond)
@@ -296,6 +301,9 @@
 	purple_input_remove(nss_data->handshake_handler);
 	nss_data->handshake_handler = 0;
 
+	gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
+
+#if 0
 	/* If a Verifier was given, hand control over to it */
 	if (gsc->verifier) {
 		GList *peers;
@@ -318,6 +326,7 @@
 		 */
 		gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
 	}
+#endif
 }
 
 static gboolean
@@ -379,10 +388,11 @@
 
 	SSL_OptionSet(nss_data->in, SSL_SECURITY,            PR_TRUE);
 	SSL_OptionSet(nss_data->in, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+	SSL_OptionSet(nss_data->in, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
 
 	/* If we have our internal verifier set up, use it. Otherwise,
 	 * use default. */
-	if (gsc->verifier != NULL)
+	if (gsc->verifier != NULL && !purple_prefs_get_bool("/purple/ssl/check_certificates"))
 		SSL_AuthCertificateHook(nss_data->in, ssl_auth_cert, NULL);
 
 	if(gsc->host)
@@ -434,6 +444,11 @@
 	PRInt32 ret;
 	PurpleSslNssData *nss_data = PURPLE_SSL_NSS_DATA(gsc);
 
+	if (nss_data->handshake_handler != 0) {
+		purple_debug_error("nss", "attempting to read from an ssl socket before the end of the handshake\n");
+		return -1;
+	}
+
 	ret = PR_Read(nss_data->in, data, len);
 
 	if (ret == -1)
@@ -451,6 +466,11 @@
 	if(!nss_data)
 		return 0;
 
+	if (nss_data->handshake_handler != 0) {
+		purple_debug_error("nss", "attempting to write to an ssl socket before the end of the handshake\n");
+		return -1;
+	}
+
 	ret = PR_Write(nss_data->in, data, len);
 
 	if (ret == -1)
@@ -483,6 +503,9 @@
 	return NULL;
 }
 
+#if 0
+/* No purple_certificate_* stuff for Instantbird */
+
 /************************************************************************/
 /* X.509 functionality                                                  */
 /************************************************************************/
@@ -936,6 +959,7 @@
 	NULL,
 	NULL
 };
+#endif
 
 static PurpleSslOps ssl_ops =
 {
@@ -954,6 +978,13 @@
 };
 
 
+void purple_nss_init(void)
+{
+	purple_ssl_set_ops(&ssl_ops);
+}
+
+#if 0
+/* Instantbird does not need the plugin stuff for NSS */
 static gboolean
 plugin_load(PurplePlugin *plugin)
 {
@@ -1026,3 +1057,4 @@
 }
 
 PURPLE_INIT_PLUGIN(ssl_nss, init_plugin, info)
+#endif
diff -ru extract/pidgin-2.10.9/libpurple/status.c libpurple/status.c
--- extract/pidgin-2.10.9/libpurple/status.c	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/status.c	2015-05-04 13:42:04.556970475 +0200
@@ -607,6 +607,7 @@
 notify_buddy_status_update(PurpleBuddy *buddy, PurplePresence *presence,
 		PurpleStatus *old_status, PurpleStatus *new_status)
 {
+#if 0
 	if (purple_prefs_get_bool("/purple/logging/log_system"))
 	{
 		time_t current_time = time(NULL);
@@ -652,6 +653,7 @@
 		g_free(tmp);
 		g_free(logtmp);
 	}
+#endif
 }
 
 static void
@@ -1253,6 +1255,7 @@
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleAccount *account = purple_buddy_get_account(buddy);
 
+#if 0
 	if (!old_idle && idle)
 	{
 		if (purple_prefs_get_bool("/purple/logging/log_system"))
@@ -1293,6 +1296,7 @@
 			}
 		}
 	}
+#endif
 
 	if (old_idle != idle)
 		purple_signal_emit(purple_blist_get_handle(), "buddy-idle-changed", buddy,
@@ -1339,6 +1343,7 @@
 
 		account = purple_presence_get_account(presence);
 
+#if 0
 		if (purple_prefs_get_bool("/purple/logging/log_system"))
 		{
 			PurpleLog *log = purple_account_get_log(account, FALSE);
@@ -1360,6 +1365,7 @@
 				g_free(msg);
 			}
 		}
+#endif
 
 		gc = purple_account_get_connection(account);
 
Only in extract/pidgin-2.10.9/libpurple: tests
Only in extract/pidgin-2.10.9/libpurple: theme.c
Only in extract/pidgin-2.10.9/libpurple: theme.h
Only in extract/pidgin-2.10.9/libpurple: theme-loader.c
Only in extract/pidgin-2.10.9/libpurple: theme-loader.h
Only in extract/pidgin-2.10.9/libpurple: theme-manager.c
Only in extract/pidgin-2.10.9/libpurple: theme-manager.h
diff -ru extract/pidgin-2.10.9/libpurple/upnp.h libpurple/upnp.h
--- extract/pidgin-2.10.9/libpurple/upnp.h	2014-02-02 22:29:19.000000000 +0100
+++ libpurple/upnp.h	2015-05-04 13:42:04.560970475 +0200
@@ -61,17 +61,6 @@
  */
 void purple_upnp_discover(PurpleUPnPCallback cb, gpointer cb_data);
 
-#if 0
-/**
- * Retrieve the current UPnP control info, if there is any available.
- * This will only be filled in if purple_upnp_discover() had been called,
- * and finished discovering.
- *
- * @return The control URL for the IGD we'll use to use the IGD services
- */
-const PurpleUPnPControlInfo* purple_upnp_get_control_info(void);
-#endif
-
 /**
  * Gets the IP address from a UPnP enabled IGD that sits on the local
  * network, so when getting the network IP, instead of returning the
diff -ru extract/pidgin-2.10.9/libpurple/util.c libpurple/util.c
--- extract/pidgin-2.10.9/libpurple/util.c	2014-02-02 22:29:20.000000000 +0100
+++ libpurple/util.c	2015-05-04 13:42:04.564970475 +0200
@@ -2495,6 +2495,7 @@
 /**************************************************************************
  * Path/Filename Functions
  **************************************************************************/
+#ifdef PURPLE_PLUGINS
 const char *
 purple_home_dir(void)
 {
@@ -2504,17 +2505,14 @@
 	return wpurple_data_dir();
 #endif
 }
+#endif
 
 /* Returns the argument passed to -c IFF it was present, or ~/.purple. */
 const char *
 purple_user_dir(void)
 {
-	if (custom_user_dir != NULL)
-		return custom_user_dir;
-	else if (!user_dir)
-		user_dir = g_build_filename(purple_home_dir(), ".purple", NULL);
-
-	return user_dir;
+	g_return_val_if_fail(custom_user_dir != NULL, NULL);
+	return custom_user_dir;
 }
 
 void purple_util_set_user_dir(const char *dir)
@@ -2715,6 +2713,7 @@
 	return xmlnode_from_file(purple_user_dir(), filename, description, "util");
 }
 
+#if 0
 /*
  * Like mkstemp() but returns a file pointer, uses a pre-set template,
  * uses the semantics of tempnam() for the directory to use and allocates
@@ -2763,6 +2762,7 @@
 
 	return fp;
 }
+#endif
 
 const char *
 purple_util_get_image_extension(gconstpointer data, size_t len)
@@ -2830,6 +2830,7 @@
 	return filename;
 }
 
+#if 0
 gboolean
 purple_program_is_valid(const char *program)
 {
@@ -2865,12 +2866,12 @@
 
 	return is_valid;
 }
-
+#endif
 
 gboolean
 purple_running_gnome(void)
 {
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__APPLE__)
 	gchar *tmp = g_find_program_in_path("gnome-open");
 
 	if (tmp == NULL)
@@ -2888,7 +2889,7 @@
 gboolean
 purple_running_kde(void)
 {
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__APPLE__)
 	gchar *tmp = g_find_program_in_path("kfmclient");
 	const char *session;
 
diff -ru extract/pidgin-2.10.9/libpurple/util.h libpurple/util.h
--- extract/pidgin-2.10.9/libpurple/util.h	2014-02-02 22:29:20.000000000 +0100
+++ libpurple/util.h	2015-05-04 13:42:04.564970475 +0200
@@ -644,7 +644,7 @@
  *
  * @see purple_user_dir()
  */
-const gchar *purple_home_dir(void);
+/* const gchar *purple_home_dir(void); */
 
 /**
  * Returns the purple settings directory in the user's home directory.
@@ -745,7 +745,7 @@
  *
  * @return A file pointer to the temporary file, or @c NULL on failure.
  */
-FILE *purple_mkstemp(char **path, gboolean binary);
+/* FILE *purple_mkstemp(char **path, gboolean binary); */
 
 /**
  * Returns an extension corresponding to the image data's file type.
@@ -787,7 +787,7 @@
  *
  * @return TRUE if the program is runable.
  */
-gboolean purple_program_is_valid(const char *program);
+/* gboolean purple_program_is_valid(const char *program); */
 
 /**
  * Check if running GNOME.
Only in extract/pidgin-2.10.9/libpurple: valgrind.h
Only in extract/pidgin-2.10.9/libpurple/win32: giowin32.c
Only in extract/pidgin-2.10.9/libpurple/win32: global.mak
diff -ru extract/pidgin-2.10.9/libpurple/win32/libc_interface.h libpurple/win32/libc_interface.h
--- extract/pidgin-2.10.9/libpurple/win32/libc_interface.h	2014-02-02 22:29:20.000000000 +0100
+++ libpurple/win32/libc_interface.h	2015-05-04 13:42:04.568970474 +0200
@@ -134,8 +134,6 @@
 /* stdio.h */
 #undef snprintf
 #define snprintf _snprintf
-#undef vsnprintf
-#define vsnprintf _vsnprintf
 
 #define rename( oldname, newname ) \
 wpurple_rename( oldname, newname )
Only in extract/pidgin-2.10.9/libpurple/win32: libpurplerc.rc.in
Only in extract/pidgin-2.10.9/libpurple/win32: rules.mak
Only in extract/pidgin-2.10.9/libpurple/win32: targets.mak
diff -ru extract/pidgin-2.10.9/libpurple/win32/win32dep.c libpurple/win32/win32dep.c
--- extract/pidgin-2.10.9/libpurple/win32/win32dep.c	2014-02-02 22:29:20.000000000 +0100
+++ libpurple/win32/win32dep.c	2015-05-04 13:42:04.568970474 +0200
@@ -22,7 +22,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  *
  */
+#ifndef _WIN32_IE
 #define _WIN32_IE 0x501
+#endif
+
 #include "internal.h"
 #include <winuser.h>
 
@@ -112,6 +115,7 @@
 
 /* Determine Purple Paths during Runtime */
 
+#if 0
 /* Get paths to special Windows folders. */
 gchar *wpurple_get_special_folder(int folder_type) {
 	gchar *retval = NULL;
@@ -327,6 +331,7 @@
 
 	return result;
 }
+#endif
 
 void wpurple_init(void) {
 	WORD wVersionRequested;
@@ -336,7 +341,7 @@
 		g_thread_init(NULL);
 
 	purple_debug_info("wpurple", "wpurple_init start\n");
-	purple_debug_info("wpurple", "libpurple version: " DISPLAY_VERSION "\n");
+	//	purple_debug_info("wpurple", "libpurple version: " DISPLAY_VERSION "\n");
 
 	purple_debug_info("wpurple", "Glib:%u.%u.%u\n",
 		glib_major_version, glib_minor_version, glib_micro_version);
diff -ru extract/pidgin-2.10.9/libpurple/win32/win32dep.h libpurple/win32/win32dep.h
--- extract/pidgin-2.10.9/libpurple/win32/win32dep.h	2014-02-02 22:29:20.000000000 +0100
+++ libpurple/win32/win32dep.h	2015-05-04 13:42:04.572970474 +0200
@@ -54,18 +54,17 @@
  **/
 /* Windows helper functions */
 FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure);
-gboolean wpurple_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result);
-char *wpurple_read_reg_string(HKEY rootkey, const char *subkey, const char *valname); /* needs to be g_free'd */
-gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname, const char *value);
+/* gboolean wpurple_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result); */
+/* char *wpurple_read_reg_string(HKEY rootkey, const char *subkey, const char *valname); / * needs to be g_free'd */
+/* gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname, const char *value); */
 char *wpurple_escape_dirsep(const char *filename); /* needs to be g_free'd */
-GIOChannel *wpurple_g_io_channel_win32_new_socket(int socket); /* Until we get the post-2.8 glib win32 giochannel implementation working, use the thread-based one */
 
 /* Determine Purple paths */
-gchar *wpurple_get_special_folder(int folder_type); /* needs to be g_free'd */
-const char *wpurple_install_dir(void);
-const char *wpurple_lib_dir(void);
-const char *wpurple_locale_dir(void);
-const char *wpurple_data_dir(void);
+/* gchar *wpurple_get_special_folder(int folder_type); /* needs to be g_free'd */
+/* const char *wpurple_install_dir(void); */
+/* const char *wpurple_lib_dir(void); */
+/* const char *wpurple_locale_dir(void); */
+/* const char *wpurple_data_dir(void); */
 
 /* init / cleanup */
 void wpurple_init(void);
@@ -80,9 +79,9 @@
 /*
  *  Purple specific
  */
-#define DATADIR wpurple_install_dir()
-#define LIBDIR wpurple_lib_dir()
-#define LOCALEDIR wpurple_locale_dir()
+/* #define DATADIR wpurple_install_dir() */
+/* #define LIBDIR wpurple_lib_dir() */
+/* #define LOCALEDIR wpurple_locale_dir() */
 
 #ifdef __cplusplus
 }
diff -ru extract/pidgin-2.10.9/libpurple/win32/wpurpleerror.h libpurple/win32/wpurpleerror.h
--- extract/pidgin-2.10.9/libpurple/win32/wpurpleerror.h	2014-02-02 22:29:20.000000000 +0100
+++ libpurple/win32/wpurpleerror.h	2015-05-04 13:42:04.572970474 +0200
@@ -25,6 +25,42 @@
 #ifndef _WPURPLEERROR_H
 #define _WPURPLEERROR_H
 
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+/* libpurple expects errno to contain winsocks error codes rather than
+   the real errno values (which are defined in MSVC10). */
+
+/* Include the Microsoft errno.h before undefining the error codes, so
+   that it doesn't do anything if it is included later (avoid macro
+   redefinition warnings). */
+#include <errno.h>
+
+#undef ENETDOWN
+#undef EAFNOSUPPORT
+#undef EINPROGRESS
+#undef ENOBUFS
+#undef EPROTONOSUPPORT
+#undef EPROTOTYPE
+#undef ESOCKTNOSUPPORT
+
+#undef EADDRINUSE
+#undef EALREADY
+#undef EADDRNOTAVAIL
+#undef ECONNREFUSED
+#undef EISCONN
+#undef ENETUNREACH
+#undef ENOTSOCK
+#undef ETIMEDOUT
+#undef EWOULDBLOCK
+
+#undef ENOTCONN
+#undef ENETRESET
+#undef EOPNOTSUPP
+#undef EMSGSIZE
+#undef ECONNABORTED
+#undef ECONNRESET
+#undef EHOSTUNREACH
+#endif
+
 /* Here we define unix socket errors as windows socket errors */
 
 #define ENETDOWN WSAENETDOWN
@@ -36,7 +72,6 @@
 #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
 
 #define EADDRINUSE WSAEADDRINUSE
-#define EINPROGRESS WSAEINPROGRESS
 #define EALREADY WSAEALREADY
 #define EADDRNOTAVAIL WSAEADDRNOTAVAIL
 #define ECONNREFUSED WSAECONNREFUSED
