changeset 27450:c374d57b3215

propagate from branch 'im.pidgin.cpw.rekkanoryo.yahoo.separate_prpls' (head 6e083673febdc8bcc64df4df1500cfb121771d02) to branch 'im.pidgin.pidgin' (head d9a55d5fdb4b18d69b3594642d829cf113f89cca)
author John Bailey <rekkanoryo@rekkanoryo.org>
date Mon, 06 Jul 2009 06:04:34 +0000
parents 0ab6fdeeefd3 (current diff) 14131ba5a07c (diff)
children 09772222714a
files ChangeLog ChangeLog.API libpurple/account.c libpurple/protocols/yahoo/yahoo.c libpurple/protocols/yahoo/yahoo.h
diffstat 43 files changed, 972 insertions(+), 1077 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jul 06 06:04:15 2009 +0000
+++ b/ChangeLog	Mon Jul 06 06:04:34 2009 +0000
@@ -10,8 +10,6 @@
 	  in a group on the buddy list. (Paul Aurich)
 	* Removed the unmaintained and unneeded toc protocol plugin.
 	* Fixed NTLM authentication on big-endian systems.
-	* Use GLib's implementations of SHA1, SHA256, and MD5 when available.
-	  (GLib 2.14 or higher)
 
 	libpurple:
 	* Various memory cleanups when unloading libpurple. (Nick Hebner)
@@ -30,6 +28,7 @@
 	  "off" variable.  Set it to any value to turn it on and unset it to turn
 	  it off.  This will optionally be used to only show less useful debug
 	  information on an as-needed basis.
+	* Add support for receiving handwritten (ink) messages on MSN.
 
 	Gadu-Gadu:
 	* Accounts can specify a server to which to connect.
@@ -78,6 +77,9 @@
 	  client supports it).
 	* Google Talk mail notifications should now work for people for whom they
 	  inexplicably did not.  (Thanks to yukam for determining the reason)
+	* New XMPP and Google Talk accounts require SSL by default.
+	* Display kicks (and the reasons given) in chat rooms when an occupant is
+	  kicked.
 
 	Yahoo!/Yahoo! JAPAN:
 	* P2P file transfers.  (Sulabh Mahajan)
--- a/ChangeLog.API	Mon Jul 06 06:04:15 2009 +0000
+++ b/ChangeLog.API	Mon Jul 06 06:04:34 2009 +0000
@@ -45,6 +45,7 @@
 		* purple_network_get_stun_ip
 		* purple_network_get_turn_ip
 		* purple_network_remove_port_mapping
+		* purple_plugins_get_search_paths
 		* purple_proxy_connect_udp
 		* purple_prpl_get_media_caps
 		* purple_prpl_got_account_actions
@@ -74,6 +75,7 @@
 		  emitted), but this signal was not emitted.
 		* Added a client_type field in the get_ui_info core UI op. See
 		  core.h for details.
+		* Added introspection of signals exposed via the D-Bus API.
 
 		Deprecated:
 		* buddy-added and buddy-removed blist signals
--- a/configure.ac	Mon Jul 06 06:04:15 2009 +0000
+++ b/configure.ac	Mon Jul 06 06:04:34 2009 +0000
@@ -1563,30 +1563,6 @@
 			AC_MSG_RESULT(no)
 		fi
 
-		if test "x$prefix" != "xNONE"; then
-			prefix=`eval echo $prefix`
-			PERL_MM_PARAMS="INSTALLDIRS=vendor PREFIX=$prefix"
-		fi
-
-		AC_ARG_WITH(perl-lib,
-		[AC_HELP_STRING([--with-perl-lib=[site|vendor|DIR]],
-			[specify where to install the Perl libraries for pidgin. Default is site.])],
-		[
-			if test "x$withval" = xsite; then
-				PERL_MM_PARAMS=""
-			elif test "x$withval" = xvendor; then
-				if test -z "`$perlpath -v | grep '5\.0'`"; then
-					PERL_MM_PARAMS="INSTALLDIRS=vendor"
-				else
-					PERL_MM_PARAMS="INSTALLDIRS=vendor PREFIX=`perl -e 'use Config; print $Config{prefix}'`"
-				fi
-			else
-				PERL_MM_PARAMS="INSTALLDIRS=vendor PREFIX=$withval"
-			fi
-		])
-
-		AC_SUBST(PERL_MM_PARAMS)
-
 		AC_MSG_CHECKING(for DynaLoader.a)
 		DYNALOADER_A=`echo $PERL_LDFLAGS | $perlpath -pe 's/^(.* )*([[^ ]]*DynaLoader\.a).*/\2/'`
 
--- a/doc/notify-signals.dox	Mon Jul 06 06:04:15 2009 +0000
+++ b/doc/notify-signals.dox	Mon Jul 06 06:04:34 2009 +0000
@@ -30,7 +30,7 @@
                                       const char *url);
   @endsignalproto
   @signaldesc
-   Emitted before email notification is handed to the UI to display.
+   Emitted before notification of a single email is handed to the UI to display.
   @param subject   Subject of email being notified of.
   @param from      Who the email is from.
   @param to        Who the email is to.
--- a/libpurple/Makefile.am	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/Makefile.am	Mon Jul 06 06:04:34 2009 +0000
@@ -1,5 +1,6 @@
 EXTRA_DIST = \
 		dbus-analyze-functions.py \
+		dbus-analyze-signals.py \
 		dbus-analyze-types.py \
 		marshallers.list \
 		purple-notifications-example \
@@ -169,6 +170,7 @@
 	dbus-bindings.c \
 	dbus-client-binding.c \
 	dbus-client-binding.h \
+	dbus-signals.c \
 	dbus-types.c \
 	dbus-types.h \
 	marshallers.c \
@@ -189,6 +191,10 @@
 purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \
 		$(purple_builtheaders)
 dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported))
+# We should probably make this better
+dbus_signals = $(purple_coresources) \
+	protocols/irc/irc.c \
+	protocols/jabber/libxmpp.c
 
 dbus-types.c: dbus-analyze-types.py $(purple_build_coreheaders)
 	cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DEFINE_TYPE\(%s\) > $@
@@ -199,8 +205,11 @@
 dbus-bindings.c: dbus-analyze-functions.py $(dbus_exported)
 	cat $(dbus_build_exported) | $(PYTHON) $(srcdir)/dbus-analyze-functions.py > $@
 
-dbus-server.$(OBJEXT): dbus-bindings.c dbus-types.c dbus-types.h
-dbus-server.lo: dbus-bindings.c dbus-types.c dbus-types.h
+dbus-signals.c: dbus-analyze-signals.py $(dbus_signals)
+	cat $(dbus_signals) | $(PYTHON) $(srcdir)/dbus-analyze-signals.py > $@
+
+dbus-server.$(OBJEXT): dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
+dbus-server.lo: dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
 $(libpurple_la_OBJECTS): dbus-types.h
 
 # libpurple-client
@@ -240,9 +249,10 @@
 bin_SCRIPTS = purple-remote purple-send purple-send-async purple-url-handler
 
 BUILT_SOURCES = $(purple_builtheaders) \
+	dbus-bindings.c \
+	dbus-signals.c \
 	dbus-types.c \
 	dbus-types.h \
-	dbus-bindings.c \
 	marshallers.c \
 	marshallers.h \
 	purple-client-bindings.c \
--- a/libpurple/account.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/account.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1166,29 +1166,32 @@
 purple_account_connect(PurpleAccount *account)
 {
 	PurplePlugin *prpl;
+	const char *password, *username;
 	PurplePluginProtocolInfo *prpl_info;
-	const char *password;
 
 	g_return_if_fail(account != NULL);
 
-	purple_debug_info("account", "Connecting to account %s\n",
-					purple_account_get_username(account));
-
-	if (!purple_account_get_enabled(account, purple_core_get_ui()))
+	username = purple_account_get_username(account);
+
+	if (!purple_account_get_enabled(account, purple_core_get_ui())) {
+		purple_debug_info("account",
+				  "Account %s not enabled, not connecting.\n",
+				  username);
 		return;
+	}
 
 	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	if (prpl == NULL)
-	{
+	if (prpl == NULL) {
 		gchar *message;
 
-		message = g_strdup_printf(_("Missing protocol plugin for %s"),
-			purple_account_get_username(account));
+		message = g_strdup_printf(_("Missing protocol plugin for %s"), username);
 		purple_notify_error(account, _("Connection Error"), message, NULL);
 		g_free(message);
 		return;
 	}
 
+	purple_debug_info("account", "Connecting to account %s.\n", username);
+
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 	password = purple_account_get_password(account);
 	if ((password == NULL) &&
@@ -2853,9 +2856,9 @@
 		sync_accounts();
 	}
 
+	for (; accounts; accounts = g_list_delete_link(accounts, accounts))
+		purple_account_destroy(accounts->data);
+
 	purple_signals_disconnect_by_handle(handle);
 	purple_signals_unregister_by_instance(handle);
-
-	for (; accounts; accounts = g_list_delete_link(accounts, accounts))
-		purple_account_destroy(accounts->data);
 }
--- a/libpurple/buddyicon.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/buddyicon.h	Mon Jul 06 06:04:34 2009 +0000
@@ -189,8 +189,6 @@
  *                  takes ownership of and will free.
  * @param icon_len  The length of the icon data.
  * @param checksum  A protocol checksum from the prpl or @c NULL.
- *
- * @return The buddy icon set, or NULL if no icon was set.
  */
 void
 purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/dbus-analyze-signals.py	Mon Jul 06 06:04:34 2009 +0000
@@ -0,0 +1,60 @@
+# This program takes a C source as the input and produces the list of
+# all signals registered.
+#
+# Output is:
+#   <signal name="Changed">
+#       <arg name="new_value" type="b"/>
+#   </signal>
+
+import re
+import sys
+
+# List "excluded" contains signals that shouldn't be exported via
+# DBus.  If you remove a signal from this list, please make sure
+# that it does not break "make" with the configure option
+# "--enable-dbus" turned on.
+
+excluded = [\
+    # purple_dbus_signal_emit_purple prevents our "dbus-method-called"
+    # signal from being propagated to dbus.
+	"dbus-method-called",
+    ]
+
+registerregex = re.compile("purple_signal_register[^;]+\"([\w\-]+)\"[^;]+(purple_marshal_\w+)[^;]+;")
+nameregex = re.compile('[-_][a-z]')
+
+print "/* Generated by %s.  Do not edit! */" % sys.argv[0]
+print "const char *dbus_signals = "
+for match in registerregex.finditer(sys.stdin.read()):
+    signal = match.group(1)
+    marshal = match.group(2)
+    if signal in excluded:
+        continue
+
+    signal = nameregex.sub(lambda x:x.group()[1].upper(), '-'+signal)
+    print "\"<signal name='%s'>\\n\""%signal
+
+    args = marshal.split('_')
+    # ['purple', 'marshal', <return type>, '', args...]
+    if len(args) > 4:
+        for arg in args[4:]:
+            if arg == "POINTER":
+                type = 'p'
+            elif arg == "ENUM":
+                type = 'i'
+            elif arg == "INT":
+                type = 'i'
+            elif arg == "UINT":
+                type = 'u'
+            elif arg == "INT64":
+                type = 'x'
+            elif arg == "UINT64":
+                type = 't'
+            elif arg == "BOOLEAN":
+                type = 'b'
+            print "\"<arg type='%s'/>\\n\""%type
+
+    print "\"</signal>\\n\""
+
+print ";"
+
--- a/libpurple/dbus-server.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/dbus-server.c	Mon Jul 06 06:04:34 2009 +0000
@@ -421,6 +421,7 @@
 }
 
 #include "dbus-bindings.c"
+#include "dbus-signals.c"
 
 static gboolean
 purple_dbus_dispatch_cb(DBusConnection *connection,
@@ -489,6 +490,9 @@
 	DBusMessage *reply;
 	GString *str;
 	GList *bindings_list, *node;
+	const char *signals;
+	const char *type;
+	const char *pointer_type;
 
 	str = g_string_sized_new(0x1000); /* TODO: why this size? */
 
@@ -529,6 +533,19 @@
 		}
 	}
 
+	if (sizeof(int) == sizeof(dbus_int32_t))
+		pointer_type = "type='i'";
+	else
+		pointer_type = "type='x'";
+
+	signals = dbus_signals;
+	while ((type = strstr(signals, "type='p'")) != NULL) {
+		g_string_append_len(str, signals, type - signals);
+		g_string_append(str, pointer_type);
+		signals = type + sizeof("type='p'") - 1;
+	}
+	g_string_append(str, signals);
+
 	g_string_append(str, "</interface>\n</node>\n");
 
 	reply = dbus_message_new_method_return(message);
--- a/libpurple/dbus-server.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/dbus-server.h	Mon Jul 06 06:04:34 2009 +0000
@@ -192,9 +192,9 @@
 /**
 
  Macro #DBUS_EXPORT expands to nothing.  It is used to indicate to the
- dbus-analize-functions.py script that the given function should be
+ dbus-analyze-functions.py script that the given function should be
  available to other applications through DBUS.  If
- dbus-analize-functions.py is run without the "--export-only" option,
+ dbus-analyze-functions.py is run without the "--export-only" option,
  this prefix is ignored.
 
  */
@@ -204,7 +204,7 @@
 /*
    Here we include the list of #PURPLE_DBUS_DECLARE_TYPE statements for
    all structs defined in purple.  This file has been generated by the
-   #dbus-analize-types.py script.
+   #dbus-analyze-types.py script.
 */
 
 #include "dbus-types.h"
--- a/libpurple/dnssrv.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/dnssrv.c	Mon Jul 06 06:04:34 2009 +0000
@@ -82,7 +82,7 @@
 	GThread *resolver;
 	char *query;
 	char *error_message;
-	GSList *results;
+	GList *results;
 #else
 	int fd_in, fd_out;
 	pid_t pid;
@@ -134,8 +134,8 @@
  * @param container_ptr The PurpleSrvResponseContainer that was chosen
  *        will be returned here.
  */
