changeset 31843:609e3855f36d

propagate from branch 'im.pidgin.pidgin' (head 4fb1347ba91ca1ac8b6f5ad029c1ed0f1b6e60a2) to branch 'im.pidgin.pidgin.next.major' (head 675a312342374865dae98f559ff532b62c47a350)
author Mark Doliner <mark@kingant.net>
date Mon, 18 Apr 2011 06:32:04 +0000
parents 29f4dbdb1d0f (diff) fec20ae8373a (current diff)
children 3448f64d197c
files ChangeLog ChangeLog.API gaim-uninstalled.pc.in gaim.pc.in libpurple/blist.c libpurple/gaim-compat.h libpurple/pounce.c libpurple/protocols/jabber/buddy.c libpurple/purple-2-uninstalled.pc.in libpurple/purple-2.pc.in libpurple/purple-uninstalled.pc.in libpurple/purple.pc.in pidgin/gtkgaim-compat.h pidgin/pidgin-2-uninstalled.pc.in pidgin/pidgin-2.pc.in pidgin/pidgin-uninstalled.pc.in pidgin/pidgin.pc.in
diffstat 21 files changed, 339 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Wed Apr 13 01:37:56 2011 +0000
+++ b/COPYRIGHT	Mon Apr 18 06:32:04 2011 +0000
@@ -576,6 +576,7 @@
 Stephen Whitmore
 Simon Wilkinson
 Dan Willemsen
+Dan Williams
 Justin Williams (Jaywalker)
 Jason Willis
 Alex Willmer
--- a/ChangeLog	Wed Apr 13 01:37:56 2011 +0000
+++ b/ChangeLog	Mon Apr 18 06:32:04 2011 +0000
@@ -8,6 +8,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)
@@ -15,9 +17,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
@@ -25,6 +30,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)
@@ -34,8 +43,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)
@@ -46,6 +65,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	Wed Apr 13 01:37:56 2011 +0000
+++ b/ChangeLog.API	Mon Apr 18 06:32:04 2011 +0000
@@ -18,11 +18,13 @@
 		* 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)
 		* 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
@@ -33,6 +35,8 @@
 	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/libpurple/blist.c	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/blist.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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"
@@ -2179,6 +2180,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/network.c	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/network.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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)
--- a/libpurple/pounce.c	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/pounce.c	Mon Apr 18 06:32:04 2011 +0000
@@ -691,6 +691,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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/pounce.h	Mon Apr 18 06:32:04 2011 +0000
@@ -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/gg/Makefile.am	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/gg/Makefile.am	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/gg/gg.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/gg/lib/libgadu.h	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/irc/irc.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/irc/parse.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Mon Apr 18 06:32:04 2011 +0000
@@ -2241,6 +2241,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);
 
@@ -2253,10 +2263,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/si.c	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/protocols/jabber/si.c	Mon Apr 18 06:32:04 2011 +0000
@@ -1705,7 +1705,7 @@
 	 * See #8477.
 	 */
 	if (filesize_64 > G_MAXSIZE) {
-		/* Shoudl this pop up a warning? */
+		/* Should this pop up a warning? */
 		purple_debug_warning("jabber", "Unable to transfer file (too large)"
 		                     " -- see #8477 for more details.");
 		return;
--- a/libpurple/signals.c	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/signals.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/libpurple/signals.h	Mon Apr 18 06:32:04 2011 +0000
@@ -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/pidgin/gtkconv.c	Wed Apr 13 01:37:56 2011 +0000
+++ b/pidgin/gtkconv.c	Mon Apr 18 06:32:04 2011 +0000
@@ -1792,6 +1792,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) {
@@ -1806,6 +1815,7 @@
 					   event->button, event->time);
 	}
 
+handled:
 	g_free(who);
 	gtk_tree_path_free(path);
 
@@ -2122,7 +2132,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:
@@ -5586,6 +5602,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);
@@ -8003,6 +8028,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	Wed Apr 13 01:37:56 2011 +0000
+++ b/pidgin/gtkdialogs.c	Mon Apr 18 06:32:04 2011 +0000
@@ -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/win32/nsis/pidgin-installer.nsi	Wed Apr 13 01:37:56 2011 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Mon Apr 18 06:32:04 2011 +0000
@@ -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	Wed Apr 13 01:37:56 2011 +0000
+++ b/share/ca-certs/Makefile.am	Mon Apr 18 06:32:04 2011 +0000
@@ -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 \