changeset 31933:6b3bc0947068

merged from im.pidgin.pidgin
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Thu, 21 Apr 2011 20:36:02 +0900
parents 8b9e9c61d061 (current diff) b671728e6ee9 (diff)
children 380f530c3f86
files configure.ac libpurple/protocols/irc/irc.c libpurple/protocols/irc/parse.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/si.c libpurple/protocols/yahoo/yahoo_filexfer.c pidgin/gtkconv.c pidgin/gtkprefs.c
diffstat 39 files changed, 678 insertions(+), 259 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Fri Apr 01 13:47:51 2011 +0900
+++ b/COPYRIGHT	Thu Apr 21 20:36:02 2011 +0900
@@ -576,6 +576,7 @@
 Stephen Whitmore
 Simon Wilkinson
 Dan Willemsen
+Dan Williams
 Justin Williams (Jaywalker)
 Jason Willis
 Alex Willmer
--- a/ChangeLog	Fri Apr 01 13:47:51 2011 +0900
+++ b/ChangeLog	Thu Apr 21 20:36:02 2011 +0900
@@ -4,6 +4,8 @@
 	General:
 	* Implement simple silence suppression for voice calls, preventing wasted
 	  bandwidth for silent periods during a call. (Jakub Adam) (half of #13180)
+	* Added the DigiCert High Assurance CA-3 intermediate CA, needed for
+	  validation of the Facebook XMPP interface's certificate.
 
 	Pidgin:
 	* Duplicate code cleanup.  (Gabriel Schulhof) (#10599)
@@ -11,9 +13,12 @@
 	  on the fly. (Jakub Adam) (half of #13535)
 	* Don't cancel an ongoing call when rejecting the addition of a stream to
 	  the existing call. (Jakub Adam) (#13537)
+	* Pidgin plugins can now override tab completion and detect clicks on
+	  usernames in the chat userlist. (kawaii.neko) (#12599)
 
 	libpurple:
-	* media: Allow obtaining active local and remote candidates. (#11830)
+	* media: Allow obtaining active local and remote candidates. (Jakub
+	  Adam) (#11830)
 	* media: Allow getting/setting video capabilities. (Jakub Adam) (half of
 	  #13095)
 	* Simple Silence Suppression is optional per-account. (Jakub Adam) (half
@@ -21,6 +26,10 @@
 	* Fix purple-url-handler being unable to find an account.
 	* media: Allow adding/removing streams on the fly. (Jakub Adam) (half of
 	  #13535)
+	* Support new connection states in NetworkManager 0.9. (Dan Williams)
+	  (#13505)
+	* When removing a buddy, delete the pounces associated with it.
+	  (Kartik Mohta) (#1131)
 
 	Gadu-Gadu:
 	* Allow showing your status only to buddies. (Mateusz Piękos) (#13358)
@@ -30,8 +39,18 @@
 	  images. (Tomasz Wasilczyk) (#13554)
 	* Fix sending inline images to remote users, don't crash when
 	  trying to send large (> 256kB) images. (Tomasz Wasilczyk) (#13580)
-	* Support incoming typing notifications. (Jan Zachorowski) (#13362)
+	* Support typing notifications. (Jan Zachorowski, Tomasz Wasilczyk,
+	  Krzysztof Klinikowski) (#13362, #13590)
 	* Require libgadu 1.10.1 to avoid using internal libgadu.
+	* SSL connection support for GNUTLS users (not on Windows yet!).
+	  (Tomasz Wasilczyk) (#13613)
+	* Don't count received messages or statuses when determining whether
+	  to send a keepalive packet. (Jan Zachorowski) (#13699)
+	* Fix a crash when receiving images on Windows or an incorrect
+	  timestamp in the log when receiving images on Linux. (Tomasz
+	  Wasilczyk) (#10268)
+	* Support XML events, resulting in immediate update of other users'
+	  buddy icons. (Tomasz Wasilczyk) (#13739)
 
 	ICQ:
 	* Fix unsetting your mood when "None" is selected.  (Dustin Gathmann)
@@ -42,6 +61,13 @@
 	  an ICQ account's settings by using a comma-delimited list.  (Dmitry
 	  Utkin (#13496)
 
+	IRC:
+	* Add "authserv" service command.  (tomos) (#13337)
+
+	XMPP:
+	* Remember the previously entered user directory when searching.
+	  (Keith Moyer) (#12451)
+
 	Plugins:
 	* The Voice/Video Settings plugin now includes the ability to test
 	  microphone settings. (Jakub Adam) (#13182)
--- a/ChangeLog.API	Fri Apr 01 13:47:51 2011 +0900
+++ b/ChangeLog.API	Thu Apr 21 20:36:02 2011 +0900
@@ -8,26 +8,38 @@
 		* cleared-message-history signal (conversation signals)
 		* purple_account_add_buddy_with_invite
 		* purple_account_add_buddies_with_invite
+		* purple_dnsquery_a_account
 		* purple_notify_user_info_add_pair_plaintext
 		* purple_media_get_active_local_candidates
 		* purple_media_get_active_remote_candidates
 		* purple_media_manager_get_video_caps (Jakub Adam) (#13095)
 		* purple_media_manager_set_video_caps (Jakub Adam) (#13095)
+		* purple_pounce_destroy_all_by_buddy (Kartik Mohta) (#1131)
+		* purple_proxy_connect_socks5_account
+		* purple_srv_resolve_account
+		* purple_txt_resolve_account
 		* Added add_buddy_with_invite to PurplePluginProtocolInfo
 		* Added add_buddies_with_invite to PurplePluginProtocolInfo
 		* Added PurpleSrvTxtQueryUiOps which allow UIs to specify their
 		  own mechanisms to resolve SRV and/or TXT queries. It works
 		  similar to PurpleDnsQueryUiOps
+		* purple_marshal_BOOLEAN__POINTER_BOOLEAN (kawaii.neko) (#12599)
 
 		Deprecated:
 		* purple_account_add_buddy
 		* purple_account_add_buddies_with_invite
+		* purple_dnsquery_a
+		* purple_proxy_connect_socks5
+		* purple_srv_resolve
+		* purple_txt_resolve
 		* add_buddy from PurplePluginProtocolInfo struct
 		* add_buddies from PurplePluginProtocolInfo struct
 
 	Pidgin:
 		Added:
 		* pidgin_make_scrollable (Gabriel Schulhof) (#10599)
+		* chat-nick-clicked signal (kawaii.neko) (#12599)
+		* chat-nick-autocomplete signal (kawaii.neko) (#12599)
 
 version 2.7.11 (03/10/2011):
 	* libpurple:
--- a/configure.ac	Fri Apr 01 13:47:51 2011 +0900
+++ b/configure.ac	Thu Apr 21 20:36:02 2011 +0900
@@ -1058,7 +1058,7 @@
 	]])], [
 		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libgadu.h>]], [[
 #if GG_DEFAULT_PROTOCOL_VERSION < 0x2e
-#error "Your libgadu version is too old. libpurple requires 1.9.0-rc2 or higher."
+#error "Your libgadu version is too old. libpurple requires 1.10.1 or higher."
 #endif
 		]])], [
 			AC_MSG_RESULT(yes)
@@ -1069,7 +1069,7 @@
 			echo
 			echo
 			echo "Your supplied copy of libgadu is too old."
-			echo "Install version 1.9.0-rc2 or newer."
+			echo "Install version 1.10.1 or newer."
 			echo "Then rerun this ./configure"
 			echo
 			echo "Falling back to using our own copy of libgadu"
--- a/libpurple/account.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/account.c	Thu Apr 21 20:36:02 2011 +0900
@@ -294,6 +294,7 @@
 			 proxy_type == PURPLE_PROXY_HTTP       ? "http"   :
 			 proxy_type == PURPLE_PROXY_SOCKS4     ? "socks4" :
 			 proxy_type == PURPLE_PROXY_SOCKS5     ? "socks5" :
+			 proxy_type == PURPLE_PROXY_TOR        ? "tor" :
 			 proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1);
 
 	if ((value = purple_proxy_info_get_host(proxy_info)) != NULL)
@@ -746,6 +747,8 @@
 			purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS4);
 		else if (purple_strequal(data, "socks5"))
 			purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS5);
+		else if (purple_strequal(data, "tor"))
+			purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_TOR);
 		else if (purple_strequal(data, "envvar"))
 			purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_ENVVAR);
 		else
--- a/libpurple/blist.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/blist.c	Thu Apr 21 20:36:02 2011 +0900
@@ -28,6 +28,7 @@
 #include "dbus-maybe.h"
 #include "debug.h"
 #include "notify.h"
+#include "pounce.h"
 #include "prefs.h"
 #include "privacy.h"
 #include "prpl.h"
@@ -2184,6 +2185,9 @@
 	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);
 
--- a/libpurple/dnsquery.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/dnsquery.c	Thu Apr 21 20:36:02 2011 +0900
@@ -54,6 +54,7 @@
 	PurpleDnsQueryConnectFunction callback;
 	gpointer data;
 	guint timeout;
+	PurpleAccount *account;
 
 #if defined(PURPLE_DNSQUERY_USE_FORK)
 	PurpleDnsQueryResolverProcess *resolver;
@@ -153,6 +154,7 @@
 resolve_ip(PurpleDnsQueryData *query_data)
 {
 	struct sockaddr_in sin;
+	/* TODO: Use inet_pton for IPv6 support */
 	if (inet_aton(query_data->hostname, &sin.sin_addr))
 	{
 		/*
@@ -341,20 +343,17 @@
 		}
 		freeaddrinfo(tmp);
 #else
-		if (!inet_aton(hostname, &sin.sin_addr)) {
-			struct hostent *hp;
-			if (!(hp = gethostbyname(hostname))) {
-				write_to_parent(child_out, &h_errno, sizeof(int));
-				close(child_out);
-				if (show_debug)
-					printf("DNS Error: %d\n", h_errno);
-				_exit(0);
-			}
-			memset(&sin, 0, sizeof(struct sockaddr_in));
-			memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
-			sin.sin_family = hp->h_addrtype;
-		} else
-			sin.sin_family = AF_INET;
+		struct hostent *hp;
+		if (!(hp = gethostbyname(hostname))) {
+			write_to_parent(child_out, &h_errno, sizeof(int));
+			close(child_out);
+			if (show_debug)
+				printf("DNS Error: %d\n", h_errno);
+			_exit(0);
+		}
+		memset(&sin, 0, sizeof(struct sockaddr_in));
+		memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
+		sin.sin_family = hp->h_addrtype;
 
 		sin.sin_port = htons(dns_params.port);
 		rc = 0;
@@ -669,62 +668,12 @@
 	handle_next_queued_request();
 }
 
-static gboolean
-resolve_host(gpointer data)
+static void
+resolve_host(PurpleDnsQueryData *query_data)
 {
-	PurpleDnsQueryData *query_data;
-
-	query_data = data;
-	query_data->timeout = 0;
-
-	if (resolve_ip(query_data))
-	{
-		/* resolve_ip calls purple_dnsquery_resolved */
-		return FALSE;
-	}
-
-	if (purple_dnsquery_ui_resolve(query_data))
-	{
-		/* The UI is handling the resolve; we're done */
-		return FALSE;
-	}
-
 	queued_requests = g_slist_append(queued_requests, query_data);
 
 	handle_next_queued_request();
-
-	return FALSE;
-}
-
-PurpleDnsQueryData *
-purple_dnsquery_a(const char *hostname, int port,
-				PurpleDnsQueryConnectFunction callback, gpointer data)
-{
-	PurpleDnsQueryData *query_data;
-
-	g_return_val_if_fail(hostname != NULL, NULL);
-	g_return_val_if_fail(port	  != 0, NULL);
-	g_return_val_if_fail(callback != NULL, NULL);
-
-	query_data = g_new(PurpleDnsQueryData, 1);
-	query_data->hostname = g_strdup(hostname);
-	g_strstrip(query_data->hostname);
-	query_data->port = port;
-	query_data->callback = callback;
-	query_data->data = data;
-	query_data->resolver = NULL;
-
-	if (*query_data->hostname == '\0')
-	{
-		purple_dnsquery_destroy(query_data);
-		g_return_val_if_reached(NULL);
-	}
-
-	purple_debug_info("dns", "DNS query for '%s' queued\n", query_data->hostname);
-
-	query_data->timeout = purple_timeout_add(0, resolve_host, query_data);
-
-	return query_data;
 }
 
 #elif defined _WIN32 /* end PURPLE_DNSQUERY_USE_FORK  */
@@ -837,50 +786,116 @@
 	return 0;
 }
 
+static void
+resolve_host(PurpleDnsQueryData *query_data)
+{
+	GError *err = NULL;
+
+	/*
+	 * Spin off a separate thread to perform the DNS lookup so
+	 * that we don't block the UI.
+	 */
+	query_data->resolver = g_thread_create(dns_thread,
+			query_data, FALSE, &err);
+	if (query_data->resolver == NULL)
+	{
+		char message[1024];
+		g_snprintf(message, sizeof(message), _("Thread creation failure: %s"),
+				(err && err->message) ? err->message : _("Unknown reason"));
+		g_error_free(err);
+		purple_dnsquery_failed(query_data, message);
+	}
+}
+
+#else /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */
+
+/*
+ * We weren't able to do anything fancier above, so use the
+ * fail-safe name resolution code, which is blocking.
+ */
+
+static void
+resolve_host(PurpleDnsQueryData *query_data)
+{
+	struct sockaddr_in sin;
+	GSList *hosts = NULL;
+	struct hostent *hp;
+	gchar *hostname;
+#ifdef USE_IDN
+	if (!dns_str_is_ascii(query_data->hostname)) {
+		int ret = purple_network_convert_idn_to_ascii(query_data->hostname,
+				&hostname);
+		if (ret != 0) {
+			char message[1024];
+			g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
+					query_data->hostname, ret);
+			purple_dnsquery_failed(query_data, message);
+			return;
+		}
+	} else /* fallthrough is intentional to the g_strdup */
+#endif
+	hostname = g_strdup(query_data->hostname);
+
+	if(!(hp = gethostbyname(hostname))) {
+		char message[1024];
+		g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
+				query_data->hostname, h_errno);
+		purple_dnsquery_failed(query_data, message);
+		g_free(hostname);
+		return;
+	}
+	memset(&sin, 0, sizeof(struct sockaddr_in));
+	memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
+	sin.sin_family = hp->h_addrtype;
+	g_free(hostname);
+	sin.sin_port = htons(query_data->port);
+
+	hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin)));
+	hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin)));
+
+	purple_dnsquery_resolved(query_data, hosts);
+}
+
+#endif /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */
+
 static gboolean
-resolve_host(gpointer data)
+initiate_resolving(gpointer data)
 {
 	PurpleDnsQueryData *query_data;
-	GError *err = NULL;
+	PurpleProxyType proxy_type;
 
 	query_data = data;
 	query_data->timeout = 0;
 
-	if (purple_dnsquery_ui_resolve(query_data))
-	{
-		/* The UI is handling the resolve; we're done */
+	if (resolve_ip(query_data))
+		/* resolve_ip calls purple_dnsquery_resolved */
+		return FALSE;
+
+	proxy_type = purple_proxy_info_get_type(
+		purple_proxy_get_setup(query_data->account));
+	if (proxy_type == PURPLE_PROXY_TOR) {
+		purple_dnsquery_failed(query_data,
+			_("Aborting DNS lookup in Tor Proxy mode."));
 		return FALSE;
 	}
 
-	if (!resolve_ip(query_data))
-	{
-		/*
-		 * Spin off a separate thread to perform the DNS lookup so
-		 * that we don't block the UI.
-		 */
-		query_data->resolver = g_thread_create(dns_thread,
-				query_data, FALSE, &err);
-		if (query_data->resolver == NULL)
-		{
-			char message[1024];
-			g_snprintf(message, sizeof(message), _("Thread creation failure: %s"),
-					(err && err->message) ? err->message : _("Unknown reason"));
-			g_error_free(err);
-			purple_dnsquery_failed(query_data, message);
-		}
-	}
+	if (purple_dnsquery_ui_resolve(query_data))
+		/* The UI is handling the resolve; we're done */
+		return FALSE;
+
+	resolve_host(query_data);
 
 	return FALSE;
 }
 
 PurpleDnsQueryData *
-purple_dnsquery_a(const char *hostname, int port,
+purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port,
 				PurpleDnsQueryConnectFunction callback, gpointer data)
 {
 	PurpleDnsQueryData *query_data;
 
 	g_return_val_if_fail(hostname != NULL, NULL);
-	g_return_val_if_fail(port	  != 0, NULL);
+	g_return_val_if_fail(port != 0, NULL);
 	g_return_val_if_fail(callback != NULL, NULL);
 
 	purple_debug_info("dnsquery", "Performing DNS lookup for %s\n", hostname);
@@ -891,115 +906,26 @@
 	query_data->port = port;
 	query_data->callback = callback;
 	query_data->data = data;
+	query_data->account = account;
 
-	if (strlen(query_data->hostname) == 0)
+	if (*query_data->hostname == '\0')
 	{
 		purple_dnsquery_destroy(query_data);
 		g_return_val_if_reached(NULL);
 	}
 
-	/* Don't call the callback before returning */
-	query_data->timeout = purple_timeout_add(0, resolve_host, query_data);
+	query_data->timeout = purple_timeout_add(0, initiate_resolving, query_data);
 
 	return query_data;
 }
 
-#else /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */
-
-/*
- * We weren't able to do anything fancier above, so use the
- * fail-safe name resolution code, which is blocking.
- */
-
-static gboolean
-resolve_host(gpointer data)
-{
-	PurpleDnsQueryData *query_data;
-	struct sockaddr_in sin;
-	GSList *hosts = NULL;
-
-	query_data = data;
-	query_data->timeout = 0;
-
-	if (purple_dnsquery_ui_resolve(query_data))
-	{
-		/* The UI is handling the resolve; we're done */
-		return FALSE;
-	}
-
-	if (!inet_aton(query_data->hostname, &sin.sin_addr)) {
-		struct hostent *hp;
-		gchar *hostname;
-#ifdef USE_IDN
-		if (!dns_str_is_ascii(query_data->hostname)) {
-			int ret = purple_network_convert_idn_to_ascii(query_data->hostname,
-					&hostname);
-			if (ret != 0) {
-				char message[1024];
-				g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
-						query_data->hostname, ret);
-				purple_dnsquery_failed(query_data, message);
-				return FALSE;
-			}
-		} else /* fallthrough is intentional to the g_strdup */
-#endif
-		hostname = g_strdup(query_data->hostname);
-
-		if(!(hp = gethostbyname(hostname))) {
-			char message[1024];
-			g_snprintf(message, sizeof(message), _("Error resolving %s: %d"),
-					query_data->hostname, h_errno);
-			purple_dnsquery_failed(query_data, message);
-			g_free(hostname);
-			return FALSE;
-		}
-		memset(&sin, 0, sizeof(struct sockaddr_in));
-		memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
-		sin.sin_family = hp->h_addrtype;
-		g_free(hostname);
-	} else
-		sin.sin_family = AF_INET;
-	sin.sin_port = htons(query_data->port);
-
-	hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin)));
-	hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin)));
-
-	purple_dnsquery_resolved(query_data, hosts);
-
-	return FALSE;
-}
-
 PurpleDnsQueryData *
 purple_dnsquery_a(const char *hostname, int port,
 				PurpleDnsQueryConnectFunction callback, gpointer data)
 {
-	PurpleDnsQueryData *query_data;
-
-	g_return_val_if_fail(hostname != NULL, NULL);
-	g_return_val_if_fail(port	  != 0, NULL);
-	g_return_val_if_fail(callback != NULL, NULL);
-
-	query_data = g_new(PurpleDnsQueryData, 1);
-	query_data->hostname = g_strdup(hostname);
-	g_strstrip(query_data->hostname);
-	query_data->port = port;
-	query_data->callback = callback;
-	query_data->data = data;
-
-	if (strlen(query_data->hostname) == 0)
-	{
-		purple_dnsquery_destroy(query_data);
-		g_return_val_if_reached(NULL);
-	}
-
-	/* Don't call the callback before returning */
-	query_data->timeout = purple_timeout_add(0, resolve_host, query_data);
-
-	return query_data;
+	return purple_dnsquery_a_account(NULL, hostname, port, callback, data);
 }
 
-#endif /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */
-
 void
 purple_dnsquery_destroy(PurpleDnsQueryData *query_data)
 {
--- a/libpurple/dnsquery.h	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/dnsquery.h	Thu Apr 21 20:36:02 2011 +0900
@@ -88,6 +88,7 @@
 /**
  * Perform an asynchronous DNS query.
  *
+ * @param account the account that the query is being done for (or NULL)
  * @param hostname The hostname to resolve.
  * @param port     A port number which is stored in the struct sockaddr.
  * @param callback The callback function to call after resolving.
@@ -96,8 +97,28 @@
  * @return NULL if there was an error, otherwise return a reference to
  *         a data structure that can be used to cancel the pending
  *         DNS query, if needed.
+ *
+ * @since 2.8.0
+ */
+PurpleDnsQueryData *purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data);
+
+#ifndef PURPLE_DISABLE_DEPRECATED
+/**
+ * Perform an asynchronous DNS query.
+ *
+ * @param hostname The hostname to resolve.
+ * @param port     A port number which is stored in the struct sockaddr.
+ * @param callback The callback function to call after resolving.
+ * @param data     Extra data to pass to the callback function.
+ *
+ * @return NULL if there was an error, otherwise return a reference to
+ *         a data structure that can be used to cancel the pending
+ *         DNS query, if needed.
+ *
+ * @deprecated Use purple_dnsquery_a_account instead
  */
 PurpleDnsQueryData *purple_dnsquery_a(const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data);
+#endif
 
 /**
  * Cancel a DNS query and destroy the associated data structure.
--- a/libpurple/dnssrv.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/dnssrv.c	Thu Apr 21 20:36:02 2011 +0900
@@ -30,12 +30,6 @@
 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
 #include <arpa/nameser_compat.h>
 #endif
-#ifndef T_SRV
-#define T_SRV	PurpleDnsTypeSrv
-#endif
-#ifndef T_TXT
-#define T_TXT	PurpleDnsTypeTxt
-#endif
 #else /* WIN32 */
 #include <windns.h>
 /* Missing from the mingw headers */
@@ -47,6 +41,13 @@
 #endif
 #endif
 
+#ifndef T_SRV
+#define T_SRV	PurpleDnsTypeSrv
+#endif
+#ifndef T_TXT
+#define T_TXT	PurpleDnsTypeTxt
+#endif
+
 #include "debug.h"
 #include "dnssrv.h"
 #include "eventloop.h"
@@ -673,11 +674,22 @@
 #endif
 
 PurpleSrvTxtQueryData *
-purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata)
+purple_srv_resolve(const char *protocol, const char *transport,
+	const char *domain, PurpleSrvCallback cb, gpointer extradata)
+{
+	return purple_srv_resolve_account(NULL, protocol, transport, domain,
+			cb, extradata);
+}
+
+PurpleSrvTxtQueryData *
+purple_srv_resolve_account(PurpleAccount *account, const char *protocol,
+	const char *transport, const char *domain, PurpleSrvCallback cb,
+	gpointer extradata)
 {
 	char *query;
 	char *hostname;
 	PurpleSrvTxtQueryData *query_data;
+	PurpleProxyType proxy_type;
 #ifndef _WIN32
 	PurpleSrvInternalQuery internal_query;
 	int in[2], out[2];
@@ -693,6 +705,14 @@
 		g_return_val_if_reached(NULL);
 	}
 
+	proxy_type = purple_proxy_info_get_type(
+		purple_proxy_get_setup(account));
+	if (proxy_type == PURPLE_PROXY_TOR) {
+		purple_debug_info("dnssrv", "Aborting SRV lookup in Tor Proxy mode.");
+		cb(NULL, 0, extradata);
+		return NULL;
+	}
+
 #ifdef USE_IDN
 	if (!dns_str_is_ascii(domain)) {
 		int ret = purple_network_convert_idn_to_ascii(domain, &hostname);
@@ -794,11 +814,20 @@
 #endif
 }
 
-PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata)
+PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner,
+	const char *domain, PurpleTxtCallback cb, gpointer extradata)
+{
+	return purple_txt_resolve_account(NULL, owner, domain, cb, extradata);
+}
+
+PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account,
+	const char *owner, const char *domain, PurpleTxtCallback cb,
+	gpointer extradata)
 {
 	char *query;
 	char *hostname;
 	PurpleSrvTxtQueryData *query_data;
+	PurpleProxyType proxy_type;
 #ifndef _WIN32
 	PurpleSrvInternalQuery internal_query;
 	int in[2], out[2];
@@ -808,6 +837,14 @@
 	static gboolean initialized = FALSE;
 #endif
 
+	proxy_type = purple_proxy_info_get_type(
+		purple_proxy_get_setup(account));
+	if (proxy_type == PURPLE_PROXY_TOR) {
+		purple_debug_info("dnssrv", "Aborting TXT lookup in Tor Proxy mode.");
+		cb(NULL, extradata);
+		return NULL;
+	}
+
 #ifdef USE_IDN
 	if (!dns_str_is_ascii(domain)) {
 		int ret = purple_network_convert_idn_to_ascii(domain, &hostname);
@@ -1042,4 +1079,4 @@
 	g_return_val_if_fail(query_data != NULL, 0);
 	
 	return query_data->type;
-}
\ No newline at end of file
+}
--- a/libpurple/dnssrv.h	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/dnssrv.h	Thu Apr 21 20:36:02 2011 +0900
@@ -103,13 +103,31 @@
 /**
  * Queries an SRV record.
  *
+ * @param account the account that the query is being done for (or NULL)
  * @param protocol Name of the protocol (e.g. "sip")
  * @param transport Name of the transport ("tcp" or "udp")
  * @param domain Domain name to query (e.g. "blubb.com")
  * @param cb A callback which will be called with the results
  * @param extradata Extra data to be passed to the callback
+ *
+ * @since 2.8.0
+ */
+PurpleSrvTxtQueryData *purple_srv_resolve_account(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata);
+
+#ifndef PURPLE_DISABLE_DEPRECATED
+/**
+ * Queries an SRV record.
+ *
+ * @param protocol Name of the protocol (e.g. "sip")
+ * @param transport Name of the transport ("tcp" or "udp")
+ * @param domain Domain name to query (e.g. "blubb.com")
+ * @param cb A callback which will be called with the results
+ * @param extradata Extra data to be passed to the callback
+ *
+ * @deprecated Use purple_srv_resolve_account instead
  */
 PurpleSrvTxtQueryData *purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata);