-static GList *select_random_response(GList *list,
-		PurpleSrvResponseContainer **container_ptr)
+static GList *
+select_random_response(GList *list, PurpleSrvResponseContainer **container_ptr)
 {
 	GList *cur;
 	size_t runningtotal;
@@ -173,11 +173,11 @@
  * Reorder a GList of PurpleSrvResponses that have the same priority
  * (aka "pref").
  */
-static void srv_reorder(GList *list, int num)
+static void
+srv_reorder(GList *list, int num)
 {
 	int i;
-	GList *cur;
-	GList *container_list = NULL;
+	GList *cur, *container_list = NULL;
 	PurpleSrvResponseContainer *container;
 
 	if (num < 2)
@@ -206,21 +206,22 @@
 }
 
 /**
- * Sorts a GList of PurpleSrvResponse's according to the
+ * Sorts a GList of PurpleSrvResponses according to the
  * algorithm described in RFC 2782.
  *
  * @param response GList of PurpleSrvResponse's
  * @param The original list, resorted
  */
-static GList *purple_srv_sort(GList *list)
+static GList *
+purple_srv_sort(GList *list)
 {
+	int pref, count;
 	GList *cur, *start;
-	int count;
-	int pref;
 
-	if (!list || !list->next)
+	if (!list || !list->next) {
 		/* Nothing to sort */
 		return list;
+	}
 
 	list = g_list_sort(list, responsecompare);
 
@@ -255,11 +256,8 @@
 	PurpleSrvResponse *srvres;
 	PurpleTxtResponse *txtres;
 	queryans answer;
-	int size;
-	int qdcount;
-	int ancount;
-	guchar *end;
-	guchar *cp;
+	int size, qdcount, ancount;
+	guchar *end, *cp;
 	gchar name[256];
 	guint16 type, dlen, pref, weight, port;
 	PurpleSrvInternalQuery query;
@@ -348,8 +346,11 @@
 	while (ret != NULL)
 	{
 		/* TODO: Check return value */
-		if (query.type == T_SRV) write(out, ret->data, sizeof(PurpleSrvResponse));
-		if (query.type == T_TXT) write(out, ret->data, sizeof(PurpleTxtResponse));
+		if (query.type == T_SRV)
+			write(out, ret->data, sizeof(PurpleSrvResponse));
+		if (query.type == T_TXT)
+			write(out, ret->data, sizeof(PurpleTxtResponse));
+
 		g_free(ret->data);
 		ret = g_list_remove(ret, ret->data);
 	}
@@ -410,7 +411,7 @@
 
 					cb(res, size, query_data->extradata);
 				} else if (type == T_TXT) {
-					GSList *responses = NULL;
+					GList *responses = NULL;
 					PurpleTxtResponse *res;
 					PurpleTxtCallback cb = query_data->cb.txt;
 					ssize_t red;
@@ -423,8 +424,8 @@
 									"response: %s\n", g_strerror(errno));
 							size = 0;
 							g_free(res);
-							g_slist_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-							g_slist_free(responses);
+							g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
+							g_list_free(responses);
 							responses = NULL;
 							break;
 						}
@@ -450,24 +451,24 @@
 res_main_thread_cb(gpointer data)
 {
 	PurpleSrvResponse *srvres = NULL;
-	int size = 0;
 	PurpleSrvQueryData *query_data = data;
 	if(query_data->error_message != NULL)
 		purple_debug_error("dnssrv", query_data->error_message);
 	else {
 		if (query_data->type == DNS_TYPE_SRV) {
 			PurpleSrvResponse *srvres_tmp = NULL;
-			GSList *lst = query_data->results;
-
-			size = g_slist_length(lst);
+			GList *lst = query_data->results;
+			int size = g_list_length(lst);
 
 			if(query_data->cb.srv && size > 0)
 				srvres_tmp = srvres = g_new0(PurpleSrvResponse, size);
 			while (lst) {
+				PurpleSrvResponse *lstdata = lst->data;
+				lst = g_list_delete_link(lst, lst);
+
 				if(query_data->cb.srv)
-					memcpy(srvres_tmp++, lst->data, sizeof(PurpleSrvResponse));
-				g_free(lst->data);
-				lst = g_slist_remove(lst, lst->data);
+					memcpy(srvres_tmp++, lstdata, sizeof(PurpleSrvResponse));
+				g_free(lstdata);
 			}
 
 			query_data->results = NULL;
@@ -476,9 +477,9 @@
 
 			if(query_data->cb.srv) query_data->cb.srv(srvres, size, query_data->extradata);
 		} else if (query_data->type == DNS_TYPE_TXT) {
-			GSList *lst = query_data->results;
+			GList *lst = query_data->results;
 
-			purple_debug_info("dnssrv", "found %d TXT entries\n", g_slist_length(lst));
+			purple_debug_info("dnssrv", "found %d TXT entries\n", g_list_length(lst));
 
 			if (query_data->cb.txt) {
 				query_data->results = NULL;
@@ -517,7 +518,7 @@
 	} else {
 		if (type == DNS_TYPE_SRV) {
 			PDNS_RECORD dr_tmp;
-			GSList *lst = NULL;
+			GList *lst = NULL;
 			DNS_SRV_DATA *srv_data;
 			PurpleSrvResponse *srvres;
 
@@ -535,14 +536,14 @@
 				srvres->port = srv_data->wPort;
 				srvres->weight = srv_data->wWeight;
 
-				lst = g_slist_prepend(lst, srvres);
+				lst = g_list_prepend(lst, srvres);
 			}
 
 			MyDnsRecordListFree(dr, DnsFreeRecordList);
 			query_data->results = purple_srv_sort(lst);
 		} else if (type == DNS_TYPE_TXT) {
 			PDNS_RECORD dr_tmp;
-			GSList *lst = NULL;
+			GList *lst = NULL;
 			DNS_TXT_DATA *txt_data;
 			PurpleTxtResponse *txtres;
 
@@ -563,7 +564,7 @@
 					s = g_string_append(s, txt_data->pStringArray[i]);
 				txtres->content = g_string_free(s, FALSE);
 
-				lst = g_slist_append(lst, txtres);
+				lst = g_list_append(lst, txtres);
 			}
 
 			MyDnsRecordListFree(dr, DnsFreeRecordList);
--- a/libpurple/dnssrv.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/dnssrv.h	Mon Jul 06 06:04:34 2009 +0000
@@ -52,10 +52,10 @@
 /**
  * Callback that returns the data retrieved from a DNS TXT lookup.
  *
- * @param responses   A GSList of PurpleTxtResponse objects.
+ * @param responses   A GList of PurpleTxtResponse objects.
  * @param data        The extra data passed to purple_txt_resolve.
  */
-typedef void (*PurpleTxtCallback)(GSList *responses, gpointer data);
+typedef void (*PurpleTxtCallback)(GList *responses, gpointer data);
 
 /**
  * Queries an SRV record.
--- a/libpurple/log.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/log.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1129,7 +1129,7 @@
 				/* set->buddy is always set below */
 				set->normalized_name = g_strdup(purple_normalize(account, name));
 
-				/* Chat for .chat or .system at the end of the name to determine the type. */
+				/* Check for .chat or .system at the end of the name to determine the type. */
 				if (len >= 7) {
 					gchar *tmp = &name[len - 7];
 					if (purple_strequal(tmp, ".system")) {
--- a/libpurple/plugin.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/plugin.c	Mon Jul 06 06:04:34 2009 +0000
@@ -861,6 +861,7 @@
 				}
 
 				g_list_free(loader_info->exts);
+				loader_info->exts = NULL;
 			}
 
 			plugin_loaders = g_list_remove(plugin_loaders, plugin);
@@ -1222,6 +1223,12 @@
 	search_paths = g_list_append(search_paths, g_strdup(path));
 }
 
+GList *
+purple_plugins_get_search_paths()
+{
+	return search_paths;
+}
+
 void
 purple_plugins_unload_all(void)
 {
--- a/libpurple/plugin.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/plugin.h	Mon Jul 06 06:04:34 2009 +0000
@@ -512,6 +512,15 @@
 void purple_plugins_add_search_path(const char *path);
 
 /**
+ * Returns a list of plugin search paths.
+ *
+ * @constreturn A list of searched paths.
+ *
+ * @since 2.6.0
+ */
+GList *purple_plugins_get_search_paths(void);
+
+/**
  * Unloads all loaded plugins.
  */
 void purple_plugins_unload_all(void);
--- a/libpurple/plugins/perl/Makefile.am	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/plugins/perl/Makefile.am	Mon Jul 06 06:04:34 2009 +0000
@@ -99,7 +99,7 @@
 			${LN_S} -f $$srcloc/$$f $$f; \
 		done; \
 	fi
-	@cd common && $(perlpath) Makefile.PL $(PERL_MM_PARAMS)
+	@cd common && $(perlpath) Makefile.PL
 
 common/Makefile.PL: common/Makefile.PL.in $(top_builddir)/config.status
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
@@ -108,7 +108,7 @@
 	@for dir in $(perl_dirs); do \
 		cd $$dir && \
 		if [ ! -f Makefile ]; then \
-			$(perlpath) Makefile.PL $(PERL_MM_PARAMS); \
+			$(perlpath) Makefile.PL; \
 		fi && \
 		($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS) || \
 		 $(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \
@@ -164,6 +164,7 @@
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/libpurple \
 	-I$(top_builddir)/libpurple \
+	-DLIBDIR=\"$(libdir)/purple-$(PURPLE_MAJOR_VERSION)\" \
 	$(DEBUG_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	$(PLUGIN_CFLAGS) \
--- a/libpurple/plugins/perl/common/Makefile.PL.in	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/plugins/perl/common/Makefile.PL.in	Mon Jul 06 06:04:34 2009 +0000
@@ -13,4 +13,16 @@
     'INC'               => '-I. -I@srcdir@ -I@top_srcdir@ -I@top_srcdir@/libpurple @GLIB_CFLAGS@',
     'OBJECT'            => '$(O_FILES)', # link all the C files too
 #    'OPTIMIZE'          => '-g', # For debugging
+    'INSTALLDIRS'          => 'vendor',
+    'INSTALL_BASE'         => '$(prefix)',
+    'INSTALLVENDORARCH'    => '$(libdir)/purple-$(PURPLE_MAJOR_VERSION)/perl',
+    'INSTALLVENDORMAN3DIR' => '$(mandir)/man3',
+    'macro'                => {
+        'prefix'               => '@prefix@',
+        'exec_prefix'          => '@exec_prefix@',
+        'libdir'               => '@libdir@',
+        'mandir'               => '@mandir@',
+        'datarootdir'          => '@datarootdir@',
+        'PURPLE_MAJOR_VERSION' => '@PURPLE_MAJOR_VERSION@',
+    },
 );
--- a/libpurple/plugins/perl/perl.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/plugins/perl/perl.c	Mon Jul 06 06:04:34 2009 +0000
@@ -131,6 +131,7 @@
 #endif
 {
 	char *file = __FILE__;
+	GList *search_paths = purple_plugins_get_search_paths();
 	dXSUB_SYS;
 
 	/* This one allows dynamic loading of perl modules in perl scripts by
@@ -139,6 +140,17 @@
 #ifdef _WIN32
 	newXS("Win32CORE::bootstrap", boot_Win32CORE, file);
 #endif
+
+	while (search_paths != NULL) {
+		gchar *uselib;
+		const gchar *search_path = search_paths->data;
+		search_paths = g_list_next(search_paths);
+
+		uselib = g_strdup_printf("unshift @INC, \"%s%cperl\";",
+		                         search_path, G_DIR_SEPARATOR);
+		eval_pv(uselib, TRUE);
+		g_free(uselib);
+	}
 }
 
 static void
--- a/libpurple/protocols/jabber/buddy.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Mon Jul 06 06:04:34 2009 +0000
@@ -650,16 +650,88 @@
 	g_free(jbi);
 }
 
+static void
+add_jbr_info(JabberBuddyInfo *jbi, const char *resource,
+             JabberBuddyResource *jbr)
+{
+	JabberBuddyInfoResource *jbir;
+	PurpleNotifyUserInfo *user_info;
+
+	jbir = g_hash_table_lookup(jbi->resources, resource);
+	user_info = jbi->user_info;
+
+	if (jbr && jbr->client.name) {
+		char *tmp =
+			g_strdup_printf("%s%s%s", jbr->client.name,
+		                    (jbr->client.version ? " " : ""),
+		                    (jbr->client.version ? jbr->client.version : ""));
+		purple_notify_user_info_prepend_pair(user_info, _("Client"), tmp);
+		g_free(tmp);
+
+		if (jbr->client.os)
+			purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os);
+	}
+
+	if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) {
+		time_t now_t;
+		struct tm *now;
+		char *timestamp;
+		time(&now_t);
+		now_t += jbr->tz_off;
+		now = gmtime(&now_t);
+
+		timestamp =
+			g_strdup_printf("%s %c%02d%02d", purple_time_format(now),
+		                    jbr->tz_off < 0 ? '-' : '+',
+		                    abs(jbr->tz_off / (60*60)),
+		                    abs((jbr->tz_off % (60*60)) / 60));
+		purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp);
+		g_free(timestamp);
+	}
+
+	if (jbir && jbir->idle_seconds > 0) {
+		char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
+		purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle);
+		g_free(idle);
+	}
+
+	if (jbr) {
+		char *purdy = NULL;
+		char *tmp;
+		char priority[12];
+		const char *status_name = jabber_buddy_state_get_name(jbr->state);
+
+		if (jbr->status) {
+			purdy = purple_strdup_withhtml(jbr->status);
+
+			if (purple_strequal(status_name, purdy))
+				status_name = NULL;
+		}
+
+		tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""),
+						((status_name && purdy) ? ": " : ""),
+						(purdy ? purdy : ""));
+		purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp);
+
+		g_snprintf(priority, sizeof(priority), "%d", jbr->priority);
+		purple_notify_user_info_prepend_pair(user_info, _("Priority"), priority);
+
+		g_free(tmp);
+		g_free(purdy);
+	} else {
+		purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown"));
+	}
+}
+
 static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi)
 {
-	char *resource_name, *tmp;
+	char *resource_name;
 	JabberBuddyResource *jbr;
-	JabberBuddyInfoResource *jbir = NULL;
 	GList *resources;
 	PurpleNotifyUserInfo *user_info;
 
 	/* not yet */
-	if(jbi->ids)
+	if (jbi->ids)
 		return;
 
 	user_info = jbi->user_info;
@@ -669,377 +741,24 @@
 	if (purple_notify_user_info_get_entries(user_info))
 		purple_notify_user_info_prepend_section_break(user_info);
 
-	/* Prepend the primary buddy info to user_info so that it goes before the vcard. */
-	if(resource_name) {
+	/* Add the information about the user's resource(s) */
+	if (resource_name) {
 		jbr = jabber_buddy_find_resource(jbi->jb, resource_name);
-		jbir = g_hash_table_lookup(jbi->resources, resource_name);
-		if(jbr && jbr->client.name) {
-			tmp = g_strdup_printf("%s%s%s", jbr->client.name,
-								  (jbr->client.version ? " " : ""),
-								  (jbr->client.version ? jbr->client.version : ""));
-			purple_notify_user_info_add_pair(user_info, _("Client"), tmp);
-			g_free(tmp);
-
-			if(jbr->client.os) {
-				purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os);
-			}
-		}
-		if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) {
-			time_t now_t;
-			struct tm *now;
-			char *timestamp;
-			time(&now_t);
-			now_t += jbr->tz_off;
-			now = gmtime(&now_t);
-
-			timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now),
-			                            jbr->tz_off < 0 ? '-' : '+',
-			                            abs(jbr->tz_off / (60*60)),
-			                            abs((jbr->tz_off % (60*60)) / 60));
-			purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp);
-			g_free(timestamp);
-		}
-		if(jbir) {
-			if(jbir->idle_seconds > 0) {
-				char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
-				purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle);
-				g_free(idle);
-			}
-		}
-		if(jbr) {
-			char *purdy = NULL;
-			const char *status_name = jabber_buddy_state_get_name(jbr->state);
-			if(jbr->status)
-				purdy = purple_strdup_withhtml(jbr->status);
-			if(status_name && purdy && !strcmp(status_name, purdy))
-				status_name = NULL;
-
-			tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""),
-							((status_name && purdy) ? ": " : ""),
-							(purdy ? purdy : ""));
-			purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp);
-			g_free(tmp);
-			g_free(purdy);
-		} else {
-			purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown"));
-		}
-#if 0
-		/* #if 0 this for now; I think this would be far more useful if we limited this to a particular set of features
- 		 * of particular interest (-vv jumps out as one). As it is now, I don't picture people getting all excited: "Oh sweet crap!
- 		 * So-and-so supports 'jabber:x:data' AND 'Collaborative Data Objects'!"
- 		 */
-
-		if(jbr && jbr->caps) {
-			GString *tmp = g_string_new("");
-			GList *iter;
-			for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) {
-				const char *feature = iter->data;
-
-				if(!strcmp(feature, "jabber:iq:last"))
-					feature = _("Last Activity");
-				else if(!strcmp(feature, "http://jabber.org/protocol/disco#info"))
-					feature = _("Service Discovery Info");
-				else if(!strcmp(feature, "http://jabber.org/protocol/disco#items"))
-					feature = _("Service Discovery Items");
-				else if(!strcmp(feature, "http://jabber.org/protocol/address"))
-					feature = _("Extended Stanza Addressing");
-				else if(!strcmp(feature, "http://jabber.org/protocol/muc"))
-					feature = _("Multi-User Chat");
-				else if(!strcmp(feature, "http://jabber.org/protocol/muc#user"))
-					feature = _("Multi-User Chat Extended Presence Information");
-				else if(!strcmp(feature, "http://jabber.org/protocol/ibb"))
-					feature = _("In-Band Bytestreams");
-				else if(!strcmp(feature, "http://jabber.org/protocol/commands"))
-					feature = _("Ad-Hoc Commands");
-				else if(!strcmp(feature, "http://jabber.org/protocol/pubsub"))
-					feature = _("PubSub Service");
-				else if(!strcmp(feature, "http://jabber.org/protocol/bytestreams"))
-					feature = _("SOCKS5 Bytestreams");
-				else if(!strcmp(feature, "jabber:x:oob"))
-					feature = _("Out of Band Data");
-				else if(!strcmp(feature, "http://jabber.org/protocol/xhtml-im"))
-					feature = _("XHTML-IM");
-				else if(!strcmp(feature, "jabber:iq:register"))
-					feature = _("In-Band Registration");
-				else if(!strcmp(feature, "http://jabber.org/protocol/geoloc"))
-					feature = _("User Location");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0084.html"))
-					feature = _("User Avatar");
-				else if(!strcmp(feature, "http://jabber.org/protocol/chatstates"))
-					feature = _("Chat State Notifications");
-				else if(!strcmp(feature, "jabber:iq:version"))
-					feature = _("Software Version");
-				else if(!strcmp(feature, "http://jabber.org/protocol/si"))
-					feature = _("Stream Initiation");
-				else if(!strcmp(feature, "http://jabber.org/protocol/si/profile/file-transfer"))
-					feature = _("File Transfer");
-				else if(!strcmp(feature, "http://jabber.org/protocol/mood"))
-					feature = _("User Mood");
-				else if(!strcmp(feature, "http://jabber.org/protocol/activity"))
-					feature = _("User Activity");
-				else if(!strcmp(feature, "http://jabber.org/protocol/caps"))
-					feature = _("Entity Capabilities");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html"))
-					feature = _("Encrypted Session Negotiations");
-				else if(!strcmp(feature, "http://jabber.org/protocol/tune"))
-					feature = _("User Tune");
-				else if(!strcmp(feature, "http://jabber.org/protocol/rosterx"))
-					feature = _("Roster Item Exchange");
-				else if(!strcmp(feature, "http://jabber.org/protocol/reach"))
-					feature = _("Reachability Address");
-				else if(!strcmp(feature, "http://jabber.org/protocol/profile"))
-					feature = _("User Profile");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0166.html#ns"))
-					feature = _("Jingle");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0167.html#ns"))
-					feature = _("Jingle Audio");
-				else if(!strcmp(feature, "http://jabber.org/protocol/nick"))
-					feature = _("User Nickname");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-udp"))
-					feature = _("Jingle ICE UDP");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-tcp"))
-					feature = _("Jingle ICE TCP");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0177.html#ns"))
-					feature = _("Jingle Raw UDP");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0180.html#ns"))
-					feature = _("Jingle Video");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0181.html#ns"))
-					feature = _("Jingle DTMF");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0184.html#ns"))
-					feature = _("Message Receipts");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0189.html#ns"))
-					feature = _("Public Key Publishing");
-				else if(!strcmp(feature, "http://jabber.org/protocol/chatting"))
-					feature = _("User Chatting");
-				else if(!strcmp(feature, "http://jabber.org/protocol/browsing"))
-					feature = _("User Browsing");
-				else if(!strcmp(feature, "http://jabber.org/protocol/gaming"))
-					feature = _("User Gaming");
-				else if(!strcmp(feature, "http://jabber.org/protocol/viewing"))
-					feature = _("User Viewing");
-				else if(!strcmp(feature, "urn:xmpp:ping"))
-					feature = _("Ping");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns"))
-					feature = _("Stanza Encryption");
-				else if(!strcmp(feature, "urn:xmpp:time"))
-					feature = _("Entity Time");
-				else if(!strcmp(feature, "urn:xmpp:delay"))
-					feature = _("Delayed Delivery");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0204.html#ns"))
-					feature = _("Collaborative Data Objects");
-				else if(!strcmp(feature, "http://jabber.org/protocol/fileshare"))
-					feature = _("File Repository and Sharing");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0215.html#ns"))
-					feature = _("STUN Service Discovery for Jingle");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html#ns"))
-					feature = _("Simplified Encrypted Session Negotiation");
-				else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0219.html#ns"))
-					feature = _("Hop Check");
-				else if(g_str_has_suffix(feature, "+notify"))
-					feature = NULL;
-				if(feature)
-					g_string_append_printf(tmp, "%s<br/>", feature);
-			}
-
-			if(strlen(tmp->str) > 0)
-				purple_notify_user_info_prepend_pair(user_info, _("Capabilities"), tmp->str);
-
-			g_string_free(tmp, TRUE);
-		}
-#endif
+		add_jbr_info(jbi, resource_name, jbr);
 	} else {
-		gboolean multiple_resources = jbi->jb->resources && jbi->jb->resources->next;
-
-		for(resources = jbi->jb->resources; resources; resources = resources->next) {
-			char *purdy = NULL;
-			const char *status_name = NULL;
-
+		for (resources = jbi->jb->resources; resources; resources = resources->next) {
 			jbr = resources->data;
 
 			/* put a section break between resources, this is not needed if
 			 we are at the first, because one was already added for the vcard
 			 section */
-			if (resources != jbi->jb->resources) {
+			if (resources != jbi->jb->resources)
 				purple_notify_user_info_prepend_section_break(user_info);
-			}
-
-			if(jbr->client.name) {
-				tmp = g_strdup_printf("%s%s%s", jbr->client.name,
-									  (jbr->client.version ? " " : ""),
-									  (jbr->client.version ? jbr->client.version : ""));
-				purple_notify_user_info_prepend_pair(user_info,
-												 _("Client"), tmp);
-				g_free(tmp);
-
-				if(jbr->client.os) {
-					purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os);
-				}
-			}
-
-			if (jbr->tz_off != PURPLE_NO_TZ_OFF) {
-				time_t now_t;
-				struct tm *now;
-				char *timestamp;
-				time(&now_t);
-				now_t += jbr->tz_off;
-				now = gmtime(&now_t);
-
-				timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now),
-				                            jbr->tz_off < 0 ? '-' : '+',
-				                            abs(jbr->tz_off / (60*60)),
-				                            abs((jbr->tz_off % (60*60)) / 60));
-				purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp);
-				g_free(timestamp);
-			}
-
-			if(jbr->name && (jbir = g_hash_table_lookup(jbi->resources, jbr->name))) {
-				if(jbir->idle_seconds > 0) {
-					char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
-					purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle);
-					g_free(idle);
-				}
-			}
-
-			status_name = jabber_buddy_state_get_name(jbr->state);
-			if(jbr->status)
-				purdy = purple_strdup_withhtml(jbr->status);
-			if(status_name && purdy && !strcmp(status_name, purdy))
-				status_name = NULL;
-
-			tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""),
-								  ((status_name && purdy) ? ": " : ""),
-								  (purdy ? purdy : ""));
-			purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp);
-			g_free(tmp);
-			g_free(purdy);
-
-			if(multiple_resources) {
-				tmp = g_strdup_printf("%d", jbr->priority);
-				purple_notify_user_info_prepend_pair(user_info, _("Priority"), tmp);
-				g_free(tmp);
-			}
-
-			if(jbr->name)
-				purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name);
-#if 0
-			if(jbr && jbr->caps) {
-				GString *tmp = g_string_new("");
-				GList *iter;
-				for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) {
-					const char *feature = iter->data;
 
-					if(!strcmp(feature, "jabber:iq:last"))
-						feature = _("Last Activity");
-					else if(!strcmp(feature, "http://jabber.org/protocol/disco#info"))
-						feature = _("Service Discovery Info");
-					else if(!strcmp(feature, "http://jabber.org/protocol/disco#items"))
-						feature = _("Service Discovery Items");
-					else if(!strcmp(feature, "http://jabber.org/protocol/address"))
-						feature = _("Extended Stanza Addressing");
-					else if(!strcmp(feature, "http://jabber.org/protocol/muc"))
-						feature = _("Multi-User Chat");
-					else if(!strcmp(feature, "http://jabber.org/protocol/muc#user"))
-						feature = _("Multi-User Chat Extended Presence Information");
-					else if(!strcmp(feature, "http://jabber.org/protocol/ibb"))
-						feature = _("In-Band Bytestreams");
-					else if(!strcmp(feature, "http://jabber.org/protocol/commands"))
-						feature = _("Ad-Hoc Commands");
-					else if(!strcmp(feature, "http://jabber.org/protocol/pubsub"))
-						feature = _("PubSub Service");
-					else if(!strcmp(feature, "http://jabber.org/protocol/bytestreams"))
-						feature = _("SOCKS5 Bytestreams");
-					else if(!strcmp(feature, "jabber:x:oob"))
-						feature = _("Out of Band Data");
-					else if(!strcmp(feature, "http://jabber.org/protocol/xhtml-im"))
-						feature = _("XHTML-IM");
-					else if(!strcmp(feature, "jabber:iq:register"))
-						feature = _("In-Band Registration");
-					else if(!strcmp(feature, "http://jabber.org/protocol/geoloc"))
-						feature = _("User Location");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0084.html"))
-						feature = _("User Avatar");
-					else if(!strcmp(feature, "http://jabber.org/protocol/chatstates"))
-						feature = _("Chat State Notifications");
-					else if(!strcmp(feature, "jabber:iq:version"))
-						feature = _("Software Version");
-					else if(!strcmp(feature, "http://jabber.org/protocol/si"))
-						feature = _("Stream Initiation");
-					else if(!strcmp(feature, "http://jabber.org/protocol/si/profile/file-transfer"))
-						feature = _("File Transfer");
-					else if(!strcmp(feature, "http://jabber.org/protocol/mood"))
-						feature = _("User Mood");
-					else if(!strcmp(feature, "http://jabber.org/protocol/activity"))
-						feature = _("User Activity");
-					else if(!strcmp(feature, "http://jabber.org/protocol/caps"))
-						feature = _("Entity Capabilities");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html"))
-						feature = _("Encrypted Session Negotiations");
-					else if(!strcmp(feature, "http://jabber.org/protocol/tune"))
-						feature = _("User Tune");
-					else if(!strcmp(feature, "http://jabber.org/protocol/rosterx"))
-						feature = _("Roster Item Exchange");
-					else if(!strcmp(feature, "http://jabber.org/protocol/reach"))
-						feature = _("Reachability Address");
-					else if(!strcmp(feature, "http://jabber.org/protocol/profile"))
-						feature = _("User Profile");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0166.html#ns"))
-						feature = _("Jingle");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0167.html#ns"))
-						feature = _("Jingle Audio");
-					else if(!strcmp(feature, "http://jabber.org/protocol/nick"))
-						feature = _("User Nickname");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-udp"))
-						feature = _("Jingle ICE UDP");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0176.html#ns-tcp"))
-						feature = _("Jingle ICE TCP");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0177.html#ns"))
-						feature = _("Jingle Raw UDP");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0180.html#ns"))
-						feature = _("Jingle Video");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0181.html#ns"))
-						feature = _("Jingle DTMF");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0184.html#ns"))
-						feature = _("Message Receipts");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0189.html#ns"))
-						feature = _("Public Key Publishing");
-					else if(!strcmp(feature, "http://jabber.org/protocol/chatting"))
-						feature = _("User Chatting");
-					else if(!strcmp(feature, "http://jabber.org/protocol/browsing"))
-						feature = _("User Browsing");
-					else if(!strcmp(feature, "http://jabber.org/protocol/gaming"))
-						feature = _("User Gaming");
-					else if(!strcmp(feature, "http://jabber.org/protocol/viewing"))
-						feature = _("User Viewing");
-					else if(!strcmp(feature, "urn:xmpp:ping"))
-						feature = _("Ping");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns"))
-						feature = _("Stanza Encryption");
-					else if(!strcmp(feature, "urn:xmpp:time"))
-						feature = _("Entity Time");
-					else if(!strcmp(feature, "urn:xmpp:delay"))
-						feature = _("Delayed Delivery");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0204.html#ns"))
-						feature = _("Collaborative Data Objects");
-					else if(!strcmp(feature, "http://jabber.org/protocol/fileshare"))
-						feature = _("File Repository and Sharing");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0215.html#ns"))
-						feature = _("STUN Service Discovery for Jingle");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0116.html#ns"))
-						feature = _("Simplified Encrypted Session Negotiation");
-					else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0219.html#ns"))
-						feature = _("Hop Check");
-					else if(g_str_has_suffix(feature, "+notify"))
-						feature = NULL;
+			add_jbr_info(jbi, jbr->name, jbr);
 
-					if(feature)
-						g_string_append_printf(tmp, "%s\n", feature);
-				}
-				if(strlen(tmp->str) > 0)
-					purple_notify_user_info_prepend_pair(user_info, _("Capabilities"), tmp->str);
-
-				g_string_free(tmp, TRUE);
-			}
-#endif
+			if (jbr->name)
+				purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name);
 		}
 	}
 