+#endif
 
 /**
  * Cancel an SRV or DNS query.
@@ -121,14 +139,31 @@
 /**
  * Queries an TXT record.
  *
+ * @param account the account that the query is being done for (or NULL)
  * @param owner Name of the protocol (e.g. "_xmppconnect")
  * @param domain Domain name to query (e.g. "blubb.com")
  * @param cb A callback which will be called with the results
  * @param extradata Extra data to be passed to the callback
  *
+ * @since 2.8.0
+ */
+PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata);
+
+#ifndef PURPLE_DISABLE_DEPRECATED
+/**
+ * Queries an TXT record.
+ *
+ * @param owner Name of the protocol (e.g. "_xmppconnect")
+ * @param domain Domain name to query (e.g. "blubb.com")
+ * @param cb A callback which will be called with the results
+ * @param extradata Extra data to be passed to the callback
+ *
+ * @deprecated Use purple_txt_resolve_account instead
+ *
  * @since 2.6.0
  */
 PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata);
+#endif
 
 /**
  * Cancel an TXT DNS query.
--- a/libpurple/network.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/network.c	Thu Apr 21 20:36:02 2011 +0900
@@ -71,6 +71,10 @@
 #include <dbus/dbus-glib.h>
 #include <NetworkManager.h>
 
+#if !defined(NM_CHECK_VERSION)
+#define NM_CHECK_VERSION(x,y,z) 0
+#endif
+
 static DBusGConnection *nm_conn = NULL;
 static DBusGProxy *nm_proxy = NULL;
 static DBusGProxy *dbus_proxy = NULL;
@@ -863,7 +867,13 @@
 
 	switch(state)
 	{
+#if NM_CHECK_VERSION(0,8,992)
+		case NM_STATE_CONNECTED_LOCAL:
+		case NM_STATE_CONNECTED_SITE:
+		case NM_STATE_CONNECTED_GLOBAL:
+#else
 		case NM_STATE_CONNECTED:
+#endif
 			/* Call res_init in case DNS servers have changed */
 			res_init();
 			/* update STUN IP in case we it changed (theoretically we could
@@ -880,6 +890,9 @@
 		case NM_STATE_ASLEEP:
 		case NM_STATE_CONNECTING:
 		case NM_STATE_DISCONNECTED:
+#if NM_CHECK_VERSION(0,8,992)
+		case NM_STATE_DISCONNECTING:
+#endif
 			if (prev != NM_STATE_CONNECTED && prev != NM_STATE_UNKNOWN)
 				break;
 			if (ui_ops != NULL && ui_ops->network_disconnected != NULL)
@@ -978,7 +991,7 @@
 	if (stun_server && stun_server[0] != '\0') {
 		if (purple_network_is_available()) {
 			purple_debug_info("network", "running DNS query for STUN server\n");
-			purple_dnsquery_a(stun_server, 3478, purple_network_ip_lookup_cb,
+			purple_dnsquery_a_account(NULL, stun_server, 3478, purple_network_ip_lookup_cb,
 				&stun_ip);
 		} else {
 			purple_debug_info("network",
@@ -996,7 +1009,7 @@
 	if (turn_server && turn_server[0] != '\0') {
 		if (purple_network_is_available()) {
 			purple_debug_info("network", "running DNS query for TURN server\n");
-			purple_dnsquery_a(turn_server,
+			purple_dnsquery_a_account(NULL, turn_server,
 				purple_prefs_get_int("/purple/network/turn_port"),
 				purple_network_ip_lookup_cb, &turn_ip);
 		} else {
--- a/libpurple/pounce.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/pounce.c	Thu Apr 21 20:36:02 2011 +0900
@@ -695,6 +695,31 @@
 }
 
 void
+purple_pounce_destroy_all_by_buddy(PurpleBuddy *buddy)
+{
+	const char *pouncee, *bname;
+	PurpleAccount *pouncer, *bacct;
+	PurplePounce *pounce;
+	GList *l, *l_next;
+
+	g_return_if_fail(buddy != NULL);
+
+	bacct = purple_buddy_get_account(buddy);
+	bname = purple_buddy_get_name(buddy);
+
+	for (l = purple_pounces_get_all(); l != NULL; l = l_next) {
+		pounce = (PurplePounce *)l->data;
+		l_next = l->next;
+
+		pouncer = purple_pounce_get_pouncer(pounce);
+		pouncee = purple_pounce_get_pouncee(pounce);
+
+		if ( (pouncer == bacct) && (strcmp(pouncee, bname) == 0) )
+			purple_pounce_destroy(pounce);
+	}
+}
+
+void
 purple_pounce_set_events(PurplePounce *pounce, PurplePounceEvent events)
 {
 	g_return_if_fail(pounce != NULL);
--- a/libpurple/pounce.h	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/pounce.h	Thu Apr 21 20:36:02 2011 +0900
@@ -123,6 +123,15 @@
 void purple_pounce_destroy_all_by_account(PurpleAccount *account);
 
 /**
+ * Destroys all buddy pounces for a buddy
+ *
+ * @param buddy The buddy whose pounces are to be removed
+ *
+ * @since 2.8.0
+ */
+void purple_pounce_destroy_all_by_buddy(PurpleBuddy *buddy);
+
+/**
  * Sets the events a pounce should watch for.
  *
  * @param pounce The buddy pounce.
--- a/libpurple/protocols/bonjour/bonjour_ft.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/bonjour/bonjour_ft.c	Thu Apr 21 20:36:02 2011 +0900
@@ -883,8 +883,9 @@
 	purple_proxy_info_set_type(xf->proxy_info, PURPLE_PROXY_SOCKS5);
 	purple_proxy_info_set_host(xf->proxy_info, xf->proxy_host);
 	purple_proxy_info_set_port(xf->proxy_info, xf->proxy_port);
-	xf->proxy_connection = purple_proxy_connect_socks5(
+	xf->proxy_connection = purple_proxy_connect_socks5_account(
 							   purple_account_get_connection(account),
+							   account,
 							   xf->proxy_info,
 							   dstaddr, 0,
 							   bonjour_bytestreams_connect_cb, xfer);
--- a/libpurple/protocols/gg/Makefile.am	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/gg/Makefile.am	Thu Apr 21 20:36:02 2011 +0900
@@ -56,7 +56,13 @@
 	lib/session.h \
 	lib/sha1.c
 
-INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED
+INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED -DUSE_INTERNAL_LIBGADU
+
+if USE_GNUTLS
+INTGG_CFLAGS += -DUSE_GNUTLS
+GADU_LIBS += $(GNUTLS_LIBS)
+endif
+
 endif
 
 GGSOURCES = \
--- a/libpurple/protocols/gg/gg.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/gg/gg.c	Thu Apr 21 20:36:02 2011 +0900
@@ -1044,6 +1044,29 @@
 }
 
 /**
+ * Try to update avatar of the buddy.
+ *
+ * @param gc     PurpleConnection
+ * @param uin    UIN of the buddy.
+ */
+static void ggp_update_buddy_avatar(PurpleConnection *gc, uin_t uin)
+{
+	gchar *avatarurl;
+	PurpleUtilFetchUrlData *url_data;
+
+	purple_debug_info("gg", "ggp_update_buddy_avatar(gc, %u)\n", uin);
+
+	avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin);
+
+	url_data = purple_util_fetch_url_request_len_with_account(
+			purple_connection_get_account(gc), avatarurl, TRUE,
+			"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
+			gg_get_avatar_url_cb, gc);
+
+	g_free(avatarurl);
+}
+
+/**
  * Handle change of the status of the buddy.
  *
  * @param gc     PurpleConnection
@@ -1056,18 +1079,10 @@
 {
 	gchar *from;
 	const char *st;
-	gchar *avatarurl;
-	PurpleUtilFetchUrlData *url_data;
+
+	ggp_update_buddy_avatar(gc, uin);
 
 	from = g_strdup_printf("%u", uin);
-	avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%s/0.xml", from);
-
-	url_data = purple_util_fetch_url_request_len_with_account(
-			purple_connection_get_account(gc), avatarurl, TRUE,
-			"Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
-			gg_get_avatar_url_cb, gc);
-
-	g_free(avatarurl);
 
 	switch (status) {
 		case GG_STATUS_NOT_AVAIL:
@@ -1383,8 +1398,8 @@
 			info->pending_richtext_messages = g_list_remove(info->pending_richtext_messages, entry->data);
 			/* We don't have any more images to download */
 			if (strstr(text, "<IMG ID=\"IMGID_HANDLER") == NULL) {
-				gchar *buf = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender);
-				serv_got_im(gc, buf, text, PURPLE_MESSAGE_IMAGES, ev->event.msg.time);
+				gchar *buf = g_strdup_printf("%lu", (unsigned long int)ev->event.image_reply.sender);
+				serv_got_im(gc, buf, text, PURPLE_MESSAGE_IMAGES, time(NULL));
 				g_free(buf);
 				purple_debug_info("gg", "ggp_recv_image_handler: richtext message: %s\n", text);
 				g_free(text);