@@ -1047,13 +766,13 @@
 		/* the buddy is offline */
 		gchar *status =
 			g_strdup_printf("%s%s%s",	_("Offline"),
-				jbi->last_message ? ": " : "",
-				jbi->last_message ? jbi->last_message : "");
+			                jbi->last_message ? ": " : "",
+			                jbi->last_message ? jbi->last_message : "");
 		if (jbi->last_seconds > 0) {
 			char *last = purple_str_seconds_to_string(jbi->last_seconds);
 			gchar *message = g_strdup_printf(_("%s ago"), last);
 			purple_notify_user_info_prepend_pair(user_info,
-				_("Logged off"), message);
+				_("Logged Off"), message);
 			g_free(last);
 			g_free(message);
 		}
@@ -1065,7 +784,7 @@
 
 	purple_notify_userinfo(jbi->js->gc, jbi->jid, user_info, NULL, NULL);
 
-	while(jbi->vcard_imgids) {
+	while (jbi->vcard_imgids) {
 		purple_imgstore_unref_by_id(GPOINTER_TO_INT(jbi->vcard_imgids->data));
 		jbi->vcard_imgids = g_slist_delete_link(jbi->vcard_imgids, jbi->vcard_imgids);
 	}
@@ -2101,45 +1820,45 @@
 	return JABBER_BUDDY_STATE_UNKNOWN;
 }
 
-JabberBuddyState jabber_buddy_show_get_state(const char *id) {
-	if(!id)
-		return JABBER_BUDDY_STATE_UNKNOWN;
-	if(!strcmp(id, "available"))
-		return JABBER_BUDDY_STATE_ONLINE;
-	if(!strcmp(id, "chat"))
-		return JABBER_BUDDY_STATE_CHAT;
-	if(!strcmp(id, "away"))
-		return JABBER_BUDDY_STATE_AWAY;
-	if(!strcmp(id, "xa"))
-		return JABBER_BUDDY_STATE_XA;
-	if(!strcmp(id, "dnd"))
-		return JABBER_BUDDY_STATE_DND;
-	if(!strcmp(id, "offline"))
-		return JABBER_BUDDY_STATE_UNAVAILABLE;
-	if(!strcmp(id, "error"))
-		return JABBER_BUDDY_STATE_ERROR;
+const struct {
+	const char *name;
+	JabberBuddyState state;
+} show_state_pairs[] = {
+	{ "available", JABBER_BUDDY_STATE_ONLINE },
+	{ "chat",      JABBER_BUDDY_STATE_CHAT },
+	{ "away",      JABBER_BUDDY_STATE_AWAY },
+	{ "xa",        JABBER_BUDDY_STATE_XA },
+	{ "dnd",       JABBER_BUDDY_STATE_DND },
+	{ "offline",   JABBER_BUDDY_STATE_UNAVAILABLE },
+	{ "error",     JABBER_BUDDY_STATE_ERROR },
+	{ NULL,        JABBER_BUDDY_STATE_UNKNOWN }
+};
 
+JabberBuddyState jabber_buddy_show_get_state(const char *id)
+{
+	int i;
+
+	g_return_val_if_fail(id != NULL, JABBER_BUDDY_STATE_UNKNOWN);
+
+	for (i = 0; show_state_pairs[i].name; ++i)
+		if (g_str_equal(id, show_state_pairs[i].name))
+			return show_state_pairs[i].state;
+
+	purple_debug_warning("jabber", "Invalid value of presence <show/> "
+	                     "attribute: %s\n", id);
 	return JABBER_BUDDY_STATE_UNKNOWN;
 }
 
-const char *jabber_buddy_state_get_show(JabberBuddyState state) {
-	switch(state) {
-		case JABBER_BUDDY_STATE_CHAT:
-			return "chat";
-		case JABBER_BUDDY_STATE_AWAY:
-			return "away";
-		case JABBER_BUDDY_STATE_XA:
-			return "xa";
-		case JABBER_BUDDY_STATE_DND:
-			return "dnd";
-		case JABBER_BUDDY_STATE_ONLINE:
-			return "available";
-		case JABBER_BUDDY_STATE_UNKNOWN:
-		case JABBER_BUDDY_STATE_ERROR:
-			return NULL;
-		case JABBER_BUDDY_STATE_UNAVAILABLE:
-			return "offline";
-	}
+const char *
+jabber_buddy_state_get_show(JabberBuddyState state)
+{
+	int i;
+
+	for (i = 0; show_state_pairs[i].name; ++i)
+		if (state == show_state_pairs[i].state)
+			return show_state_pairs[i].name;
+
+/*	purple_debug_warning("jabber", "Unknown buddy state: %d\n", state); */
 	return NULL;
 }
 
--- a/libpurple/protocols/jabber/jabber.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Jul 06 06:04:34 2009 +0000
@@ -596,7 +596,7 @@
 }
 
 static void
-txt_resolved_cb(GSList *responses, gpointer data)
+txt_resolved_cb(GList *responses, gpointer data)
 {
 	JabberStream *js = data;
 
@@ -624,7 +624,7 @@
 		}
 		g_strfreev(token);
 		purple_txt_response_destroy(resp);
-		responses = g_slist_delete_link(responses, responses);
+		responses = g_list_delete_link(responses, responses);
 	}
 
 	if (js->bosh) {
@@ -634,8 +634,8 @@
 	}
 
 	if (responses) {
-		g_slist_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-		g_slist_free(responses);
+		g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
+		g_list_free(responses);
 	}
 }
 
@@ -908,7 +908,7 @@
 	if (type == JABBER_IQ_RESULT) {
 		if(js->registration) {
 			buf = g_strdup_printf(_("Registration of %s@%s successful"),
-				js->user->node, js->user->domain);
+					js->user->node, js->user->domain);
 			if(account->registration_cb)
 				(account->registration_cb)(account, TRUE, account->registration_cb_user_data);
 		} else {
--- a/libpurple/protocols/jabber/libxmpp.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Jul 06 06:04:34 2009 +0000
@@ -288,7 +288,7 @@
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 
-	option = purple_account_option_bool_new(_("Require SSL/TLS"), "require_tls", FALSE);
+	option = purple_account_option_bool_new(_("Require SSL/TLS"), "require_tls", TRUE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
--- a/libpurple/protocols/jabber/presence.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/jabber/presence.c	Mon Jul 06 06:04:34 2009 +0000
@@ -460,9 +460,6 @@
 {
 	const char *from;
 	const char *type;
-	const char *real_jid = NULL;
-	const char *affiliation = NULL;
-	const char *role = NULL;
 	char *status = NULL;
 	int priority = 0;
 	JabberID *jid;
@@ -476,7 +473,6 @@
 	char *buddy_name;
 	JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN;
 	xmlnode *y;
-	gboolean muc = FALSE;
 	char *avatar_hash = NULL;
 	xmlnode *caps = NULL;
 	int idle = 0;
@@ -486,34 +482,57 @@
 	from = xmlnode_get_attrib(packet, "from");
 	type = xmlnode_get_attrib(packet, "type");
 
-	if(!(jb = jabber_buddy_find(js, from, TRUE)))
-		return;
+	jb = jabber_buddy_find(js, from, TRUE);
+	g_return_if_fail(jb != NULL);
 
 	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin,
 			"jabber-receiving-presence", js->gc, type, from, packet));
 	if (signal_return)
 		return;
 
-	if(!(jid = jabber_id_new(from)))
+	jid = jabber_id_new(from);
+	if (jid == NULL) {
+		purple_debug_error("jabber", "Ignoring presence with malformed 'from' "
+		                   "JID: %s\n", from);
 		return;
+	}
 
 	if(jb->error_msg) {
 		g_free(jb->error_msg);
 		jb->error_msg = NULL;
 	}
 
-	if(type && !strcmp(type, "error")) {
+	if (type == NULL) {
+		xmlnode *show;
+		char *show_data = NULL;
+
+		state = JABBER_BUDDY_STATE_ONLINE;
+
+		show = xmlnode_get_child(packet, "show");
+		if (show) {
+			show_data = xmlnode_get_data(show);
+			if (show_data) {
+				state = jabber_buddy_show_get_state(show_data);
+				g_free(show_data);
+			} else
+				purple_debug_warning("jabber", "<show/> present on presence, "
+				                     "but no contents!\n");
+		}
+	} else if (g_str_equal(type, "error")) {
 		char *msg = jabber_parse_error(js, packet, NULL);
 
 		state = JABBER_BUDDY_STATE_ERROR;
 		jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence"));
-	} else if(type && !strcmp(type, "subscribe")) {
+	} else if (g_str_equal(type, "subscribe")) {
 		struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1);
 		gboolean onlist = FALSE;
-		PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(js->gc), from);
+		PurpleAccount *account;
+		PurpleBuddy *buddy;
 		JabberBuddy *jb = NULL;
 		xmlnode *nick;
 
+		account = purple_connection_get_account(js->gc);
+		buddy = purple_find_buddy(account, from);
 		nick = xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick");
 		if (nick)
 			nickname = xmlnode_get_data(nick);
@@ -528,16 +547,17 @@
 		jap->who = g_strdup(from);
 		jap->js = js;
 
-		purple_account_request_authorization(purple_connection_get_account(js->gc), from, NULL, nickname, NULL, onlist,
-				authorize_add_cb, deny_add_cb, jap);
+		purple_account_request_authorization(account, from, NULL, nickname,
+				NULL, onlist, authorize_add_cb, deny_add_cb, jap);
+
 		g_free(nickname);
 		jabber_id_free(jid);
 		return;
-	} else if(type && !strcmp(type, "subscribed")) {
+	} else if (g_str_equal(type, "subscribed")) {
 		/* we've been allowed to see their presence, but we don't care */
 		jabber_id_free(jid);
 		return;
-	} else if(type && !strcmp(type, "unsubscribe")) {
+	} else if (g_str_equal(type, "unsubscribe")) {
 		/* XXX I'm not sure this is the right way to handle this, it
 		 * might be better to add "unsubscribe" to the presence status
 		 * if lower down, but I'm not sure. */
@@ -546,14 +566,19 @@
 		 * acknowledging this (and the others) at some point. */
 		jabber_id_free(jid);
 		return;
+	} else if (g_str_equal(type, "probe")) {
+		purple_debug_warning("jabber", "Ignoring presence probe\n");
+		jabber_id_free(jid);
+		return;
+	} else if (g_str_equal(type, "unavailable")) {
+		state = JABBER_BUDDY_STATE_UNAVAILABLE;
+	} else if (g_str_equal(type, "unsubscribed")) {
+		state = JABBER_BUDDY_STATE_UNKNOWN;
 	} else {
-		if((y = xmlnode_get_child(packet, "show"))) {
-			char *show = xmlnode_get_data(y);
-			state = jabber_buddy_show_get_state(show);
-			g_free(show);
-		} else {
-			state = JABBER_BUDDY_STATE_ONLINE;
-		}
+		purple_debug_warning("jabber", "Ignoring presence with invalid type "
+		                     "'%s'\n", type);
+		jabber_id_free(jid);
+		return;
 	}
 
 
@@ -588,49 +613,6 @@
 				/* XXX: compare the time.  jabber:x:delay can happen on presence packets that aren't really and truly delayed */
 				delayed = TRUE;
 				stamp = xmlnode_get_attrib(y, "stamp");
-			} else if(!strcmp(xmlns, "http://jabber.org/protocol/muc#user")) {
-				xmlnode *z;
-
-				muc = TRUE;
-				if((z = xmlnode_get_child(y, "status"))) {
-					const char *code = xmlnode_get_attrib(z, "code");
-					if(code && !strcmp(code, "201")) {
-						if((chat = jabber_chat_find(js, jid->node, jid->domain))) {
-							chat->config_dialog_type = PURPLE_REQUEST_ACTION;
-							chat->config_dialog_handle =
-								purple_request_action(js->gc,
-										_("Create New Room"),
-										_("Create New Room"),
-										_("You are creating a new room.  Would"
-											" you like to configure it, or"
-											" accept the default settings?"),
-										/* Default Action */ 1,
-										purple_connection_get_account(js->gc), NULL, chat->conv,
-										chat, 2,
-										_("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure),
-										_("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room));
-						}
-					} else if(code && !strcmp(code, "210")) {
-						/*  server rewrote room-nick */
-						if((chat = jabber_chat_find(js, jid->node, jid->domain))) {
-							g_free(chat->handle);
-							chat->handle = g_strdup(jid->resource);
-						}
-					}
-				}
-				if((z = xmlnode_get_child(y, "item"))) {
-					real_jid = xmlnode_get_attrib(z, "jid");
-					affiliation = xmlnode_get_attrib(z, "affiliation");
-					role = xmlnode_get_attrib(z, "role");
-					if(affiliation != NULL && !strcmp(affiliation, "owner"))
-						flags |= PURPLE_CBFLAGS_FOUNDER;
-					if (role != NULL) {
-						if (!strcmp(role, "moderator"))
-							flags |= PURPLE_CBFLAGS_OP;
-						else if (!strcmp(role, "participant"))
-							flags |= PURPLE_CBFLAGS_VOICE;
-					}
-				}
 			} else if(!strcmp(xmlns, "vcard-temp:x:update")) {
 				xmlnode *photo = xmlnode_get_child(y, "photo");
 				if(photo) {
@@ -687,75 +669,12 @@
 			return;
 		}
 
-
-		if(type && !strcmp(type, "unavailable")) {
-			gboolean nick_change = FALSE;
-
-			/* If the chat nick is invalid, we haven't yet joined, or we've
-			 * already left (it was probably us leaving after we closed the
-			 * chat), we don't care.
-			 */
-			if (!jid->resource || !chat->conv || chat->left) {
-				if (chat->left &&
-						jid->resource && chat->handle && !strcmp(jid->resource, chat->handle))
-					jabber_chat_destroy(chat);
-				jabber_id_free(jid);
-				g_free(status);
-				g_free(avatar_hash);
-				g_free(nickname);
-				return;
-			}
+		if (type == NULL) {
+			xmlnode *x;
+			const char *real_jid = NULL;
+			const char *affiliation = NULL;
+			const char *role = NULL;
 
-			jabber_buddy_remove_resource(jb, jid->resource);
-			if(chat->muc) {
-				xmlnode *x;
-				for(x = xmlnode_get_child(packet, "x"); x; x = xmlnode_get_next_twin(x)) {
-					const char *xmlns, *nick, *code;
-					xmlnode *stat, *item;
-					if(!(xmlns = xmlnode_get_namespace(x)) ||
-							strcmp(xmlns, "http://jabber.org/protocol/muc#user"))
-						continue;
-					if(!(stat = xmlnode_get_child(x, "status")))
-						continue;
-					if(!(code = xmlnode_get_attrib(stat, "code")))
-						continue;
-					if(!strcmp(code, "301")) {
-						/* XXX: we got banned */
-					} else if(!strcmp(code, "303")) {
-						if(!(item = xmlnode_get_child(x, "item")))
-							continue;
-						if(!(nick = xmlnode_get_attrib(item, "nick")))
-							continue;
-						nick_change = TRUE;
-						if(!strcmp(jid->resource, chat->handle)) {
-							g_free(chat->handle);
-							chat->handle = g_strdup(nick);
-						}
-						purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, nick);
-						jabber_chat_remove_handle(chat, jid->resource);
-						break;
-					} else if(!strcmp(code, "307")) {
-						/* XXX: we got kicked */
-					} else if(!strcmp(code, "321")) {
-						/* XXX: removed due to an affiliation change */
-					} else if(!strcmp(code, "322")) {
-						/* XXX: removed because room is now members-only */
-					} else if(!strcmp(code, "332")) {
-						/* XXX: removed due to system shutdown */
-					}
-				}
-			}
-			if(!nick_change) {
-				if(!g_utf8_collate(jid->resource, chat->handle)) {
-					serv_got_chat_left(js->gc, chat->id);
-					jabber_chat_destroy(chat);
-				} else {
-					purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), jid->resource,
-							status);
-					jabber_chat_remove_handle(chat, jid->resource);
-				}
-			}
-		} else {
 			/*
 			 * XEP-0045 mandates the presence to include a resource (which is
 			 * treated as the chat nick). Some non-compliant servers allow
@@ -769,10 +688,61 @@
 				return;
 			}
 
+			x = xmlnode_get_child_with_namespace(packet, "x",
+					"http://jabber.org/protocol/muc#user");
+			if (x) {
+				xmlnode *status_node;
+				xmlnode *item_node;
+
+				status_node = xmlnode_get_child(x, "status");
+				if (status_node) {
+					const char *code = xmlnode_get_attrib(status_node, "code");
+					if (purple_strequal(code, "201")) {
+						if ((chat = jabber_chat_find(js, jid->node, jid->domain))) {
+							chat->config_dialog_type = PURPLE_REQUEST_ACTION;
+							chat->config_dialog_handle =
+								purple_request_action(js->gc,
+										_("Create New Room"),
+										_("Create New Room"),
+										_("You are creating a new room.  Would"
+											" you like to configure it, or"
+											" accept the default settings?"),
+										/* Default Action */ 1,
+										purple_connection_get_account(js->gc), NULL, chat->conv,
+										chat, 2,
+										_("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure),
+										_("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room));
+						}
+					} else if (purple_strequal(code, "210")) {
+						/* server rewrote room-nick */
+						if((chat = jabber_chat_find(js, jid->node, jid->domain))) {
+							g_free(chat->handle);
+							chat->handle = g_strdup(jid->resource);
+						}
+					}
+				}
+
+				item_node = xmlnode_get_child(x, "item");
+				if (item_node) {
+					real_jid    = xmlnode_get_attrib(item_node, "jid");
+					affiliation = xmlnode_get_attrib(item_node, "affiliation");
+					role        = xmlnode_get_attrib(item_node, "role");
+
+					if (purple_strequal(affiliation, "owner"))
+						flags |= PURPLE_CBFLAGS_FOUNDER;
+					if (role) {
+						if (g_str_equal(role, "moderator"))
+							flags |= PURPLE_CBFLAGS_OP;
+						else if (g_str_equal(role, "participant"))
+							flags |= PURPLE_CBFLAGS_VOICE;
+					}
+				}
+			}
+
 			if(!chat->conv) {
 				char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain);
 				chat->id = i++;
-				chat->muc = muc;
+				chat->muc = (x != NULL);
 				chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid);
 				purple_conv_chat_set_nick(PURPLE_CONV_CHAT(chat->conv), chat->handle);
 
@@ -791,6 +761,133 @@
 			else
 				purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(chat->conv), jid->resource,
 						flags);
+		} else if (g_str_equal(type, "unavailable")) {
+			gboolean nick_change = FALSE;
+			gboolean kick = FALSE;
+			gboolean is_our_resource = FALSE; /* Is the presence about us? */
+
+			/* If the chat nick is invalid, we haven't yet joined, or we've
+			 * already left (it was probably us leaving after we closed the
+			 * chat), we don't care.
+			 */
+			if (!jid->resource || !chat->conv || chat->left) {
+				if (chat->left &&
+						jid->resource && chat->handle && !strcmp(jid->resource, chat->handle))
+					jabber_chat_destroy(chat);
+				jabber_id_free(jid);
+				g_free(status);
+				g_free(avatar_hash);
+				g_free(nickname);
+				return;
+			}
+
+			is_our_resource = (0 == g_utf8_collate(jid->resource, chat->handle));
+
+			jabber_buddy_remove_resource(jb, jid->resource);
+			if(chat->muc) {
+				xmlnode *x;
+				for(x = xmlnode_get_child(packet, "x"); x; x = xmlnode_get_next_twin(x)) {
+					const char *xmlns, *nick, *code;
+					xmlnode *stat, *item;
+					if(!(xmlns = xmlnode_get_namespace(x)) ||
+							strcmp(xmlns, "http://jabber.org/protocol/muc#user"))
+						continue;
+					if(!(stat = xmlnode_get_child(x, "status")))
+						continue;
+					if(!(code = xmlnode_get_attrib(stat, "code")))
+						continue;
+
+					item = xmlnode_get_child(x, "item");
+
+					if(!strcmp(code, "301")) {
+						/* XXX: we got banned */
+					} else if(!strcmp(code, "303")) {
+						if (!item)
+							continue;
+						if(!(nick = xmlnode_get_attrib(item, "nick")))
+							continue;
+						nick_change = TRUE;
+						if(!strcmp(jid->resource, chat->handle)) {
+							g_free(chat->handle);
+							chat->handle = g_strdup(nick);
+						}
+						purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, nick);
+						jabber_chat_remove_handle(chat, jid->resource);
+						break;
+					} else if(!strcmp(code, "307")) {
+						/* Someone was kicked from the room */
+						xmlnode *reason = NULL, *actor = NULL;
+						const char *actor_name = NULL;
+						char *reason_text = NULL;
+						char *tmp;
+
+						kick = TRUE;
+
+						if (item) {
+							reason = xmlnode_get_child(item, "reason");
+							actor = xmlnode_get_child(item, "actor");
+
+							if (reason != NULL)
+								reason_text = xmlnode_get_data(reason);
+							if (actor != NULL)
+								actor_name = xmlnode_get_attrib(actor, "jid");
+						}
+
+						if (reason_text == NULL)
+							reason_text = g_strdup(_("No reason"));
+
+						if (is_our_resource) {
+							if (actor_name != NULL)
+								tmp = g_strdup_printf(_("You have been kicked by %s: (%s)"),
+										actor_name, reason_text);
+							else
+								tmp = g_strdup_printf(_("You have been kicked: (%s)"),
+										reason_text);
+						} else {
+							if (actor_name != NULL)
+								tmp = g_strdup_printf(_("Kicked by %s (%s)"),
+										actor_name, reason_text);
+							else
+								tmp = g_strdup_printf(_("Kicked (%s)"),
+										reason_text);
+						}
+
+						g_free(reason_text);
+						g_free(status);
+						status = tmp;
+					} else if(!strcmp(code, "321")) {
+						/* XXX: removed due to an affiliation change */
+					} else if(!strcmp(code, "322")) {
+						/* XXX: removed because room is now members-only */
+					} else if(!strcmp(code, "332")) {
+						/* XXX: removed due to system shutdown */
+					}
+				}
+			}
+			if(!nick_change) {
+				if (is_our_resource) {
+					if (kick)
+						purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), jid->resource,
+								status, PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+					serv_got_chat_left(js->gc, chat->id);
+					jabber_chat_destroy(chat);
+				} else {
+					purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), jid->resource,
+							status);
+					jabber_chat_remove_handle(chat, jid->resource);
+				}
+			}
+		} else {
+			/* A type that isn't available or unavailable */
+			purple_debug_error("jabber", "MUC presence with bad type: %s\n",
+			                   type);
+
+			jabber_id_free(jid);
+			g_free(avatar_hash);
+			g_free(status);
+			g_free(nickname);
+			g_return_if_reached();
 		}
 	} else {
 		buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "",
@@ -837,8 +934,8 @@
 		}
 
 		if(state == JABBER_BUDDY_STATE_ERROR ||
-				(type && (!strcmp(type, "unavailable") ||
-						  !strcmp(type, "unsubscribed")))) {
+				(type && (g_str_equal(type, "unavailable") ||
+				          g_str_equal(type, "unsubscribed")))) {
 			PurpleConversation *conv;
 
 			jabber_buddy_remove_resource(jb, jid->resource);
@@ -867,7 +964,7 @@
 		g_free(buddy_name);
 	}
 
-	if (caps && (!type || g_str_equal(type, "available"))) {
+	if (caps && !type) {
 		/* handle Entity Capabilities (XEP-0115) */
 		const char *node = xmlnode_get_attrib(caps, "node");
 		const char *ver  = xmlnode_get_attrib(caps, "ver");
--- a/libpurple/protocols/msn/msg.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/msn/msg.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1048,3 +1048,14 @@
 	g_hash_table_destroy(body);
 }
 
+/* Only called from chats. Handwritten messages for IMs come as a SLP message */
+void
+msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+{
+	const char *body;
+	size_t body_len;
+
+	body = msn_message_get_bin_data(msg, &body_len);
+	msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
+}
+
--- a/libpurple/protocols/msn/msg.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/msn/msg.h	Mon Jul 06 06:04:34 2009 +0000
@@ -345,4 +345,6 @@
 
 void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
+void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+
 #endif /* _MSN_MSG_H_ */
--- a/libpurple/protocols/msn/msn.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/msn/msn.h	Mon Jul 06 06:04:34 2009 +0000
@@ -138,7 +138,7 @@
 } MsnClientVerId;
 
 #define MSN_CLIENT_ID_VERSION      MSN_CLIENT_VER_7_0
-#define MSN_CLIENT_ID_CAPABILITIES MSN_CLIENT_CAP_PACKET
+#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF)
 
 #define MSN_CLIENT_ID \
 	((MSN_CLIENT_ID_VERSION    << 24) | \
--- a/libpurple/protocols/msn/slpcall.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Mon Jul 06 06:04:34 2009 +0000
@@ -210,8 +210,51 @@
 	{
 		char *body_str;
 
-		body_str = g_strndup((const char *)body, body_len);
-		slpcall = msn_slp_sip_recv(slplink, body_str);
+		if (slpmsg->session_id == 64)
+		{
+			/* This is for handwritten messages (Ink) */
+			GError *error;
+			glong items_read, items_written;
+
+			body_str = g_utf16_to_utf8((gunichar2 *)body, body_len / 2,
+			                           &items_read, &items_written, &error);
+			body_len -= items_read * 2 + 2;
+			body += items_read * 2 + 2;
+			if (body_str == NULL
+			 || body_len <= 0
+			 || strstr(body_str, "image/gif") == NULL)
+			{
+				if (error != NULL)
+					purple_debug_error("msn",
+					                   "Unable to convert Ink header from UTF-16 to UTF-8: %s\n",
+					                   error->message);
+				else
+					purple_debug_error("msn",
+					                   "Received Ink in unknown format\n");
+				g_free(body_str);
+				return NULL;
+			}
+			g_free(body_str);
+
+			body_str = g_utf16_to_utf8((gunichar2 *)body, body_len / 2,
+			                           &items_read, &items_written, &error);
+			if (!body_str)
+			{
+				purple_debug_error("msn",
+				                   "Unable to convert Ink body from UTF-16 to UTF-8: %s\n",
+				                   error->message);
+				return NULL;
+			}
+
+			msn_switchboard_show_ink(slpmsg->slplink->swboard,
+			                         slplink->remote_user,
+			                         body_str);
+		}
+		else
+		{
+			body_str = g_strndup((const char *)body, body_len);
+			slpcall = msn_slp_sip_recv(slplink, body_str);
+		}
 		g_free(body_str);
 	}
 	else if (slpmsg->flags == 0x20 ||
--- a/libpurple/protocols/msn/switchboard.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Mon Jul 06 06:04:34 2009 +0000
@@ -905,6 +905,47 @@
 #endif
 }
 
+void
+msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+                         const char *data)
+{
+	PurpleConnection *gc;
+	guchar *image_data;
+	size_t image_len;
+	int imgid;
+	char *image_msg;
+
+	if (!purple_str_has_prefix(data, "base64:"))
+	{
+		purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n");
+		return;
+	}
+
+	gc = purple_account_get_connection(swboard->session->account);
+
+	data += sizeof("base64:") - 1;
+	image_data = purple_base64_decode(data, &image_len);
+	if (!image_data || !image_len) 
+	{
+		purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n");
+		return;
+	}
+
+	imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
+	image_msg = g_strdup_printf("<IMG ID=%d/>", imgid);
+
+	if (swboard->current_users > 1 ||
+		((swboard->conv != NULL) &&
+		 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+		serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg,
+						 time(NULL));
+	else
+		serv_got_im(gc, passport, image_msg, 0, time(NULL));
+
+	purple_imgstore_unref_by_id(imgid);
+	g_free(image_msg);
+}
+
 /**************************************************************************
  * Connect stuff
  **************************************************************************/
@@ -1239,6 +1280,8 @@
 						   msn_datacast_msg);
 	msn_table_add_msg_type(cbs_table, "text/x-msmsgsinvite",
 						   msn_invite_msg);
+	msn_table_add_msg_type(cbs_table, "image/gif",
+						   msn_handwritten_msg);
 }
 
 void
--- a/libpurple/protocols/msn/switchboard.h	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.h	Mon Jul 06 06:04:34 2009 +0000
@@ -280,4 +280,14 @@
  */
 void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
+/**
+ * Shows an ink message from this switchboard.
+ *
+ * @param swboard  The switchboard.
+ * @param passport The user that sent the ink.
+ * @param data     The ink data.
+ */
+void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+                              const char *data);
+
 #endif /* _MSN_SWITCHBOARD_H_ */
--- a/libpurple/protocols/myspace/message.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/myspace/message.c	Mon Jul 06 06:04:34 2009 +0000
@@ -19,9 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
-#include "internal.h"
+#include "myspace.h"
 #include "message.h"
-#include "myspace.h"
 
 static void msim_msg_debug_string_element(gpointer data, gpointer user_data);
 
--- a/libpurple/protocols/oscar/oscar.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1548,9 +1548,8 @@
 	 * authenticate.
 	 *
 	 * AIM 5.9 and lower use an MD5-based login procedure called "BUCP".