@@ -1610,10 +1625,79 @@
     if (length)
 	serv_got_typing(gc, from, 0, PURPLE_TYPING);
     else
-	serv_got_typing(gc, from, 0, PURPLE_NOT_TYPING);
+	serv_got_typing_stopped(gc, from);
     g_free(from);
 }
 
+/**
+ * Handling of XML events.
+ *
+ * @param gc PurpleConnection.
+ * @param data Raw XML contents.
+ *
+ * @see http://toxygen.net/libgadu/protocol/#ch1.13
+ */
+static void ggp_xml_event_handler(PurpleConnection *gc, char *data)
+{
+	xmlnode *xml = NULL;
+	xmlnode *xmlnode_next_event;
+
+	xml = xmlnode_from_str(data, -1);
+	if (xml == NULL)
+		goto out;
+
+	xmlnode_next_event = xmlnode_get_child(xml, "event");
+	while (xmlnode_next_event != NULL)
+	{
+		xmlnode *xmlnode_current_event = xmlnode_next_event;
+		
+		xmlnode *xmlnode_type;
+		char *event_type_raw;
+		int event_type = 0;
+		
+		xmlnode *xmlnode_sender;
+		char *event_sender_raw;
+		uin_t event_sender = 0;
+
+		xmlnode_next_event = xmlnode_get_next_twin(xmlnode_next_event);
+		
+		xmlnode_type = xmlnode_get_child(xmlnode_current_event, "type");
+		if (xmlnode_type == NULL)
+			continue;
+		event_type_raw = xmlnode_get_data(xmlnode_type);
+		if (event_type_raw != NULL)
+			event_type = atoi(event_type_raw);
+		g_free(event_type_raw);
+		
+		xmlnode_sender = xmlnode_get_child(xmlnode_current_event, "sender");
+		if (xmlnode_sender != NULL)
+		{
+			event_sender_raw = xmlnode_get_data(xmlnode_sender);
+			if (event_sender_raw != NULL)
+				event_sender = ggp_str_to_uin(event_sender_raw);
+			g_free(event_sender_raw);
+		}
+		
+		switch (event_type)
+		{
+			case 28: /* avatar update */
+				purple_debug_info("gg",
+					"ggp_xml_event_handler: avatar updated (uid: %u)\n",
+					event_sender);
+				ggp_update_buddy_avatar(gc, event_sender);
+				break;
+			default:
+				purple_debug_error("gg",
+					"ggp_xml_event_handler: unsupported event type=%d from=%u\n",
+					event_type, event_sender);
+		}
+	}
+	
+	out:
+		if (xml)
+			xmlnode_free(xml);
+}
+
 static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
 {
 	PurpleConnection *gc = _gc;
@@ -1629,7 +1713,7 @@
 			_("Unable to read from socket"));
 		return;
 	}