-	 * Note that some people were unable to log in to ICQ using the MD5
-	 * method, and so ICQ, when not using clientLogin, is still using a
-	 * very insecure XOR-based login scheme.
+	 * 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)) {
 		send_client_login(od, purple_account_get_username(account));
--- a/libpurple/prpl.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/prpl.c	Mon Jul 06 06:04:34 2009 +0000
@@ -282,7 +282,8 @@
 
 	g_slist_free(list);
 
-	/* we get to re-use the last status we found */
+	/* The buddy is no longer online, they are therefore by definition not
+	 * still typing to us. */
 	if (!purple_status_is_online(status))
 		serv_got_typing_stopped(purple_account_get_connection(account), name);
 }
--- a/libpurple/purple-remote	Mon Jul 06 06:04:15 2009 +0000
+++ b/libpurple/purple-remote	Mon Jul 06 06:04:34 2009 +0000
@@ -161,7 +161,6 @@
                 purple.PurpleSavedstatusSetSubstatus(current, account, type, message)
                 purple.PurpleSavedstatusActivateForAccount(current, account)
         else:
-            accounts = purple.PurpleAccountsGetAllActive()
             saved = purple.PurpleSavedstatusNew("", status_type)
             purple.PurpleSavedstatusSetMessage(saved, message)
             purple.PurpleSavedstatusActivate(saved)
--- a/pidgin/gtkaccount.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/gtkaccount.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1990,8 +1990,9 @@
 				/* This is for when set_account() is called for a single account */
 				const char *path;
 				path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon");
-				if (path != NULL && *path != '\0')
+				if ((path != NULL) && (*path != '\0')) {
 					img = purple_imgstore_new_from_file(path);
+				}
 			}
 		} else {
 			img = purple_buddy_icons_find_account_icon(account);
--- a/pidgin/gtkblist.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/gtkblist.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1575,7 +1575,7 @@
 
 	if (!(purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)) {
 		show_offline = purple_blist_node_get_bool(node, "show_offline");
-		pidgin_new_item_from_stock(menu, show_offline ? _("Hide when offline") : _("Show when offline"),
+		pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"),
 				NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
 	}
 
@@ -1759,7 +1759,7 @@
 				 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL);
 	if (!(purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)) {
 		gboolean show_offline = purple_blist_node_get_bool(node, "show_offline");
-		pidgin_new_item_from_stock(menu, show_offline ? _("Hide when offline") : _("Show when offline"),
+		pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"),
 				NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
 	}
 
@@ -6300,7 +6300,7 @@
 	selected = (gnode == selected_node);
 
 	if (!expanded) {
-		g_snprintf(group_count, sizeof(group_count), " (%d/%d)",
+		g_snprintf(group_count, sizeof(group_count), "%d/%d",
 		           purple_blist_get_group_online_count(group),
 		           purple_blist_get_group_size(group, FALSE));
 	}
@@ -6319,11 +6319,18 @@
 
 	esc = g_markup_escape_text(group->name, -1);
 	if (text_color) {
-		mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s</span>",
-							text_color, text_font, esc ? esc : "", group_count);
+		mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s%s%s</span>",
+		                       text_color, text_font,
+		                       esc ? esc : "",
+		                       !expanded ? " <span font_weight='light'>(</span>" : "",
+		                       group_count,
+		                       !expanded ? "<span font_weight='light'>)</span>" : "");
 	} else {
-		mark = g_strdup_printf("<span font_desc='%s'><b>%s</b>%s</span>",
-							text_font, esc ? esc : "", group_count);
+		mark = g_strdup_printf("<span font_desc='%s'><b>%s</b>%s%s%s</span>",
+		                       text_font, esc ? esc : "",
+		                       !expanded ? " <span font_weight='light'>(</span>" : "",
+		                       group_count,
+		                       !expanded ? "<span font_weight='light'>)</span>" : "");
 	}
 
 	g_free(esc);
--- a/pidgin/gtkconv.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/gtkconv.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1770,7 +1770,7 @@
 			g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
 	}
 
-	button = pidgin_new_item_from_stock(menu, _("Last said"), GTK_STOCK_INDEX,
+	button = pidgin_new_item_from_stock(menu, _("Last Said"), GTK_STOCK_INDEX,
 						G_CALLBACK(menu_last_said_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL);
 	g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
 	if (!get_mark_for_user(PIDGIN_CONVERSATION(conv), who))
@@ -8196,15 +8196,11 @@
 static void
 build_warn_close_dialog(PidginWindow *gtkwin)
 {
-	GtkWidget *label;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *img;
+	GtkWidget *label, *vbox, *hbox, *img;
 
 	g_return_if_fail(warn_close_dialog == NULL);
 
-
-	warn_close_dialog = gtk_dialog_new_with_buttons(
-							_("Confirm close"),
+	warn_close_dialog = gtk_dialog_new_with_buttons(_("Confirm close"),
 							GTK_WINDOW(gtkwin->window), GTK_DIALOG_MODAL,
 							GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 							GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL);
--- a/pidgin/gtkprefs.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/gtkprefs.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1457,7 +1457,7 @@
 	gtk_size_group_add_widget(sg, label);
 	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
 
-	vbox = pidgin_make_frame(ret, _("Conversation Window Hiding"));
+	vbox = pidgin_make_frame(ret, _("Conversation Window"));
 	label = pidgin_prefs_dropdown(vbox, _("_Hide new IM conversations:"),
 					PURPLE_PREF_STRING, PIDGIN_PREFS_ROOT "/conversations/im/hide_new",
 					_("Never"), "never",
@@ -1467,6 +1467,9 @@
 	gtk_size_group_add_widget(sg, label);
 	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
 
+#ifdef _WIN32
+	pidgin_prefs_checkbox(_("Minimi_ze new conversation windows"), PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", vbox);
+#endif
 
 	/* All the tab options! */
 	vbox = pidgin_make_frame(ret, _("Tabs"));
@@ -1575,8 +1578,6 @@
 
 #ifdef _WIN32
 	pidgin_prefs_checkbox(_("F_lash window when IMs are received"), PIDGIN_PREFS_ROOT "/win32/blink_im", vbox);
-
-	pidgin_prefs_checkbox(_("Minimi_ze new conversation windows"), PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", vbox);
 #endif
 
 	pidgin_prefs_labeled_spin_button(vbox,
@@ -1584,7 +1585,6 @@
 		PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines",
 		1, 8, NULL);
 
-
 #if GTK_CHECK_VERSION(2,4,0)
 	vbox = pidgin_make_frame(ret, _("Font"));
 	if (purple_running_gnome())
@@ -1593,7 +1593,11 @@
 		fontpref = pidgin_prefs_checkbox(_("Use font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox);
 
 	font_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font");
-	font_button = gtk_font_button_new_with_font(font_name ? font_name : NULL);
+	if ((font_name == NULL) || (*font_name == '\0')) {
+		font_button = gtk_font_button_new();
+	} else {
+		font_button = gtk_font_button_new_with_font(font_name);
+	}
 
 	gtk_font_button_set_show_style(GTK_FONT_BUTTON(font_button), TRUE);
 	hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Conversation _font:"), NULL, font_button, FALSE, NULL);
@@ -2777,9 +2781,7 @@
 }
 
 static int
-prefs_notebook_add_page(const char *text,
-  		                GtkWidget *page,
-                        int ind)
+prefs_notebook_add_page(const char *text, GtkWidget *page, int ind)
 {
 #if GTK_CHECK_VERSION(2,4,0)
 	return gtk_notebook_append_page(GTK_NOTEBOOK(prefsnotebook), page, gtk_label_new(text));
--- a/pidgin/gtksmiley.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/gtksmiley.c	Mon Jul 06 06:04:34 2009 +0000
@@ -74,6 +74,7 @@
 static void
 pidgin_smiley_destroy(PidginSmiley *smiley)
 {
+	g_object_set_data(G_OBJECT(smiley->smiley), "edit-dialog", NULL);
 	gtk_widget_destroy(smiley->parent);
 	g_free(smiley->filename);
 	if (smiley->custom_pixbuf)
@@ -402,6 +403,7 @@
 			smiley ? GTK_STOCK_SAVE : GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
 			NULL);
 	s->parent = window;
+	g_object_set_data(G_OBJECT(smiley), "edit-dialog", window);
 
 	gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER);
 
@@ -650,8 +652,12 @@
 smiley_edit_iter(SmileyManager *dialog, GtkTreeIter *iter)
 {
 	PurpleSmiley *smiley = NULL;
+	GtkWidget *window = NULL;
 	gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), iter, SMILEY, &smiley, -1);
-	pidgin_smiley_edit(gtk_widget_get_toplevel(GTK_WIDGET(dialog->treeview)), smiley);
+	if ((window = g_object_get_data(G_OBJECT(smiley), "edit-dialog")) != NULL)
+		gtk_window_present(GTK_WINDOW(window));
+	else
+		pidgin_smiley_edit(gtk_widget_get_toplevel(GTK_WIDGET(dialog->treeview)), smiley);
 	g_object_unref(G_OBJECT(smiley));
 }
 
--- a/pidgin/plugins/disco/xmppdisco.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/plugins/disco/xmppdisco.c	Mon Jul 06 06:04:34 2009 +0000
@@ -500,6 +500,10 @@
 			++list->fetch_count;
 			pidgin_disco_list_ref(list);
 		}
+		else {
+			pidgin_disco_list_set_in_progress(list, FALSE);
+			g_free(cb_data);
+		}
 	}
 	else {
 		error = xmlnode_get_child(iq, "error");
--- a/pidgin/plugins/perl/Makefile.am	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/plugins/perl/Makefile.am	Mon Jul 06 06:04:34 2009 +0000
@@ -44,7 +44,7 @@
 			${LN_S} -f $$srcloc/$$f $$f; \
 		done; \
 	fi
-	@cd common && $(perlpath) Makefile.PL $(PERL_MM_PARAMS)
+	@cd common && $(perlpath) Makefile.PL
 
 common/Makefile.PL: common/Makefile.PL.in $(top_builddir)/config.status
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
@@ -53,7 +53,7 @@
 	@for dir in $(perl_dirs); do \
 		cd $$dir && \
 		if [ ! -f Makefile ]; then \
-			$(perlpath) Makefile.PL $(PERL_MM_PARAMS); \
+			$(perlpath) Makefile.PL; \
 		fi && \
 		($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS) || \
 		$(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \
--- a/pidgin/plugins/perl/common/Makefile.PL.in	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/plugins/perl/common/Makefile.PL.in	Mon Jul 06 06:04:34 2009 +0000
@@ -13,4 +13,15 @@
     'OBJECT'        => '$(O_FILES)', # link all the C files too
     'TYPEMAPS'      => ["@top_srcdir@/libpurple/plugins/perl/common/typemap"],
 #    'OPTIMIZE'      => '-g', # For debugging.
+    'INSTALLDIRS'          => 'vendor',
+    'INSTALL_BASE'         => '$(prefix)',
+    'INSTALLVENDORARCH'    => '$(libdir)/pidgin/perl',
+    'INSTALLVENDORMAN3DIR' => '$(mandir)/man3',
+    'macro'                => {
+        'prefix'      => '@prefix@',
+        'exec_prefix' => '@exec_prefix@',
+        'libdir'      => '@libdir@',
+        'mandir'      => '@mandir@',
+        'datarootdir' => '@datarootdir@',
+    },
 );
--- a/pidgin/plugins/pidginrc.c	Mon Jul 06 06:04:15 2009 +0000
+++ b/pidgin/plugins/pidginrc.c	Mon Jul 06 06:04:34 2009 +0000
@@ -1,7 +1,13 @@
 /**
- * @file purplerc.c Purple gtk resource control plugin.
+ * @file pidginrc.c Pidgin GTK+ resource control plugin.
+ * @ingroup pidgin
+ */
+
+/* pidgin
  *
- * Copyright (C) 2005 Etan Reisner <deryni@eden.rutgers.edu>
+ * Pidgin 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
@@ -612,7 +618,7 @@
 	DISPLAY_VERSION,
 	N_("Provides access to commonly used gtkrc settings."),
 	N_("Provides access to commonly used gtkrc settings."),
-	"Etan Reisner <deryni@eden.rutgers.edu>",
+	"Etan Reisner <deryni@pidgin.im>",
 	PURPLE_WEBSITE,
 	purplerc_plugin_load,
 	purplerc_plugin_unload,
--- a/po/ca.po	Mon Jul 06 06:04:15 2009 +0000
+++ b/po/ca.po	Mon Jul 06 06:04:34 2009 +0000
@@ -33,8 +33,8 @@
 msgstr ""
 "Project-Id-Version: Pidgin\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-07-04 10:23+0200\n"
-"PO-Revision-Date: 2009-07-04 10:30+0200\n"
+"POT-Creation-Date: 2009-07-06 00:17+0200\n"
+"PO-Revision-Date: 2009-07-06 00:19+0200\n"
 "Last-Translator: Josep Puigdemont i Casamajó <josep.puigdemont@gmail.com>\n"
 "Language-Team: Catalan <tradgnome@softcatala.net>\n"
 "MIME-Version: 1.0\n"
@@ -3881,172 +3881,6 @@
 msgid "Local Time"
 msgstr "Hora local"
 
-msgid "Last Activity"
-msgstr "Darrera activitat"
-
-msgid "Service Discovery Info"
-msgstr "Informació del servei de descoberta"
-
-msgid "Service Discovery Items"
-msgstr "Elements del servei de descoberta"
-
-# http://xmpp.org/extensions/xep-0033.html
-msgid "Extended Stanza Addressing"
-msgstr "Bloc d'adreçament estès"
-
-msgid "Multi-User Chat"
-msgstr "Xat multi-usuari"
-
-msgid "Multi-User Chat Extended Presence Information"
-msgstr "Informació de presència estesa per a xats multi-usuari"
-
-msgid "In-Band Bytestreams"
-msgstr ""
-
-msgid "Ad-Hoc Commands"
-msgstr "Ordres Ad-Hoc"
-
-msgid "PubSub Service"
-msgstr "Servei PubSub"
-
-msgid "SOCKS5 Bytestreams"
-msgstr "Flux de bits SOCK5"
-
-msgid "Out of Band Data"
-msgstr ""
-
-msgid "XHTML-IM"
-msgstr "XHTML-IM"
-
-msgid "In-Band Registration"
-msgstr ""
-
-msgid "User Location"
-msgstr "Ubicació de l'usuari"
-
-msgid "User Avatar"
-msgstr "Avatar de l'usuari"
-
-msgid "Chat State Notifications"
-msgstr "Notificacions de l'estat del xat"
-
-msgid "Software Version"
-msgstr "Versió del programari"
-
-msgid "Stream Initiation"
-msgstr "Iniciació del flux"
-
-msgid "File Transfer"
-msgstr "Transferència de fitxers"
-
-msgid "User Mood"
-msgstr "Estat d'ànim de l'usuari"
-
-msgid "User Activity"
-msgstr "Activitat de l'usuari"
-
-msgid "Entity Capabilities"
-msgstr "Capacitats de l'entitat"
-
-msgid "Encrypted Session Negotiations"
-msgstr "Negociacions de la sessió xifrada"
-
-# Pot ser també música, cançó... (josep)
-# Vegeu: http://xmpp.org/extensions/xep-0118.html
-msgid "User Tune"
-msgstr "Melodia de l'usuari"
-
-# Nota: "Roster" en XMPP és la llista de contactes (josep)
-msgid "Roster Item Exchange"
-msgstr "Intercanvi d'element de la llista de contactes"
-
-# Vegeu: http://xmpp.org/extensions/xep-0152.html (josep)
-# Nota: codi mort
-msgid "Reachability Address"
-msgstr "Adreça de localització"
-
-msgid "User Profile"
-msgstr "Perfil de l'usuari"
-
-# Nota: Jingle és una extensió d'XMPP i ho considerem nom propi (josep)
-# http://www.xmpp.org/extensions/xep-0166.html
-msgid "Jingle"
-msgstr "Jingle"
-
-# FIXME
-msgid "Jingle Audio"
-msgstr "Àudio amb Jingle"
-
-msgid "User Nickname"
-msgstr "Sobrenom de l'usuari"
-
-msgid "Jingle ICE UDP"
-msgstr "Jingle ICE UDP"
-
-msgid "Jingle ICE TCP"
-msgstr "Jingle ICE TCP"
-
-msgid "Jingle Raw UDP"
-msgstr "Jingle Raw UDP"
-
-msgid "Jingle Video"
-msgstr "Vídeo amb Jingle"
-
-msgid "Jingle DTMF"
-msgstr "Jingle DTMF"
-
-msgid "Message Receipts"
-msgstr "Recepció de missatges"
-
-msgid "Public Key Publishing"
-msgstr "Publicació de claus públiques"
-
-msgid "User Chatting"
-msgstr "Converses d'usuari"
-
-msgid "User Browsing"
-msgstr "Navegació d'usuaris"
-
-msgid "User Gaming"
-msgstr "Jocs d'usuari"
-
-msgid "User Viewing"
-msgstr "Visualització d'usuaris"
-
-msgid "Ping"
-msgstr "Ping"
-
-# Vegeu: http://xmpp.org/extensions/xep-0200.html
-# Nota: Això es refereix a les capabilitats de l'altre interlocutor
-# No apareix a l'aplicació final, és codi mort dins un #if 0 ... #endif (josep)
-msgid "Stanza Encryption"
-msgstr "Blocs xifrats"
-
-msgid "Entity Time"
-msgstr "Hora de l'entitat"
-
-msgid "Delayed Delivery"
-msgstr "Lliurament endarrerit"
-
-msgid "Collaborative Data Objects"
-msgstr "Objectes de dades col·laboratius"
-
-msgid "File Repository and Sharing"
-msgstr "Dipòsit de fitxers i compartició"
-
-msgid "STUN Service Discovery for Jingle"
-msgstr "Servei de descoberta STUN per al Jingle"
-
-msgid "Simplified Encrypted Session Negotiation"
-msgstr "Negociació simple del xifratge de la sessió"
-
-# Mireu l'RFC (josep)
-msgid "Hop Check"
-msgstr "Comprovació dels salts"
-
-msgid "Capabilities"
-msgstr "Capacitats"
-
 msgid "Priority"
 msgstr "Prioritat"
 
@@ -4057,7 +3891,7 @@
 msgid "%s ago"
 msgstr "fa %s"
 
-msgid "Logged off"
+msgid "Logged Off"
 msgstr "Desconnectat"
 
 # Segons la viquipèdia
@@ -6979,6 +6813,9 @@
 msgid "Member Since"
 msgstr "Membre des de"
 
+msgid "Capabilities"
+msgstr "Capacitats"
+
 msgid "Profile"
 msgstr "Perfil"
 
@@ -8228,6 +8065,9 @@
 msgid "Video Camera"
 msgstr "Càmera de vídeo"
 
+msgid "File Transfer"
+msgstr "Transferència de fitxers"
+
 msgid "Supports"
 msgstr "Permet"
 
@@ -9046,6 +8886,9 @@
 msgid "Network Statistics"
 msgstr "Estadístiques de xarxa"
 
+msgid "Ping"
+msgstr "Ping"
+
 msgid "Ping failed"
 msgstr "Ha fallat el ping"
 
@@ -10657,9 +10500,12 @@
 msgid "View _Log"
 msgstr "_Visualitza el registre"
 
-msgid "Hide when offline"
+msgid "Hide When Offline"
 msgstr "Amaga quan estigui fora de línia"
 
+msgid "Show When Offline"
+msgstr "Mostra quan estigui fora de línia"
+
 msgid "_Alias..."
 msgstr "À_lies..."
 
@@ -11199,7 +11045,7 @@
 msgid "Get Away Message"
 msgstr "Aconsegueix el missatge d'absència"
 
-msgid "Last said"
+msgid "Last Said"
 msgstr "El darrer que es digué"
 
 msgid "Unable to save icon file to disk."
@@ -12799,9 +12645,8 @@
 msgid "On unread messages"
 msgstr "Si hi ha missatges sense llegir"
 
-# REVIEW
-msgid "Conversation Window Hiding"
-msgstr "Ocultació de les finestres"
+msgid "Conversation Window"
+msgstr "Finestra de conversa"
 
 msgid "_Hide new IM conversations:"
 msgstr "_Amaga noves converses de MI:"
@@ -12809,6 +12654,9 @@
 msgid "When away"
 msgstr "En estar absent"
 
+msgid "Minimi_ze new conversation windows"
+msgstr "_Minimitza les finestres de conversa noves"
+
 #. All the tab options!
 msgid "Tabs"
 msgstr "Pestanyes"
@@ -12867,9 +12715,6 @@
 msgid "F_lash window when IMs are received"
 msgstr "_Fes que la finestra faci un flaix quan hi arribin missatges"
 
-msgid "Minimi_ze new conversation windows"
-msgstr "_Minimitza les finestres de conversa noves"
-
 msgid "Minimum input area height in lines:"
 msgstr "Alçada mínima en línies de l'àrea d'entrada:"
 
@@ -14614,6 +14459,158 @@
 msgid "This plugin is useful for debbuging XMPP servers or clients."
 msgstr "Aquest connector és útil per a depurar servidors i clients XMPP."
 
+#~ msgid "Last Activity"
+#~ msgstr "Darrera activitat"
+
+#~ msgid "Service Discovery Info"
+#~ msgstr "Informació del servei de descoberta"
+
+#~ msgid "Service Discovery Items"
+#~ msgstr "Elements del servei de descoberta"
+
+# http://xmpp.org/extensions/xep-0033.html
+#~ msgid "Extended Stanza Addressing"
+#~ msgstr "Bloc d'adreçament estès"
+
+#~ msgid "Multi-User Chat"
+#~ msgstr "Xat multi-usuari"
+
+#~ msgid "Multi-User Chat Extended Presence Information"
+#~ msgstr "Informació de presència estesa per a xats multi-usuari"
+
+#~ msgid "Ad-Hoc Commands"
+#~ msgstr "Ordres Ad-Hoc"
+
+#~ msgid "PubSub Service"
+#~ msgstr "Servei PubSub"
+
+#~ msgid "SOCKS5 Bytestreams"
+#~ msgstr "Flux de bits SOCK5"
+
+#~ msgid "XHTML-IM"
+#~ msgstr "XHTML-IM"
+
+#~ msgid "User Location"
+#~ msgstr "Ubicació de l'usuari"
+
+#~ msgid "User Avatar"
+#~ msgstr "Avatar de l'usuari"
+
+#~ msgid "Chat State Notifications"
+#~ msgstr "Notificacions de l'estat del xat"
+
+#~ msgid "Software Version"
+#~ msgstr "Versió del programari"
+
+#~ msgid "Stream Initiation"
+#~ msgstr "Iniciació del flux"
+
+#~ msgid "User Mood"
+#~ msgstr "Estat d'ànim de l'usuari"
+
+#~ msgid "User Activity"
+#~ msgstr "Activitat de l'usuari"
+
+#~ msgid "Entity Capabilities"
+#~ msgstr "Capacitats de l'entitat"
+
+#~ msgid "Encrypted Session Negotiations"
+#~ msgstr "Negociacions de la sessió xifrada"
+
+# Pot ser també música, cançó... (josep)
+# Vegeu: http://xmpp.org/extensions/xep-0118.html
+#~ msgid "User Tune"
+#~ msgstr "Melodia de l'usuari"
+
+# Nota: "Roster" en XMPP és la llista de contactes (josep)
+#~ msgid "Roster Item Exchange"
+#~ msgstr "Intercanvi d'element de la llista de contactes"
+
+# Vegeu: http://xmpp.org/extensions/xep-0152.html (josep)
+# Nota: codi mort
+#~ msgid "Reachability Address"
+#~ msgstr "Adreça de localització"
+
+#~ msgid "User Profile"
+#~ msgstr "Perfil de l'usuari"
+
+# Nota: Jingle és una extensió d'XMPP i ho considerem nom propi (josep)
+# http://www.xmpp.org/extensions/xep-0166.html
+#~ msgid "Jingle"
+#~ msgstr "Jingle"
+
+# FIXME
+#~ msgid "Jingle Audio"
+#~ msgstr "Àudio amb Jingle"
+
+#~ msgid "User Nickname"
+#~ msgstr "Sobrenom de l'usuari"
+
+#~ msgid "Jingle ICE UDP"
+#~ msgstr "Jingle ICE UDP"
+
+#~ msgid "Jingle ICE TCP"
+#~ msgstr "Jingle ICE TCP"
+
+#~ msgid "Jingle Raw UDP"
+#~ msgstr "Jingle Raw UDP"
+
+#~ msgid "Jingle Video"
+#~ msgstr "Vídeo amb Jingle"
+
+#~ msgid "Jingle DTMF"
+#~ msgstr "Jingle DTMF"
+
+#~ msgid "Message Receipts"
+#~ msgstr "Recepció de missatges"
+
+#~ msgid "Public Key Publishing"
+#~ msgstr "Publicació de claus públiques"
+
+#~ msgid "User Chatting"
+#~ msgstr "Converses d'usuari"
+
+#~ msgid "User Browsing"
+#~ msgstr "Navegació d'usuaris"
+
+#~ msgid "User Gaming"
+#~ msgstr "Jocs d'usuari"
+
+#~ msgid "User Viewing"
+#~ msgstr "Visualització d'usuaris"
+
+# Vegeu: http://xmpp.org/extensions/xep-0200.html
+# Nota: Això es refereix a les capabilitats de l'altre interlocutor
+# No apareix a l'aplicació final, és codi mort dins un #if 0 ... #endif (josep)
+#~ msgid "Stanza Encryption"
+#~ msgstr "Blocs xifrats"
+
+#~ msgid "Entity Time"
+#~ msgstr "Hora de l'entitat"
+
+#~ msgid "Delayed Delivery"
+#~ msgstr "Lliurament endarrerit"
+
+#~ msgid "Collaborative Data Objects"
+#~ msgstr "Objectes de dades col·laboratius"
+
+#~ msgid "File Repository and Sharing"
+#~ msgstr "Dipòsit de fitxers i compartició"
+
+#~ msgid "STUN Service Discovery for Jingle"
+#~ msgstr "Servei de descoberta STUN per al Jingle"
+
+#~ msgid "Simplified Encrypted Session Negotiation"
+#~ msgstr "Negociació simple del xifratge de la sessió"
+
+# Mireu l'RFC (josep)
+#~ msgid "Hop Check"
+#~ msgstr "Comprovació dels salts"
+
+# REVIEW
+#~ msgid "Conversation Window Hiding"
+#~ msgstr "Ocultació de les finestres"
+
 #~ msgid "More Data needed"
 #~ msgstr "Calen més dades"
 
--- a/po/de.po	Mon Jul 06 06:04:15 2009 +0000
+++ b/po/de.po	Mon Jul 06 06:04:34 2009 +0000
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-07-04 12:30+0200\n"
-"PO-Revision-Date: 2009-07-04 12:30+0200\n"
+"POT-Creation-Date: 2009-07-05 13:02+0200\n"
+"PO-Revision-Date: 2009-07-05 13:02+0200\n"
 "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -2191,9 +2191,8 @@
 msgid "(%s) %s <AUTO-REPLY>: %s\n"
 msgstr "(%s) %s <AUTO-REPLY>: %s\n"
 
-#, fuzzy
 msgid "Error creating conference."
-msgstr "Fehler beim Herstellen der Verbindung"
+msgstr "Fehler beim Erstellen der Konferenz"
 
 #, c-format
 msgid "You are using %s, but this plugin requires %s."
@@ -2600,7 +2599,6 @@
 "Mitschnittsbetrachter an."
 
 #. * description
-#, fuzzy
 msgid ""
 "When viewing logs, this plugin will include logs from other IM clients. "
 "Currently, this includes Adium, MSN Messenger, aMSN, and Trillian.\n"
@@ -2609,8 +2607,8 @@
 "at your own risk!"
 msgstr ""
 "Dieses Plugin zeigt auch die Mitschnitte anderer Sofortnachrichtenprogramme "
-"im Mitschnittsbetrachter an. Momentan sind das Adium, MSN Messenger und "
-"Trillian.\n"
+"im Mitschnittsbetrachter an. Momentan sind das Adium, MSN Messenger, aMSN "
+"und Trillian.\n"
 "WARNUNG: Dieses Plugin ist immer noch im Alpha-Stadium und kann oft "
 "abstürzen. Benutzung auf eigene Gefahr!"
 
@@ -2657,12 +2655,11 @@
 msgid "Save messages sent to an offline user as pounce."
 msgstr "Sichert Nachrichten an einen Offline-Benutzer als Alarm."
 
-#, fuzzy
 msgid ""
 "The rest of the messages will be saved as pounces. You can edit/delete the "
 "pounce from the `Buddy Pounce' dialog."
 msgstr ""
-"Die folgenden Nachrichten werden als Alarm gesichert. Sie können den Alarm "
+"Die folgenden Nachrichten werden als Alarme gesichert. Sie können den Alarm "
 "im `Buddy-Alarm'-Dialog ändern oder löschen."
 
 #, c-format
@@ -3863,159 +3860,6 @@
 msgid "Local Time"
 msgstr "Lokale Zeit"
 
-msgid "Last Activity"
-msgstr "Letzte Aktivität"
-
-msgid "Service Discovery Info"
-msgstr "Information zur Dienstsuche"
-
-msgid "Service Discovery Items"
-msgstr "Elemente der Dienstsuche"
-
-msgid "Extended Stanza Addressing"
-msgstr "Erweiterte Blockadressierung"
-
-msgid "Multi-User Chat"
-msgstr "Mehrbenutzer-Chat"
-
-msgid "Multi-User Chat Extended Presence Information"
-msgstr "Erweiterte Anwesenheitsinformation im Mehrbenutzer-Chat"
-
-msgid "In-Band Bytestreams"
-msgstr "Bandinterner Bytestrom("
-
-msgid "Ad-Hoc Commands"
-msgstr "Ad Hoc-Kommando"
-
-msgid "PubSub Service"
-msgstr "PubSub-Dienst"
-
-msgid "SOCKS5 Bytestreams"
-msgstr "SOCKS5-Bytestrom"
-
-msgid "Out of Band Data"
-msgstr "Bandexterne Daten"
-
-msgid "XHTML-IM"
-msgstr "XHTML-IM"
-
-msgid "In-Band Registration"
-msgstr "Bandinterne Registrierung"
-
-msgid "User Location"
-msgstr "Benutzerort"
-
-msgid "User Avatar"
-msgstr "Benutzer-Avatar"
-
-msgid "Chat State Notifications"
-msgstr "Chat-Status-Benachrichtigung"
-
-msgid "Software Version"
-msgstr "Software-Version"
-
-msgid "Stream Initiation"
-msgstr "Strom-Initialisierung"
-
-msgid "File Transfer"
-msgstr "Dateiübertragung"
-
-msgid "User Mood"
-msgstr "Benutzerstimmung"
-
-msgid "User Activity"
-msgstr "Benutzeraktivität"
-
-msgid "Entity Capabilities"
-msgstr "Instanz-Fähigkeiten"
-
-msgid "Encrypted Session Negotiations"
-msgstr "Aushandlung einer verschlüsselten Sitzung"
-
-msgid "User Tune"
-msgstr "Benutzer anpassen"
-
-msgid "Roster Item Exchange"
-msgstr "Mitgliedsverzeichnis-Eintragsaustausch"
-
-msgid "Reachability Address"
-msgstr "Erreichbare Adresse"
-
-msgid "User Profile"
-msgstr "Benutzerprofil"
-
-msgid "Jingle"
-msgstr "Jingle"
-
-msgid "Jingle Audio"
-msgstr "Jingle-Klang"
-
-msgid "User Nickname"
-msgstr "Benutzer-Spitzname"
-
-msgid "Jingle ICE UDP"
-msgstr "Jingle ICE UDP"
-
-msgid "Jingle ICE TCP"
-msgstr "Jingle ICE TCP"
-
-msgid "Jingle Raw UDP"
-msgstr "Jingle Raw UDP"
-
-msgid "Jingle Video"
-msgstr "Jingle-Video"
-
-msgid "Jingle DTMF"
-msgstr "Jingle DTMF"
-
-msgid "Message Receipts"
-msgstr "Nachrichtempfänge"
-
-msgid "Public Key Publishing"
-msgstr "Öffentliche Schlüssel-Veröffentlichung"
-
-msgid "User Chatting"
-msgstr "Benutzer, die chatten"
-
-msgid "User Browsing"
-msgstr "Benutzer, die im Web surfen"
-
-msgid "User Gaming"
-msgstr "Benutzer, die spielen"
-
-msgid "User Viewing"
-msgstr "Benutzer, die schauen"
-
-msgid "Ping"
-msgstr "Ping"
-
-msgid "Stanza Encryption"
-msgstr "Blockverschlüsselung"
-
-msgid "Entity Time"
-msgstr "Instanzzeit"
-
-msgid "Delayed Delivery"
-msgstr "Verzögerte Lieferung"
-
-msgid "Collaborative Data Objects"
-msgstr "Kooperative Datenobjekte"
-
-msgid "File Repository and Sharing"
-msgstr "Speicherbereich und gemeinsame Benutzung von Dateien"
-
-msgid "STUN Service Discovery for Jingle"
-msgstr "STUN-Dienstsuche für Jingle"
-
-msgid "Simplified Encrypted Session Negotiation"
-msgstr "Vereinfachte Aushandlung der verschlüsselten Sitzung"
-
-msgid "Hop Check"
-msgstr "Hop-Überprüfung"
-
-msgid "Capabilities"
-msgstr "Fähigkeiten"
-
 msgid "Priority"
 msgstr "Priorität"
 
@@ -4026,7 +3870,7 @@
 msgid "%s ago"
 msgstr "vor %s"
 
-msgid "Logged off"
+msgid "Logged Off"
 msgstr "Abgemeldet"
 
 msgid "Middle Name"
@@ -5095,10 +4939,11 @@
 msgid "Non-IM Contacts"
 msgstr "Nicht-IM-Kontakte"
 
-#, fuzzy, c-format
+#, c-format
 msgid "%s sent you a voice chat invite, which is not yet supported."
 msgstr ""
-"%s hat Ihnen eine Webcam-Einladung gesendet, die noch nicht unterstützt wird."
+"%s hat Ihnen eine Audiochat-Einladung gesendet, die noch nicht unterstützt "
+"wird."
 
 msgid "Nudge"
 msgstr "Anstoßen"
@@ -6317,7 +6162,6 @@
 "%s scheint offline zu sein und hat die Nachricht, die Sie gerade gesendet "
 "haben, nicht empfangen."
 
-#, fuzzy
 msgid ""
 "Unable to connect to server. Please enter the address of the server to which "
 "you wish to connect."
@@ -6352,9 +6196,8 @@
 msgid "Server port"
 msgstr "Server-Port"
 
-#, fuzzy
 msgid "Received unexpected response from "
-msgstr "Ungültige HTTP-Antwort vom Server empfangen."
+msgstr "Unerwartete Antwort erhalten von"
 
 #. username connecting too frequently
 msgid ""
@@ -6916,6 +6759,9 @@
 msgid "Member Since"
 msgstr "Mitglied seit"
 
+msgid "Capabilities"
+msgstr "Fähigkeiten"
+
 msgid "Profile"
 msgstr "Profil"
 
@@ -8167,6 +8013,9 @@
 msgid "Video Camera"
 msgstr "Videokamera"
 
+msgid "File Transfer"
+msgstr "Dateiübertragung"
+
 msgid "Supports"
 msgstr "Unterstützt"
 
@@ -8992,6 +8841,9 @@
 msgid "Network Statistics"
 msgstr "Netzwerkstatistik"
 
+msgid "Ping"
+msgstr "Ping"
+
 msgid "Ping failed"
 msgstr "Ping fehlgeschlagen"
 
@@ -11004,7 +10856,7 @@
 msgstr "Hintergrundfarbe"
 
 msgid "The background color for the buddy list"
-msgstr ""
+msgstr "Die Hintergrundfarbe für die Buddy-Liste"
 
 #, fuzzy
 msgid "Layout"
@@ -11019,28 +10871,28 @@
 msgstr "Hintergrundfarbe"
 
 msgid "The background color of an expanded group"
-msgstr ""
+msgstr "Die Hintergrundfarbe für eine ausgeklappte Gruppe"
 
 #, fuzzy
 msgid "Expanded Text"
 msgstr "A_usklappen"
 
 msgid "The text information for when a group is expanded"
-msgstr ""
+msgstr "Die Textinformation für eine ausgeklappte Gruppe"
 
 #, fuzzy
 msgid "Collapsed Background Color"
 msgstr "Hintergrundfarbe auswählen"
 
 msgid "The background color of a collapsed group"
-msgstr ""
+msgstr "Die Hintergrundfarbe für eine zusammengeklappte Gruppe"
 
 #, fuzzy
 msgid "Collapsed Text"
 msgstr "_Zusammenklappen"
 
 msgid "The text information for when a group is collapsed"
-msgstr ""
+msgstr "Die Textinformation für eine zusammengeklappte Gruppe"
 
 #. Buddy
 #, fuzzy
@@ -11055,41 +10907,41 @@
 msgstr "Verknüpfter Text"
 
 msgid "The text information for when a contact is expanded"
-msgstr ""
+msgstr "Die Textinformation für einen ausgeklappten Kontakt"
 
 #, fuzzy
 msgid "On-line Text"
 msgstr "Online"
 
 msgid "The text information for when a buddy is online"
-msgstr ""
+msgstr "Die Textinformation für einen Online-Buddy"
 
 #, fuzzy
 msgid "Away Text"
 msgstr "Abwesend"
 
 msgid "The text information for when a buddy is away"
-msgstr ""
+msgstr "Die Textinformation für einen abwesenden Buddy"
 
 #, fuzzy
 msgid "Off-line Text"
 msgstr "Offline"
 
 msgid "The text information for when a buddy is off-line"
-msgstr ""
+msgstr "Die Textinformation für einen Offline-Buddy"
 
 #, fuzzy
 msgid "Idle Text"
 msgstr "Stimmungstext"
 
 msgid "The text information for when a buddy is idle"
-msgstr ""
+msgstr "Die Textinformation für einen untätigen Buddy"
 
 msgid "Message Text"
 msgstr "Nachrichtentext"
 
 msgid "The text information for when a buddy has an unread message"
-msgstr ""
+msgstr "Die Textinformation für einen Buddy mit ungelesenen Nachrichten"
 
 msgid "Message (Nick Said) Text"
 msgstr ""
@@ -11098,10 +10950,11 @@
 "The text information for when a chat has an unread message that mentions "
 "your nick"
 msgstr ""
-
-#, fuzzy
+"Die Textinformation für einen Chat mit einer ungelesenen Nachricht, in der "
+"Ihr Nickname vorkommt"
+
 msgid "The text information for a buddy's status"
-msgstr "Ändere die Benutzerinformation für %s"
+msgstr "Die Textinformation für den Status eines Buddys"
 
 msgid "Type the host name for this certificate."
 msgstr "Geben Sie einen Hostnamen für dieses Zertifikat an."
@@ -12093,7 +11946,6 @@
 msgid "Typing notification color"
 msgstr "Farbe der Tipp-Benachrichtigung"
 
-#, fuzzy
 msgid "The color to use for the typing notification"
 msgstr ""
 "Die Farbe, die für die Tipp-Benachrichtigungsmeldung benutzt werden soll"
@@ -13907,7 +13759,6 @@
 msgstr "Musik-Nachrichten-Plugin zum gemeinschaftlichen Komponieren."
 
 #. *  summary
-#, fuzzy
 msgid ""
 "The Music Messaging Plugin allows a number of users to simultaneously work "
 "on a piece of music by editing a common score in real-time."
@@ -14067,9 +13918,8 @@
 msgid "GTK+ Text Shortcut Theme"
 msgstr "GTK+ Text Shortcut-Thema"
 
-#, fuzzy
 msgid "Disable Typing Notification Text"
-msgstr "Tipp-Benachrichtigung aktivieren"
+msgstr "Tipp-Benachrichtigungstext deaktivieren"
 
 msgid "GTK+ Theme Control Settings"
 msgstr "Themenkontroll-Einstellungen für GTK+"
@@ -14166,7 +14016,6 @@
 msgstr "Senden-Knopf für das Gesprächsfenster."
 
 #. *< summary
-#, fuzzy
 msgid ""
 "Adds a Send button to the entry area of the conversation window. Intended "
 "for use when no physical keyboard is present."
@@ -14225,13 +14074,11 @@
 msgstr ""
 "Ersetzt Text in ausgehenden Nachrichten durch benutzerdefinierte Regeln."
 
-#, fuzzy
 msgid "Just logged in"
-msgstr "Nicht angemeldet"
-
-#, fuzzy
+msgstr "Gerade angemeldet"
+
 msgid "Just logged out"
-msgstr "Nicht angemeldet"
+msgstr "Gerade abgemeldet"
 
 msgid ""
 "Icon for Contact/\n"
@@ -14242,9 +14089,8 @@
 msgid "Icon for Chat"
 msgstr "Chat betreten"
 
-#, fuzzy
 msgid "Ignored"
-msgstr "Ignorieren"
+msgstr "Ignoriert"
 
 #, fuzzy
 msgid "Founder"
@@ -14257,63 +14103,52 @@
 msgid "Half Operator"
 msgstr ""
 
-#, fuzzy
 msgid "Authorization dialog"
-msgstr "Autorisierung wurde gegeben"
-
-#, fuzzy
+msgstr "Autorisierungsdialog"
+
 msgid "Error dialog"
-msgstr "Fehler "
-
-#, fuzzy
+msgstr "Fehlerdialog"
+
 msgid "Information dialog"
-msgstr "Information"
+msgstr "Informationsdialog"
 
 msgid "Mail dialog"
-msgstr ""
+msgstr "Mail-Dialog"
 
 #, fuzzy
 msgid "Question dialog"
 msgstr "Anfrage-Dialog"
 
-#, fuzzy
 msgid "Warning dialog"
-msgstr "Warnstufe"
+msgstr "Warnungdialog"
 
 msgid "What kind of dialog is this?"
-msgstr ""
-
-#
-#, fuzzy
+msgstr "Welche Art von Dialog ist dies?"
+
 msgid "Status Icons"
-msgstr "Status für %s"
+msgstr "Status-Icons"
 
 #, fuzzy
 msgid "Chatroom Emblems"
 msgstr "Chatraum-Gebiet"
 
-#, fuzzy
 msgid "Dialog Icons"
-msgstr "Icon ändern"
-
-#, fuzzy
+msgstr "Dialog-Icons"
+
 msgid "Pidgin Icon Theme Editor"
-msgstr "Pidgin GTK+ Themenkontrolle"
-
-#, fuzzy
+msgstr "Pidgin Icon-Themen-Editor"
+
 msgid "Contact"
-msgstr "Kontakt-Info"
-
-#, fuzzy
+msgstr "Kontakt"
+
 msgid "Pidgin Buddylist Theme Editor"
-msgstr "Buddy-Listen-Thema"
-
-#, fuzzy
+msgstr "Pidgin Buddy-Listen-Thema-Editor"
+
 msgid "Edit Buddylist Theme"
-msgstr "Buddy-Listen-Thema"
+msgstr "Buddy-Listen-Thema bearbeiten"
 
 msgid "Edit Icon Theme"
-msgstr ""
+msgstr "Icon-Thema bearbeiten"
 
 #. *< type
 #. *< ui_requirement
@@ -14322,16 +14157,14 @@
 #. *< priority
 #. *< id
 #. *  description
-#, fuzzy
 msgid "Pidgin Theme Editor"
-msgstr "Pidgin GTK+ Themenkontrolle"
+msgstr "Pidgin Themen-Editor"
 
 #. *< name
 #. *< version
 #. *  summary
-#, fuzzy
 msgid "Pidgin Theme Editor."
-msgstr "Pidgin GTK+ Themenkontrolle"
+msgstr "Pidgin Themen-Editor"
 
 #. *< type
 #. *< ui_requirement
@@ -14499,7 +14332,6 @@
 msgid "Options specific to Pidgin for Windows."
 msgstr "Optionen für Pidgin unter Windows."
 
-#, fuzzy
 msgid ""
 "Provides options specific to Pidgin for Windows, such as buddy list docking."
 msgstr ""