-	gc->last_received = time(NULL);
+
 	switch (ev->type) {
 		case GG_EVENT_NONE:
 			/* Nothing happened. */
@@ -1731,6 +1815,10 @@
 			ggp_typing_notification_handler(gc, ev->event.typing_notification.uin,
 				ev->event.typing_notification.length);
 			break;
+		case GG_EVENT_XML_EVENT:
+			purple_debug_info("gg", "GG_EVENT_XML_EVENT\n");
+			ggp_xml_event_handler(gc, ev->event.xml_event.data);
+			break;
 		default:
 			purple_debug_error("gg",
 				"unsupported event type=%d\n", ev->type);
@@ -2041,7 +2129,12 @@
 
 	glp->async = 1;
 	glp->status = ggp_to_gg_status(status, &glp->status_descr);
+#if defined(USE_GNUTLS) || !defined(USE_INTERNAL_LIBGADU)
+	glp->tls = 1;
+#else
 	glp->tls = 0;
+#endif
+	purple_debug_info("gg", "TLS enabled: %d\n", glp->tls);
 
 	if (!info->status_broadcasting)
 		glp->status = glp->status|GG_STATUS_FRIENDS_MASK;
@@ -2241,6 +2334,26 @@
 	return ret;
 }
 
+static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
+{
+	int dummy_length; // we don't send real length of typed message
+	
+	if (state == PURPLE_TYPED) // not supported
+		return 1;
+	
+	if (state == PURPLE_TYPING)
+		dummy_length = (int)g_random_int();
+	else // PURPLE_NOT_TYPING
+		dummy_length = 0;
+	
+	gg_typing_notification(
+		((GGPInfo*)gc->proto_data)->session,
+		ggp_str_to_uin(name),
+		dummy_length); 
+	
+	return 1; // wait 1 second before another notification
+}
+
 static void ggp_get_info(PurpleConnection *gc, const char *name)
 {
 	GGPInfo *info = gc->proto_data;
@@ -2546,7 +2659,7 @@
 	ggp_close,			/* close */
 	ggp_send_im,			/* send_im */
 	NULL,				/* set_info */
-	NULL,				/* send_typing */
+	ggp_send_typing,		/* send_typing */
 	ggp_get_info,			/* get_info */
 	ggp_set_status,			/* set_away */
 	NULL,				/* set_idle */
--- a/libpurple/protocols/gg/lib/libgadu.h	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/gg/lib/libgadu.h	Thu Apr 21 20:36:02 2011 +0900
@@ -72,7 +72,11 @@
 #undef GG_CONFIG_HAVE_LONG_LONG
 
 /* Defined if libgadu was compiled and linked with GnuTLS support. */
-#undef GG_CONFIG_HAVE_GNUTLS
+#ifdef USE_GNUTLS
+#	define GG_CONFIG_HAVE_GNUTLS
+#else
+#	undef GG_CONFIG_HAVE_GNUTLS
+#endif
 
 /* Defined if libgadu was compiled and linked with OpenSSL support. */
 #undef GG_CONFIG_HAVE_OPENSSL
--- a/libpurple/protocols/irc/irc.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/irc/irc.c	Thu Apr 21 20:36:02 2011 +0900
@@ -403,8 +403,7 @@
 
 static gboolean do_login(PurpleConnection *gc) {
 	char *buf, *tmp = NULL;
-	char *hostname, *server;
-	const char *hosttmp;
+	char *server;
 	const char *username, *realname;
 	struct irc_conn *irc = gc->proto_data;
 	const char *pass = purple_connection_get_password(gc);
@@ -432,17 +431,6 @@
 		}
 	}
 
-	hosttmp = purple_get_host_name();
-	if (*hosttmp == ':') {
-		/* This is either an IPv6 address, or something which
-		 * doesn't belong here.  Either way, we need to escape
-		 * it. */
-		hostname = g_strdup_printf("0%s", hosttmp);
-	} else {
-		/* Ugly, I know. */
-		hostname = g_strdup(hosttmp);
-	}
-
 	if (*irc->server == ':') {
 		/* Same as hostname, above. */
 		server = g_strdup_printf("0%s", irc->server);
@@ -450,10 +438,9 @@
 		server = g_strdup(irc->server);
 	}
 
-	buf = irc_format(irc, "vvvv:", "USER", tmp ? tmp : username, hostname, server,
+	buf = irc_format(irc, "vvvv:", "USER", tmp ? tmp : username, "*", server,
 	                 strlen(realname) ? realname : IRC_DEFAULT_ALIAS);
 	g_free(tmp);
-	g_free(hostname);
 	g_free(server);
 	if (irc_send(irc, buf) < 0) {
 		g_free(buf);
--- a/libpurple/protocols/irc/parse.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/irc/parse.c	Thu Apr 21 20:36:02 2011 +0900
@@ -125,6 +125,7 @@
 	char *help;
 } _irc_cmds[] = {
 	{ "action", ":", irc_cmd_ctcp_action, N_("action &lt;action to perform&gt;:  Perform an action.") },
+	{ "authserv", ":", irc_cmd_service, N_("authserv: Send a command to authserv") },
 	{ "away", ":", irc_cmd_away, N_("away [message]:  Set an away message, or use no message to return from being away.") },
 	{ "ctcp", "t:", irc_cmd_ctcp, N_("ctcp <nick> <msg>: sends ctcp msg to nick.") },
 	{ "chanserv", ":", irc_cmd_service, N_("chanserv: Send a command to chanserv") },
--- a/libpurple/protocols/jabber/buddy.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/jabber/buddy.c	Thu Apr 21 20:36:02 2011 +0900
@@ -2229,6 +2229,16 @@
 		return;
 	}
 
+	/* If the value provided isn't the disco#info default, persist it.  Otherwise,
+	   make sure we aren't persisting an old value */
+	if(js->user_directories && js->user_directories->data &&
+	   !strcmp(directory, js->user_directories->data)) {
+		purple_account_set_string(js->gc->account, "user_directory", "");
+	}
+	else {
+		purple_account_set_string(js->gc->account, "user_directory", directory);
+	}
+
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search");
 	xmlnode_set_attrib(iq->node, "to", directory);
 
@@ -2241,10 +2251,13 @@
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
+	const char *def_val = purple_account_get_string(js->gc->account, "user_directory", "");
+	if(!*def_val && js->user_directories)
+		def_val = js->user_directories->data;
 
 	purple_request_input(gc, _("Enter a User Directory"), _("Enter a User Directory"),
 			_("Select a user directory to search"),
-			js->user_directories ? js->user_directories->data : NULL,
+			def_val,
 			FALSE, FALSE, NULL,
 			_("Search Directory"), PURPLE_CALLBACK(jabber_user_search),
 			_("Cancel"), NULL,
--- a/libpurple/protocols/jabber/disco.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/jabber/disco.c	Thu Apr 21 20:36:02 2011 +0900
@@ -480,10 +480,12 @@
 	js->srv_query_data = NULL;
 
 	if (results > 0) {
+		PurpleAccount *account;
 		purple_debug_info("jabber", "looking up IP for %s:%d\n",
 			resp[0].hostname, resp[0].port);
+		account = purple_connection_get_account(js->gc);
 		js->stun_query =
-			purple_dnsquery_a(resp[0].hostname, resp[0].port,
+			purple_dnsquery_a_account(account, resp[0].hostname, resp[0].port,
 				jabber_disco_stun_lookup_cb, js);
 	}
 }
@@ -548,7 +550,9 @@
 		} else if (purple_network_get_stun_ip() == NULL ||
 		    purple_strequal(purple_network_get_stun_ip(), "")) {
 			js->srv_query_data =
-				purple_srv_resolve("stun", "udp", js->user->domain,
+				purple_srv_resolve_account(
+					purple_connection_get_account(js->gc), "stun", "udp",
+					js->user->domain,
 					jabber_disco_stun_srv_resolve_cb, js);
 			/* TODO: add TURN support later... */
 		}
--- a/libpurple/protocols/jabber/google/jingleinfo.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/jabber/google/jingleinfo.c	Thu Apr 21 20:36:02 2011 +0900
@@ -109,13 +109,15 @@
 			const gchar *udp = xmlnode_get_attrib(server, "udp");
 
 			if (host && udp) {
+				PurpleAccount *account;
 				int port = atoi(udp);
 				/* if there, would already be an ongoing query,
 				 cancel it */
 				if (js->stun_query)
 					purple_dnsquery_destroy(js->stun_query);
 
-				js->stun_query = purple_dnsquery_a(host, port,
+				account = purple_connection_get_account(js->gc);
+				js->stun_query = purple_dnsquery_a_account(account, host, port,
 					jabber_google_stun_lookup_cb, js);
 			}
 		}
--- a/libpurple/protocols/jabber/jabber.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/jabber/jabber.c	Thu Apr 21 20:36:02 2011 +0900
@@ -815,7 +815,8 @@
 			try_srv_connect(js);
 		} else {
 			purple_debug_info("jabber","Couldn't connect directly to %s.  Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
-			js->srv_query_data = purple_txt_resolve("_xmppconnect",
+			js->srv_query_data = purple_txt_resolve_account(
+					purple_connection_get_account(gc), "_xmppconnect",
 					js->user->domain, txt_resolved_cb, js);
 		}
 		return;
@@ -1074,7 +1075,7 @@
 		jabber_login_connect(js, js->user->domain, connect_server,
 				purple_account_get_int(account, "port", 5222), TRUE);
 	} else {
-		js->srv_query_data = purple_srv_resolve("xmpp-client",
+		js->srv_query_data = purple_srv_resolve_account(account, "xmpp-client",
 				"tcp", js->user->domain, srv_resolved_cb, js);
 	}
 }
--- a/libpurple/protocols/jabber/si.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/jabber/si.c	Thu Apr 21 20:36:02 2011 +0900
@@ -279,6 +279,7 @@
 
 	if(dstjid != NULL && streamhost->host && streamhost->port > 0) {
 		char *dstaddr, *hash;
+		PurpleAccount *account;
 		jsx->gpi = purple_proxy_info_new();
 		purple_proxy_info_set_type(jsx->gpi, PURPLE_PROXY_SOCKS5);
 		purple_proxy_info_set_host(jsx->gpi, streamhost->host);
@@ -295,8 +296,9 @@
 		/* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
 		hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1");
 
-		jsx->connect_data = purple_proxy_connect_socks5(NULL, jsx->gpi,
-				hash, 0,
+		account = purple_connection_get_account(jsx->js->gc);
+		jsx->connect_data = purple_proxy_connect_socks5_account(NULL, account,
+				jsx->gpi, hash, 0,
 				jabber_si_bytestreams_connect_cb, xfer);
 		g_free(hash);
 		g_free(dstaddr);
@@ -1696,6 +1698,7 @@
 	PurpleXfer *xfer;
 	xmlnode *file, *feature, *x, *field, *option, *value, *thumbnail;
 	const char *stream_id, *filename, *filesize_c, *profile;
+	guint64 filesize_64 = 0;
 	size_t filesize = 0;
 
 	if(!(profile = xmlnode_get_attrib(si, "profile")) ||
@@ -1712,7 +1715,17 @@
 		return;
 
 	if((filesize_c = xmlnode_get_attrib(file, "size")))
-		filesize = strtoul(filesize_c, NULL, 10);
+		filesize_64 = g_ascii_strtoull(filesize_c, NULL, 10);
+	/* TODO 3.0.0: When the core uses a guint64, this is redundant.
+	 * See #8477.
+	 */
+	if (filesize_64 > G_MAXSIZE) {
+		/* Should this pop up a warning? */
+		purple_debug_warning("jabber", "Unable to transfer file (too large)"
+		                     " -- see #8477 for more details.");
+		return;
+	}
+	filesize = filesize_64;
 
 	if(!(feature = xmlnode_get_child(si, "feature")))
 		return;
--- a/libpurple/protocols/qq/qq_network.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/qq/qq_network.c	Thu Apr 21 20:36:02 2011 +0900
@@ -987,7 +987,7 @@
 	}
 
 	purple_debug_info("QQ", "UDP Connect to %s:%d\n", server, port);
-	qd->udp_query_data = purple_dnsquery_a(server, port, udp_host_resolved, gc);
+	qd->udp_query_data = purple_dnsquery_a_account(account, server, port, udp_host_resolved, gc);
 	if ( qd->udp_query_data == NULL ) {
 		purple_debug_error("QQ", "Could not resolve hostname\n");
 		return FALSE;
--- a/libpurple/protocols/simple/simple.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/simple/simple.c	Thu Apr 21 20:36:02 2011 +0900
@@ -1903,7 +1903,8 @@
 	} else { /* UDP */
 		purple_debug_info("simple", "using udp with server %s and port %d\n", hostname, port);
 
-		sip->query_data = purple_dnsquery_a(hostname, port, simple_udp_host_resolved, sip);
+		sip->query_data = purple_dnsquery_a_account(sip->account, hostname,
+			port, simple_udp_host_resolved, sip);
 		if (sip->query_data == NULL) {
 			purple_connection_error_reason(sip->gc,
 				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -1965,7 +1966,7 @@
 		hosttoconnect = purple_account_get_string(account, "proxy", sip->servername);
 	}
 
-	sip->srv_query_data = purple_srv_resolve("sip",
+	sip->srv_query_data = purple_srv_resolve_account(account, "sip",
 			sip->udp ? "udp" : "tcp", hosttoconnect, srvresolved, sip);
 }
 
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Thu Apr 21 20:36:02 2011 +0900
@@ -1665,6 +1665,7 @@
 	}
 	if(val_222 == 3)
 	{
+		PurpleAccount *account;
 		xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
 								   xfer_peer_idstring);
 		if(!xfer)
@@ -1684,14 +1685,17 @@
 			return;
 		}
 
+		account = purple_connection_get_account(gc);
 		if (yd->jp)
 		{
-			purple_dnsquery_a(YAHOOJP_XFER_RELAY_HOST, YAHOOJP_XFER_RELAY_PORT,
+			purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST,
+							YAHOOJP_XFER_RELAY_PORT,
 							yahoo_xfer_dns_connected_15, xfer);
 		}
 		else
 		{
-			purple_dnsquery_a(YAHOO_XFER_RELAY_HOST, YAHOO_XFER_RELAY_PORT,
+			purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST,
+							YAHOO_XFER_RELAY_PORT,
 							yahoo_xfer_dns_connected_15, xfer);
 		}
 		return;
@@ -1789,7 +1793,6 @@
 	char *xfer_idstring_for_relay = NULL;
 	GSList *l;
 	struct yahoo_packet *pkt_to_send;
-	PurpleAccount *account;
 	struct yahoo_p2p_data *p2p_data;
 
 	yd = gc->proto_data;
@@ -1843,7 +1846,8 @@
 
 	xfer_data->info_val_249 = val_249;
 	xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
-	if(val_249 == 1 || val_249 == 3)	{
+	if(val_249 == 1 || val_249 == 3) {
+		PurpleAccount *account;
 		if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
 			purple_xfer_cancel_remote(xfer);
 			return;
--- a/libpurple/proxy.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/proxy.c	Thu Apr 21 20:36:02 2011 +0900
@@ -69,6 +69,7 @@
 	guchar *read_buffer;
 	gsize read_buf_len;
 	gsize read_len;
+	PurpleAccount *account;
 };
 
 static const char * const socks5errors[] = {
@@ -1367,7 +1368,8 @@
 
 		proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
 	} else {
-		connect_data->query_data = purple_dnsquery_a(connect_data->host,
+		connect_data->query_data = purple_dnsquery_a_account(
+				connect_data->account, connect_data->host,
 				connect_data->port, s4_host_resolved, connect_data);
 
 		if (connect_data->query_data == NULL) {
@@ -2137,6 +2139,7 @@
 			break;
 
 		case PURPLE_PROXY_SOCKS5:
+		case PURPLE_PROXY_TOR:
 			proxy_connect_socks5(connect_data, addr, addrlen);
 			break;
 
@@ -2281,6 +2284,7 @@
 	connect_data->host = g_strdup(host);
 	connect_data->port = port;
 	connect_data->gpi = purple_proxy_get_setup(account);
+	connect_data->account = account;
 
 	if ((purple_proxy_info_get_type(connect_data->gpi) != PURPLE_PROXY_NONE) &&
 		(purple_proxy_info_get_host(connect_data->gpi) == NULL ||
@@ -2299,6 +2303,7 @@
 		case PURPLE_PROXY_HTTP:
 		case PURPLE_PROXY_SOCKS4:
 		case PURPLE_PROXY_SOCKS5:
+		case PURPLE_PROXY_TOR:
 		case PURPLE_PROXY_USE_ENVVAR:
 			connecthost = purple_proxy_info_get_host(connect_data->gpi);
 			connectport = purple_proxy_info_get_port(connect_data->gpi);
@@ -2311,7 +2316,7 @@
 			return NULL;
 	}
 
-	connect_data->query_data = purple_dnsquery_a(connecthost,
+	connect_data->query_data = purple_dnsquery_a_account(account, connecthost,
 			connectport, connection_host_resolved, connect_data);
 	if (connect_data->query_data == NULL)
 	{
@@ -2347,6 +2352,7 @@
 	connect_data->host = g_strdup(host);
 	connect_data->port = port;
 	connect_data->gpi = purple_proxy_get_setup(account);
+	connect_data->account = account;
 
 	if ((purple_proxy_info_get_type(connect_data->gpi) != PURPLE_PROXY_NONE) &&
 		(purple_proxy_info_get_host(connect_data->gpi) == NULL ||
@@ -2365,6 +2371,7 @@
 		case PURPLE_PROXY_HTTP:
 		case PURPLE_PROXY_SOCKS4:
 		case PURPLE_PROXY_SOCKS5:
+		case PURPLE_PROXY_TOR:
 		case PURPLE_PROXY_USE_ENVVAR:
 			purple_debug_info("proxy", "Ignoring Proxy type (%d) for UDP.\n",
 			                  purple_proxy_info_get_type(connect_data->gpi));
@@ -2377,7 +2384,7 @@
 			return NULL;
 	}
 
-	connect_data->query_data = purple_dnsquery_a(connecthost,
+	connect_data->query_data = purple_dnsquery_a_account(account, connecthost,
 			connectport, connection_host_resolved, connect_data);
 	if (connect_data->query_data == NULL)
 	{
@@ -2399,6 +2406,19 @@
 						  PurpleProxyConnectFunction connect_cb,
 						  gpointer data)
 {
+	return purple_proxy_connect_socks5_account(NULL, handle, gpi,
+						  host, port, connect_cb, data);
+}
+/*
+ * Combine some of this code with purple_proxy_connect()
+ */
+PurpleProxyConnectData *
+purple_proxy_connect_socks5_account(void *handle, PurpleAccount *account,
+						  PurpleProxyInfo *gpi,
+						  const char *host, int port,
+						  PurpleProxyConnectFunction connect_cb,
+						  gpointer data)
+{
 	PurpleProxyConnectData *connect_data;
 
 	g_return_val_if_fail(host       != NULL, NULL);
@@ -2414,9 +2434,11 @@
 	connect_data->host = g_strdup(host);
 	connect_data->port = port;
 	connect_data->gpi = gpi;
+	connect_data->account = account;
 
 	connect_data->query_data =
-			purple_dnsquery_a(purple_proxy_info_get_host(gpi),
+			purple_dnsquery_a_account(account,
+					purple_proxy_info_get_host(gpi),
 					purple_proxy_info_get_port(gpi),
 					connection_host_resolved, connect_data);
 	if (connect_data->query_data == NULL)
@@ -2470,6 +2492,8 @@
 			proxytype = PURPLE_PROXY_SOCKS4;
 		else if (purple_strequal(type, "socks5"))
 			proxytype = PURPLE_PROXY_SOCKS5;
+		else if (purple_strequal(type, "tor"))
+			proxytype = PURPLE_PROXY_TOR;
 		else if (purple_strequal(type, "envvar"))
 			proxytype = PURPLE_PROXY_USE_ENVVAR;
 		else
--- a/libpurple/proxy.h	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/proxy.h	Thu Apr 21 20:36:02 2011 +0900
@@ -39,7 +39,8 @@
 	PURPLE_PROXY_HTTP,             /**< HTTP proxy.                       */
 	PURPLE_PROXY_SOCKS4,           /**< SOCKS 4 proxy.                    */
 	PURPLE_PROXY_SOCKS5,           /**< SOCKS 5 proxy.                    */
-	PURPLE_PROXY_USE_ENVVAR        /**< Use environmental settings.       */
+	PURPLE_PROXY_USE_ENVVAR,       /**< Use environmental settings.       */
+	PURPLE_PROXY_TOR               /**< Use a Tor proxy (SOCKS 5 really)  */
 
 } PurpleProxyType;
 
@@ -306,10 +307,39 @@
  *         opaque data structure that can be used to cancel
  *         the pending connection, if needed.
  */
+PurpleProxyConnectData *purple_proxy_connect_socks5_account(void *handle,
+			PurpleAccount *account, PurpleProxyInfo *gpi,
+			const char *host, int port,
+			PurpleProxyConnectFunction connect_cb, gpointer data);
+
+#ifndef PURPLE_DISABLE_DEPRECATED
+/**
+ * Makes a connection through a SOCKS5 proxy.
+ *
+ * @param handle     A handle that should be associated with this
+ *                   connection attempt.  The handle can be used
+ *                   to cancel the connection attempt using the
+ *                   purple_proxy_connect_cancel_with_handle()
+ *                   function.
+ * @param gpi        The PurpleProxyInfo specifying the proxy settings
+ * @param host       The destination host.
+ * @param port       The destination port.
+ * @param connect_cb The function to call when the connection is
+ *                   established.  If the connection failed then
+ *                   fd will be -1 and error message will be set
+ *                   to something descriptive (hopefully).
+ * @param data       User-defined data.
+ *
+ * @return NULL if there was an error, or a reference to an
+ *         opaque data structure that can be used to cancel
+ *         the pending connection, if needed.
+ * @deprecated Use purple_proxy_connect_socks5_account instead
+ */
 PurpleProxyConnectData *purple_proxy_connect_socks5(void *handle,
 			PurpleProxyInfo *gpi,
 			const char *host, int port,
 			PurpleProxyConnectFunction connect_cb, gpointer data);
+#endif
 
 /**
  * Cancel an in-progress connection attempt.  This should be called
--- a/libpurple/signals.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/signals.c	Thu Apr 21 20:36:02 2011 +0900
@@ -880,6 +880,20 @@
 }
 
 void
+purple_marshal_BOOLEAN__POINTER_BOOLEAN(PurpleCallback cb, va_list args,
+									  void *data, void **return_val)
+{
+	gboolean ret_val;
+	void *arg1 = va_arg(args, void *);
+	gboolean arg2 = va_arg(args, gboolean);
+
+	ret_val = ((gboolean (*)(void *, gboolean, void *))cb)(arg1, arg2, data);
+
+	if (return_val != NULL)
+		*return_val = GINT_TO_POINTER(ret_val);
+}
+
+void
 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER(PurpleCallback cb, va_list args,
 											  void *data, void **return_val)
 {
--- a/libpurple/signals.h	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/signals.h	Thu Apr 21 20:36:02 2011 +0900
@@ -339,6 +339,8 @@
 		PurpleCallback cb, va_list args, void *data, void **return_val);
 void purple_marshal_BOOLEAN__POINTER_POINTER(
 		PurpleCallback cb, va_list args, void *data, void **return_val);
+void purple_marshal_BOOLEAN__POINTER_BOOLEAN(
+		PurpleCallback cb, va_list args, void *data, void **return_val);
 void purple_marshal_BOOLEAN__POINTER_POINTER_POINTER(
 		PurpleCallback cb, va_list args, void *data, void **return_val);
 void purple_marshal_BOOLEAN__POINTER_POINTER_UINT(
--- a/libpurple/stun.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/libpurple/stun.c	Thu Apr 21 20:36:02 2011 +0900
@@ -365,7 +365,7 @@
 	purple_debug_info("stun", "got %d SRV responses, server: %s, port: %d\n",
 		results, servername, port);
 
-	purple_dnsquery_a(servername, port, hbn_cb, NULL);
+	purple_dnsquery_a_account(NULL, servername, port, hbn_cb, NULL);
 	g_free(resp);
 }
 
@@ -424,7 +424,7 @@
 	nattype.servername = g_strdup(servername);
 
 	callbacks = g_slist_append(callbacks, cb);
-	purple_srv_resolve("stun", "udp", servername, do_test1,
+	purple_srv_resolve_account(NULL, "stun", "udp", servername, do_test1,
 		(gpointer) servername);
 
 	return &nattype;
--- a/pidgin/gtkaccount.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/pidgin/gtkaccount.c	Thu Apr 21 20:36:02 2011 +0900
@@ -1021,6 +1021,12 @@
 
 	gtk_list_store_append(model, &iter);
 	gtk_list_store_set(model, &iter,
+			0, _("Tor/Privacy (SOCKS5)"),
+			1, PURPLE_PROXY_TOR,
+			-1);
+
+	gtk_list_store_append(model, &iter);
+	gtk_list_store_set(model, &iter,
 			0, _("Use Environmental Settings"),
 			1, PURPLE_PROXY_USE_ENVVAR,
 			-1);
@@ -2254,7 +2260,7 @@
 					 G_CALLBACK(account_treeview_double_click_cb), dialog);
 
 	gtk_notebook_append_page(GTK_NOTEBOOK(accounts_window->notebook),
-		pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1), 
+		pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1),
 		NULL);
 
 	add_columns(treeview, dialog);
--- a/pidgin/gtkconv.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/pidgin/gtkconv.c	Thu Apr 21 20:36:02 2011 +0900
@@ -1848,6 +1848,15 @@
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
 	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
 
+	/* emit chat-nick-clicked signal */
+	if (event->type == GDK_BUTTON_PRESS) {
+		gint plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
+					pidgin_conversations_get_handle(), "chat-nick-clicked",
+					conv, who, event->button));
+		if (plugin_return)
+			goto handled;
+	}
+
 	if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
 		chat_do_im(gtkconv, who);
 	} else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) {
@@ -1862,6 +1871,7 @@
 					   event->button, event->time);
 	}
 
+handled:
 	g_free(who);
 	gtk_tree_path_free(path);
 
@@ -2178,7 +2188,13 @@
 		case GDK_ISO_Left_Tab:
 			if (gtkconv->entry != entry)
 				break;
-			return tab_complete(conv);
+			{
+				gint plugin_return;
+				plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
+							pidgin_conversations_get_handle(), "chat-nick-autocomplete",
+							conv, event->state & GDK_SHIFT_MASK));
+				return plugin_return ? TRUE : tab_complete(conv);
+			}
 			break;
 
 		case GDK_Page_Up:
@@ -5679,6 +5695,15 @@
 
 		buddyname = (tag->name) + 6;
 
+		/* emit chat-nick-clicked signal */
+		if (event->type == GDK_BUTTON_PRESS) {
+			gint plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1(
+						pidgin_conversations_get_handle(), "chat-nick-clicked",
+						data, buddyname, btn_event->button));
+			if (plugin_return)
+				return TRUE;
+		}
+
 		if (btn_event->button == 1 &&
 				event->type == GDK_2BUTTON_PRESS) {
 			chat_do_im(PIDGIN_CONVERSATION(conv), buddyname);
@@ -8139,6 +8164,21 @@
 						 purple_value_new(PURPLE_TYPE_BOXED,
 										"PidginConversation *"));
 
+	purple_signal_register(handle, "chat-nick-autocomplete",
+						 purple_marshal_BOOLEAN__POINTER_BOOLEAN,
+						 purple_value_new(PURPLE_TYPE_BOOLEAN), 1,
+						 purple_value_new(PURPLE_TYPE_SUBTYPE,
+							 			PURPLE_SUBTYPE_CONVERSATION));
+
+	purple_signal_register(handle, "chat-nick-clicked",
+						 purple_marshal_BOOLEAN__POINTER_POINTER_UINT,
+						 purple_value_new(PURPLE_TYPE_BOOLEAN), 3,
+						 purple_value_new(PURPLE_TYPE_SUBTYPE,
+							 			PURPLE_SUBTYPE_CONVERSATION),
+						 purple_value_new(PURPLE_TYPE_STRING),
+						 purple_value_new(PURPLE_TYPE_UINT));
+
+
 	/**********************************************************************
 	 * Register commands
 	 **********************************************************************/
--- a/pidgin/gtkdialogs.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/pidgin/gtkdialogs.c	Thu Apr 21 20:36:02 2011 +0900
@@ -102,8 +102,10 @@
 /* Order: Alphabetical by Last Name */
 static const struct developer patch_writers[] = {
 	{"Jakub 'haakon' Adam",            NULL,                        NULL},
+	{"Krzysztof Klinikowski",          NULL,                        NULL},
 	{"Peter 'Fmoo' Ruibal",            NULL,                        NULL},
 	{"Gabriel 'Nix' Schulhof",         NULL,                        NULL},
+	{"Tomasz Wasilczyk",               NULL,                        NULL},
 	{NULL, NULL, NULL}
 };
 
--- a/pidgin/gtkprefs.c	Fri Apr 01 13:47:51 2011 +0900
+++ b/pidgin/gtkprefs.c	Thu Apr 21 20:36:02 2011 +0900
@@ -2044,9 +2044,10 @@
 		pidgin_prefs_dropdown(prefs_proxy_frame, _("Proxy t_ype:"), PURPLE_PREF_STRING,
 					"/purple/proxy/type",
 					_("No proxy"), "none",
-					"SOCKS 4", "socks4",
-					"SOCKS 5", "socks5",
-					"HTTP", "http",
+					_("SOCKS 4"), "socks4",
+					_("SOCKS 5"), "socks5",
+					_("Tor/Privacy (SOCKS5)"), "tor",
+					_("HTTP"), "http",
 					_("Use Environmental Settings"), "envvar",
 					NULL);
 		gtk_box_pack_start(GTK_BOX(prefs_proxy_frame), prefs_proxy_subframe, 0, 0, 0);
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Fri Apr 01 13:47:51 2011 +0900
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Thu Apr 21 20:36:02 2011 +0900
@@ -536,6 +536,7 @@
     Delete "$INSTDIR\ca-certs\CAcert_Class3.pem"
     Delete "$INSTDIR\ca-certs\CAcert_Root.pem"
     Delete "$INSTDIR\ca-certs\Deutsche_Telekom_Root_CA_2.pem"
+    Delete "$INSTDIR\ca-certs\DigiCertHighAssuranceCA-3.pem"
     Delete "$INSTDIR\ca-certs\Entrust.net_Secure_Server_CA.pem"
     Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem"
     Delete "$INSTDIR\ca-certs\Equifax_Secure_Global_eBusiness_CA-1.pem"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/ca-certs/DigiCertHighAssuranceCA-3.pem	Thu Apr 21 20:36:02 2011 +0900
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGVTCCBT2gAwIBAgIQCFH5WYFBRcq94CTiEsnCDjANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA3MDQwMzAwMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
+CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
+KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
+BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
+1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
+zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
+32duXvsCAwEAAaOCAvcwggLzMA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
+ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
+LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
+AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
+AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
+AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
+AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
+AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
+AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
+AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
+AHIAZQBuAGMAZQAuMA8GA1UdEwEB/wQFMAMBAf8wNAYIKwYBBQUHAQEEKDAmMCQG
+CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSBhzCB
+hDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFz
+c3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu
+Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSMEGDAW
+gBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUBINTe
+eZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAF1PhPGoiNOjsrycbeUpSXfh59bcqdg1
+rslx3OXb3J0kIZCmz7cBHJvUV5eR13UWpRLXuT0uiT05aYrWNTf58SHEW0CtWakv
+XzoAKUMncQPkvTAyVab+hA4LmzgZLEN8rEO/dTHlIxxFVbdpCJG1z9fVsV7un5Tk
+1nq5GMO41lJjHBC6iy9tXcwFOPRWBW3vnuzoYTYMFEuFFFoMg08iXFnLjIpx2vrF
+EIRYzwfu45DC9fkpx1ojcflZtGQriLCnNseaIGHr+k61rmsb5OPs4tk8QUmoIKRU
+9ZKNu8BVIASm2LAXFszj0Mi0PeXZhMbT9m5teMl5Q+h6N/9cNUm/ocU=
+-----END CERTIFICATE-----
--- a/share/ca-certs/Makefile.am	Fri Apr 01 13:47:51 2011 +0900
+++ b/share/ca-certs/Makefile.am	Thu Apr 21 20:36:02 2011 +0900
@@ -22,6 +22,7 @@
 
 EXTRA_CERTS = \
 		AOL_Member_CA.pem \
+		DigiCertHighAssuranceCA-3.pem \
 		Microsoft_Internet_Authority.pem \
 		Microsoft_Internet_Authority_2010.pem \
 		Microsoft_Secure_Server_Authority.pem \