changeset 25745:c974d4453f12

propagate from branch 'im.pidgin.pidgin' (head d3440d677dd69ed30a8158b515bd26d210dacb9d) to branch 'im.pidgin.cpw.malu.xmpp.ibb_ft' (head 0272db32424bf245d924c833b771e3f6c2ebe286)
author Marcus Lundblad <ml@update.uu.se>
date Sun, 30 Nov 2008 19:41:51 +0000
parents 487a750cc924 (current diff) 821afc095104 (diff)
children 0285bb19f311
files libpurple/protocols/jabber/libxmpp.c libpurple/protocols/jabber/si.c
diffstat 50 files changed, 1196 insertions(+), 747 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon Nov 24 22:12:36 2008 +0000
+++ b/COPYRIGHT	Sun Nov 30 19:41:51 2008 +0000
@@ -338,6 +338,7 @@
 Dennis Ristuccia
 Lee Roach
 Eion Robb
+Kahlil Robinson
 Rhett Robinson
 Luciano Miguel Ferreira Rocha
 Andrew Rodland
@@ -349,6 +350,7 @@
 Michael Ruprecht
 Sam S.
 Thanumalayan S.
+Jonathan Sailor
 Elliott Sales de Andrade
 Tomasz Sałaciński <tsalacinski@gmail.com>
 Pradyumna Sampath
--- a/ChangeLog	Mon Nov 24 22:12:36 2008 +0000
+++ b/ChangeLog	Sun Nov 30 19:41:51 2008 +0000
@@ -8,7 +8,6 @@
 	  --with-system-ssl-certs and GnuTLS need to include these in the
 	  system certs directory.
 	* Corrected maximum message lengths for Yahoo!
-	* Fix some problems with Gadu-Gadu buddy icons (Adam Strzelecki)
 	* Enable auto-reply on Zephyr, to emulate 'zaway' (Toby Schaffer)
 	* The Buddy State Notification plugin no longer prints duplicate
 	  notifications when the same buddy is in multiple groups (Florian Quèze)
@@ -16,6 +15,25 @@
 	  ID's, etc. into links (Florian Quèze)
 	* Fix a crash in SIMPLE when a malformed message is received.
 
+	Gadu-Gadu:
+	* Fix some problems with Gadu-Gadu buddy icons (Adam Strzelecki)
+	* Gadu-Gadu now validates that UID's are valid (Adam Strzelecki)
+	* Gadu-Gadu now does proper charset translations where needed (Adam
+	  Strzelecki)
+
+	XMPP:
+	* Fix the namespace URL we look for in PEP reply stanzas to match the URL
+	  used in the 'get' requests (Paul Aurich)
+	* Resources can be set to the local machine's hostname by using
+	  __HOSTNAME__ as the resource string (Jonathan Sailor)
+	* Resources can now be left blank, causing the server to generate a
+	  resource for us where supported (Jonathan Sailor)
+	* Resources now default to no value
+	* Quit trying to get user info for MUC's (Paul Aurich)
+	* Send "client-accepts-full-bind-result" attribute during SASL login.
+	  This will fix Google Talk login failures if the user configures the
+	  wrong domain for his/her account.
+
 	Pidgin:
 	* On GTK+ 2.14 and higher, we're using the gtk-tooltip-delay setting
 	  instead of our own (hidden) tooltip_delay pref.  If you had
--- a/Makefile.am	Mon Nov 24 22:12:36 2008 +0000
+++ b/Makefile.am	Sun Nov 30 19:41:51 2008 +0000
@@ -59,7 +59,7 @@
 # Ensure we're working from a tag...
 	test x`mtn automate select t:v$(PACKAGE_VERSION)` = x`mtn automate get_base_revision_id`
 # ... and have no changes in the working copy.
-	test x`mtn diff | grep -v '^#'` = x
+	test "x`mtn diff | grep -v '^#'`" = x
 
 release: version-check distcheck packages
 
--- a/autogen.sh	Mon Nov 24 22:12:36 2008 +0000
+++ b/autogen.sh	Sun Nov 30 19:41:51 2008 +0000
@@ -66,7 +66,7 @@
 	CMD=$1
 
 	printf "%s" "checking for ${CMD}... "
-	BIN=`which ${CMD} 2> /dev/null`
+	BIN=`which ${CMD} 2>/dev/null`
 
 	if [ x"${BIN}" = x"" ] ; then
 		echo "not found."
--- a/finch/gntblist.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/gntblist.c	Sun Nov 30 19:41:51 2008 +0000
@@ -2207,6 +2207,7 @@
 {
 	PurpleSavedStatus *current;
 	const char *message, *newmessage;
+	char *escnewmessage;
 	PurpleStatusPrimitive prim, newprim;
 	StatusBoxItem *item;
 
@@ -2216,6 +2217,7 @@
 
 	newmessage = gnt_entry_get_text(GNT_ENTRY(ggblist->statustext));
 	item = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(ggblist->status));
+	escnewmessage = newmessage ? g_markup_escape_text(newmessage, -1) : NULL;
 
 	switch (item->type) {
 		case STATUS_PRIMITIVE:
@@ -2228,16 +2230,16 @@
 			goto end;  /* 'New' or 'Saved' is selected, but this should never happen. */
 	}
 
-	if (newprim != prim || ((message && !newmessage) ||
-				(!message && newmessage) ||
-				(message && newmessage && g_utf8_collate(message, newmessage) != 0)))
+	if (newprim != prim || ((message && !escnewmessage) ||
+				(!message && escnewmessage) ||
+				(message && escnewmessage && g_utf8_collate(message, escnewmessage) != 0)))
 	{
-		PurpleSavedStatus *status = purple_savedstatus_find_transient_by_type_and_message(newprim, newmessage);
+		PurpleSavedStatus *status = purple_savedstatus_find_transient_by_type_and_message(newprim, escnewmessage);
 									/* Holy Crap! That's a LAWNG function name */
 		if (status == NULL)
 		{
 			status = purple_savedstatus_new(NULL, newprim);
-			purple_savedstatus_set_message(status, newmessage);
+			purple_savedstatus_set_message(status, escnewmessage);
 		}
 
 		purple_savedstatus_activate(status);
@@ -2245,6 +2247,7 @@
 
 	gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree);
 end:
+	g_free(escnewmessage);
 	if (ggblist->typing)
 		g_source_remove(ggblist->typing);
 	ggblist->typing = 0;
--- a/finch/gntdebug.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/gntdebug.c	Sun Nov 30 19:41:51 2008 +0000
@@ -344,6 +344,7 @@
 	REGISTER_G_LOG_HANDLER("GModule");
 	REGISTER_G_LOG_HANDLER("GLib-GObject");
 	REGISTER_G_LOG_HANDLER("GThread");
+	REGISTER_G_LOG_HANDLER("Gnt");
 #ifdef USE_GSTREAMER
 	REGISTER_G_LOG_HANDLER("GStreamer");
 #endif
--- a/finch/libgnt/Makefile.am	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/Makefile.am	Sun Nov 30 19:41:51 2008 +0000
@@ -6,6 +6,8 @@
 
 lib_LTLIBRARIES = libgnt.la
 
+noinst_HEADERS = gntinternal.h
+
 BUILT_SOURCES = gntmarshal.h
 
 libgnt_la_SOURCES = \
--- a/finch/libgnt/gntbindable.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntbindable.c	Sun Nov 30 19:41:51 2008 +0000
@@ -22,6 +22,10 @@
 
 #include <string.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Bindable"
+
 #include "gntbindable.h"
 #include "gntstyle.h"
 #include "gnt.h"
@@ -360,7 +364,7 @@
 
 	action = g_hash_table_lookup(klass->actions, name);
 	if (!action) {
-		g_printerr("GntBindable: Invalid action name %s for %s\n",
+		gnt_warning("Invalid action name %s for %s",
 				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
 		if (list)
 			g_list_free(list);
--- a/finch/libgnt/gntcolors.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntcolors.c	Sun Nov 30 19:41:51 2008 +0000
@@ -24,6 +24,10 @@
 
 #include <ncurses.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Colors"
+
 #include "gntcolors.h"
 #include "gntstyle.h"
 
@@ -182,7 +186,7 @@
 
 	if (error)
 	{
-		g_printerr("GntColors: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		error = NULL;
 	}
@@ -226,7 +230,7 @@
 
 	if (error)
 	{
-		g_printerr("GntColors: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		return;
 	}
--- a/finch/libgnt/gntentry.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntentry.c	Sun Nov 30 19:41:51 2008 +0000
@@ -365,7 +365,7 @@
 		return TRUE;
 
 	len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor);
-	update_kill_ring(entry, ENTRY_DEL_BWD_CHAR, entry->cursor, -len);
+	update_kill_ring(entry, ENTRY_JAIL, entry->cursor, -len);
 	entry->cursor -= len;
 
 	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor);
@@ -391,7 +391,7 @@
 		return FALSE;
 
 	len = g_utf8_find_next_char(entry->cursor, NULL) - entry->cursor;
-	update_kill_ring(entry, ENTRY_DEL_FWD_CHAR, entry->cursor, len);
+	update_kill_ring(entry, ENTRY_JAIL, entry->cursor, len);
 	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor - len + 1);
 	entry->end -= len;
 	entry_redraw(GNT_WIDGET(entry));
--- a/finch/libgnt/gntfilesel.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntfilesel.c	Sun Nov 30 19:41:51 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "FileSel"
+
 #include "gntbutton.h"
 #include "gntentry.h"
 #include "gntfilesel.h"
@@ -254,7 +258,7 @@
 		struct stat st;
 
 		if (stat(fp, &st)) {
-			g_printerr("Error stating location %s\n", fp);
+			gnt_warning("Error stating location %s", fp);
 		} else {
 			if (S_ISDIR(st.st_mode)) {
 				file = gnt_file_new_dir(str);
@@ -309,7 +313,7 @@
 		success = local_read_fn(sel->current, &files, err);
 	
 	if (!success || *err) {
-		g_printerr("GntFileSel: error opening location %s (%s)\n",
+		gnt_warning("error opening location %s (%s)",
 			sel->current, *err ? (*err)->message : "reason unknown");
 		return FALSE;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntinternal.h	Sun Nov 30 19:41:51 2008 +0000
@@ -0,0 +1,33 @@
+/*
+ * GNT - The GLib Ncurses Toolkit
+ *
+ * GNT 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 library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "Gnt"
+
+#ifdef __GNUC__
+# ifndef GNT_LOG_DOMAIN
+#  define GNT_LOG_DOMAIN ""
+# endif
+# define gnt_warning(format, args...)  g_warning("(%s) %s: " format, GNT_LOG_DOMAIN, __PRETTY_FUNCTION__, args)
+#else /* __GNUC__ */
+# define gnt_warning g_warning
+#endif
+
--- a/finch/libgnt/gntkeys.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntkeys.c	Sun Nov 30 19:41:51 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Keys"
+
 #include "gntkeys.h"
 
 #include <glib.h>
--- a/finch/libgnt/gntmain.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntmain.c	Sun Nov 30 19:41:51 2008 +0000
@@ -32,6 +32,10 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Main"
+
 #include "gnt.h"
 #include "gntbox.h"
 #include "gntbutton.h"
@@ -319,7 +323,7 @@
 	                                 But irssi does this, so I am going to assume the
 	                                 crashes were caused by some other stuff. */
 
-	g_printerr("gntmain: setting up IO (%d)\n", channel_read_callback);
+	gnt_warning("setting up IO (%d)", channel_read_callback);
 }
 
 static gboolean
--- a/finch/libgnt/gntstyle.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntstyle.c	Sun Nov 30 19:41:51 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Style"
+
 #include "gntstyle.h"
 #include "gntcolors.h"
 #include "gntws.h"
@@ -226,7 +230,7 @@
 		keys = g_key_file_get_keys(gkfile, name, &len, &error);
 		if (error)
 		{
-			g_printerr("GntStyle: %s\n", error->message);
+			gnt_warning("%s", error->message);
 			g_error_free(error);
 			g_free(name);
 			return;
@@ -241,7 +245,7 @@
 
 			if (error)
 			{
-				g_printerr("GntStyle: %s\n", error->message);
+				gnt_warning("%s", error->message);
 				g_error_free(error);
 				error = NULL;
 			}
@@ -249,7 +253,7 @@
 			{
 				const char *keycode = parse_key(key);
 				if (keycode == NULL) {
-					g_printerr("GntStyle: Invalid key-binding %s\n", key);
+					gnt_warning("Invalid key-binding %s", key);
 				} else {
 					gnt_bindable_register_binding(klass, action, keycode, NULL);
 				}
@@ -280,7 +284,7 @@
 		keys = g_key_file_get_keys(gkfile, kname, &len, &error);
 		if (error)
 		{
-			g_printerr("GntStyle: %s\n", error->message);
+			gnt_warning("%s", error->message);
 			g_error_free(error);
 			g_free(kname);
 			return ret;
@@ -295,7 +299,7 @@
 
 			if (error)
 			{
-				g_printerr("GntStyle: %s\n", error->message);
+				gnt_warning("%s", error->message);
 				g_error_free(error);
 				error = NULL;
 			}
@@ -303,7 +307,7 @@
 			{
 				const char *keycode = parse_key(key);
 				if (keycode == NULL) {
-					g_printerr("GntStyle: Invalid key-binding %s\n", key);
+					gnt_warning("Invalid key-binding %s", key);
 				} else {
 					ret = TRUE;
 					g_hash_table_replace(table, g_strdup(keycode), menuid);
@@ -338,7 +342,7 @@
 		keys = g_key_file_get_keys(gkfile, name, &len, &error);
 		if (error)
 		{
-			g_printerr("GntStyle: %s\n", error->message);
+			gnt_warning("%s", error->message);
 			g_error_free(error);
 			g_free(name);
 			return;
@@ -353,7 +357,7 @@
 
 			if (error)
 			{
-				g_printerr("GntStyle: %s\n", error->message);
+				gnt_warning("%s", error->message);
 				g_error_free(error);
 				error = NULL;
 				g_free(key);
@@ -402,7 +406,7 @@
 
 	if (error)
 	{
-		g_printerr("GntStyle: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 	}
 	else
@@ -426,7 +430,7 @@
 	if (!g_key_file_load_from_file(gkfile, filename,
                 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
 	{
-		g_printerr("GntStyle: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		return;
 	}
--- a/finch/libgnt/gnttextview.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gnttextview.c	Sun Nov 30 19:41:51 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "TextView"
+
 #include "gntstyle.h"
 #include "gnttextview.h"
 #include "gntutils.h"
@@ -67,6 +71,7 @@
 gnt_text_view_draw(GntWidget *widget)
 {
 	GntTextView *view = GNT_TEXT_VIEW(widget);
+	int n;
 	int i = 0;
 	GList *lines;
 	int rows, scrcol;
@@ -76,10 +81,11 @@
 	wbkgd(widget->window, gnt_color_pair(GNT_COLOR_NORMAL));
 	werase(widget->window);
 
+	n = g_list_length(view->list);
 	if ((view->flags & GNT_TEXT_VIEW_TOP_ALIGN) &&
-			g_list_length(view->list) < widget->priv.height) {
+			n < widget->priv.height) {
 		GList *now = view->list;
-		comp = widget->priv.height - g_list_length(view->list);
+		comp = widget->priv.height - n;
 		view->list = g_list_nth_prev(view->list, comp);
 		if (!view->list) {
 			view->list = g_list_first(now);
@@ -236,6 +242,7 @@
 static char *
 gnt_text_view_get_p(GntTextView *view, int x, int y)
 {
+	int n;
 	int i = 0;
 	GntWidget *wid = GNT_WIDGET(view);
 	GntTextLine *line;
@@ -244,10 +251,11 @@
 	GntTextSegment *seg;
 	gchar *pos;
 
+	n = g_list_length(view->list);
 	y = wid->priv.height - y;
-	if (g_list_length(view->list) < y) {
+	if (n < y) {
 		x = 0;
-		y = g_list_length(view->list) - 1;
+		y = n - 1;
 	}
 
 	lines = g_list_nth(view->list, y - 1);
@@ -776,7 +784,7 @@
 						/* XXX: Make things work if the tagged text spans over several lines. */
 					} else {
 						/* XXX: handle the rest of the conditions */
-						g_printerr("WTF! This needs to be handled properly!!\n");
+						gnt_warning("WTF! This needs to be handled properly!!%s", "");
 					}
 				}
 			}
--- a/finch/libgnt/gntutils.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntutils.c	Sun Nov 30 19:41:51 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Utils"
+
 #include "gntbutton.h"
 #include "gntcheckbox.h"
 #include "gntcombobox.h"
@@ -306,7 +310,7 @@
 	xmlFree(content);
 
 	if (widget == NULL) {
-		g_printerr("Invalid widget name %s\n", name);
+		gnt_warning("Invalid widget name %s", name);
 		return NULL;
 	}
 
--- a/finch/libgnt/gntwm.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/finch/libgnt/gntwm.c	Sun Nov 30 19:41:51 2008 +0000
@@ -46,6 +46,10 @@
 #include <string.h>
 #include <time.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "WM"
+
 #include "gntwm.h"
 #include "gntstyle.h"
 #include "gntmarshal.h"
@@ -201,7 +205,7 @@
 	GString *text = g_string_new("act: ");
 	if (message)
 		gnt_widget_destroy(message);
-	if (g_list_length(act) == 0)
+	if (!act)
 		return;
 	for (iter = act; iter; iter = iter->next) {
 		GntWS *ws = iter->data;
@@ -325,7 +329,7 @@
 	gsize nk;
 
 	if (!g_key_file_load_from_file(gfile, filename, G_KEY_FILE_NONE, &error)) {
-		g_printerr("GntWM: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		g_free(filename);
 		return;
@@ -333,7 +337,7 @@
 
 	keys = g_key_file_get_keys(gfile, "positions", &nk, &error);
 	if (error) {
-		g_printerr("GntWM: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		error = NULL;
 	} else {
@@ -349,7 +353,7 @@
 				p->y = y;
 				g_hash_table_replace(wm->positions, g_strdup(title + 1), p);
 			} else {
-				g_printerr("GntWM: Invalid number of arguments for positioing a window.\n");
+				gnt_warning("Invalid number of arguments (%d) for positioning a window.", l);
 			}
 			g_strfreev(coords);
 		}
@@ -927,6 +931,7 @@
 	GntWidget *tree, *win;
 	GList *iter;
 	GntWM *wm = GNT_WM(bindable);
+	int n;
 	if (wm->_list.window || wm->menu)
 		return TRUE;
 
@@ -950,8 +955,9 @@
 				gnt_tree_create_row(GNT_TREE(tree), action->label), NULL);
 	}
 	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), wm);
-	gnt_widget_set_size(tree, 0, g_list_length(wm->acts));
-	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - g_list_length(wm->acts));
+	n = g_list_length(wm->acts);
+	gnt_widget_set_size(tree, 0, n);
+	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - n);
 
 	gnt_widget_show(win);
 	return TRUE;
@@ -2093,7 +2099,7 @@
 
 	file = fopen(filename, "wb");
 	if (file == NULL) {
-		g_printerr("GntWM: error opening file to save positions\n");
+		gnt_warning("error opening file (%s) to save positions", filename);
 	} else {
 		fprintf(file, "[positions]\n");
 		g_hash_table_foreach(wm->positions, write_gdi, file);
--- a/libpurple/protocols/gg/buddylist.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/gg/buddylist.c	Sun Nov 30 19:41:51 2008 +0000
@@ -96,9 +96,10 @@
 	PurpleGroup *group;
 	gchar **users_tbl;
 	int i;
+	char *utf8buddylist = charset_convert(buddylist, "CP1250", "UTF-8");
 
 	/* Don't limit the number of records in a buddylist. */
-	users_tbl = g_strsplit(buddylist, "\r\n", -1);
+	users_tbl = g_strsplit(utf8buddylist, "\r\n", -1);
 
 	for (i = 0; users_tbl[i] != NULL; i++) {
 		gchar **data_tbl;
@@ -115,23 +116,22 @@
 			continue;
 		}
 
-		show = charset_convert(data_tbl[F_NICKNAME], "CP1250", "UTF-8");
+		show = data_tbl[F_NICKNAME];
 		name = data_tbl[F_UIN];
-		if ('\0' == *name) {
+		if ('\0' == *name || !atol(name)) {
 			purple_debug_warning("gg",
-				"Something is wrong on line %d of the buddylist. Skipping.\n",
+				"Identifier on line %d of the buddylist is not a number. Skipping.\n",
 				i + 1);
 			continue;
 		}
 
 		if ('\0' == *show) {
-			show = g_strdup(name);
+			show = name;
 		}
 
 		purple_debug_info("gg", "got buddy: name=%s; show=%s\n", name, show);
 
 		if (purple_find_buddy(purple_connection_get_account(gc), name)) {
-			g_free(show);
 			g_strfreev(data_tbl);
 			continue;
 		}
@@ -144,7 +144,7 @@
 			gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
 			if (ggp_array_size(group_tbl) > 0) {
 				g_free(g);
-				g = charset_convert(group_tbl[0], "CP1250", "UTF-8");
+				g = g_strdup(group_tbl[0]);
 			}
 			g_strfreev(group_tbl);
 		}
@@ -160,10 +160,10 @@
 		purple_blist_add_buddy(buddy, NULL, group, NULL);
 		g_free(g);
 
-		g_free(show);
 		g_strfreev(data_tbl);
 	}
 	g_strfreev(users_tbl);
+	g_free(utf8buddylist);
 
 	ggp_buddylist_send(gc);
 }
@@ -234,8 +234,7 @@
 				continue;
 
 			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) {
-				gchar *newdata, *name, *alias, *gname;
-				gchar *cp_alias, *cp_gname;
+				gchar *name, *alias, *gname;
 
 				if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
 					continue;
@@ -248,25 +247,20 @@
 				alias = buddy->alias ? buddy->alias : buddy->name;
 				gname = group->name;
 
-				cp_gname = charset_convert(gname, "UTF-8", "CP1250");
-				cp_alias = charset_convert(alias, "UTF-8", "CP1250");
-				newdata = g_strdup_printf(
-						"%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
-						cp_alias, cp_alias, cp_alias, cp_alias,
-						"", cp_gname, name, "", "");
+				ptr = buddylist;
+				buddylist = g_strdup_printf(
+						"%s%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
+						ptr, alias, alias, alias, alias,
+						"", gname, name, "", "");
 
-				ptr = buddylist;
-				buddylist = g_strconcat(ptr, newdata, NULL);
-
-				g_free(newdata);
 				g_free(ptr);
-				g_free(cp_gname);
-				g_free(cp_alias);
 			}
 		}
 	}
 
-	return buddylist;
+	ptr = charset_convert(buddylist, "UTF-8", "CP1250");
+	g_free(buddylist);
+	return ptr;
 }
 /* }}} */
 
--- a/libpurple/protocols/jabber/auth.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/auth.c	Sun Nov 30 19:41:51 2008 +0000
@@ -397,6 +397,10 @@
 		auth = xmlnode_new("auth");
 		xmlnode_set_namespace(auth, "urn:ietf:params:xml:ns:xmpp-sasl");
 		xmlnode_set_attrib(auth, "mechanism", js->current_mech);
+		
+		xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
+		xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
+
 		if (clientout) {
 			if (coutlen == 0) {
 				xmlnode_insert_data(auth, "=", -1);
--- a/libpurple/protocols/jabber/buddy.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Sun Nov 30 19:41:51 2008 +0000
@@ -115,14 +115,18 @@
 						break;
 					case JABBER_BUDDY_STATE_AWAY:
 					case JABBER_BUDDY_STATE_DND:
-					case JABBER_BUDDY_STATE_UNAVAILABLE:
-						/* This resource is away/dnd/unavailable. Prefer to one which is extended away or unknown. */
-						if ((jbr->state == JABBER_BUDDY_STATE_XA) || 
+						/* This resource is away/dnd. Prefer to one which is extended away, unavailable, or unknown. */
+						if ((jbr->state == JABBER_BUDDY_STATE_XA) || (jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) ||
 							(jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
 							jbr = l->data;
 						break;
 					case JABBER_BUDDY_STATE_XA:
-						/* This resource is extended away. That's better than unknown. */
+						/* This resource is extended away. That's better than unavailable or unknown. */
+						if ((jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) || (jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
+							jbr = l->data;
+						break;
+					case JABBER_BUDDY_STATE_UNAVAILABLE:
+						/* This resource is unavailable. That's better than unknown. */
 						if ((jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
 							jbr = l->data;
 						break;
@@ -966,7 +970,7 @@
 		}
 #endif
 	} else {
-		gboolean multiple_resources = jbi->jb->resources && (g_list_length(jbi->jb->resources) > 1);
+		gboolean multiple_resources = jbi->jb->resources && jbi->jb->resources->next;
 
 		for(resources = jbi->jb->resources; resources; resources = resources->next) {
 			char *purdy = NULL;
@@ -1798,12 +1802,21 @@
 void jabber_buddy_get_info(PurpleConnection *gc, const char *who)
 {
 	JabberStream *js = gc->proto_data;
-	char *bare_jid = jabber_get_bare_jid(who);
+	JabberID *jid = jabber_id_new(who);
+
+	if (!jid)
+		return;
 
-	if(bare_jid) {
+	if (jabber_chat_find(js, jid->node, jid->domain)) {
+		/* For a conversation, include the resource (indicates the user). */
+		jabber_buddy_get_info_for_jid(js, who);
+	} else {
+		char *bare_jid = jabber_get_bare_jid(who);
 		jabber_buddy_get_info_for_jid(js, bare_jid);
 		g_free(bare_jid);
 	}
+
+	jabber_id_free(jid);
 }
 
 static void jabber_buddy_set_invisibility(JabberStream *js, const char *who,
--- a/libpurple/protocols/jabber/jabber.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sun Nov 30 19:41:51 2008 +0000
@@ -146,10 +146,37 @@
 	jabber_session_init(js);
 }
 
+static char *jabber_prep_resource(char *input) {
+	char hostname[256]; /* current hostname */
+
+	/* Empty resource == don't send any */
+	if (*input == '\0')
+		return NULL;
+
+	if (strstr(input, "__HOSTNAME__") == NULL)
+		return input;
+
+	/* Replace __HOSTNAME__ with hostname */
+	if (gethostname(hostname, sizeof(hostname) - 1)) {
+		purple_debug_warning("jabber", "gethostname: %s\n", g_strerror(errno));
+		/* according to glibc doc, the only time an error is returned
+		   is if the hostname is longer than the buffer, in which case
+		   glibc 2.2+ would still fill the buffer with partial
+		   hostname, so maybe we want to detect that and use it
+		   instead
+		*/
+		strcpy(hostname, "localhost");
+	}
+	hostname[sizeof(hostname) - 1] = '\0';
+
+	return purple_strreplace(input, "__HOSTNAME__", hostname);
+}
+
 static void jabber_stream_features_parse(JabberStream *js, xmlnode *packet)
 {
 	if(xmlnode_get_child(packet, "starttls")) {
 		if(jabber_process_starttls(js, packet))
+	
 			return;
 	} else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) {
 		purple_connection_error_reason (js->gc,
@@ -164,11 +191,17 @@
 		jabber_auth_start(js, packet);
 	} else if(xmlnode_get_child(packet, "bind")) {
 		xmlnode *bind, *resource;
+		char *requested_resource;
 		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
 		bind = xmlnode_new_child(iq->node, "bind");
 		xmlnode_set_namespace(bind, "urn:ietf:params:xml:ns:xmpp-bind");
-		resource = xmlnode_new_child(bind, "resource");
-		xmlnode_insert_data(resource, js->user->resource, -1);
+		requested_resource = jabber_prep_resource(js->user->resource);
+
+		if (requested_resource != NULL) {
+			resource = xmlnode_new_child(bind, "resource");
+			xmlnode_insert_data(resource, requested_resource, -1);
+			free(requested_resource);
+		}
 
 		jabber_iq_set_callback(iq, jabber_bind_result_cb, NULL);
 
@@ -679,19 +712,6 @@
 		return;
 	}
 	
-	if(!js->user->resource) {
-		char *me;
-		js->user->resource = g_strdup("Home");
-		if(!js->user->node) {
-			js->user->node = js->user->domain;
-			js->user->domain = g_strdup("jabber.org");
-		}
-		me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain,
-				js->user->resource);
-		purple_account_set_username(account, me);
-		g_free(me);
-	}
-
 	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
 		my_jb->subscription |= JABBER_SUB_BOTH;
 
@@ -1159,19 +1179,6 @@
 
 	js->write_buffer = purple_circ_buffer_new(512);
 
-	if(!js->user->resource) {
-		char *me;
-		js->user->resource = g_strdup("Home");
-		if(!js->user->node) {
-			js->user->node = js->user->domain;
-			js->user->domain = g_strdup("jabber.org");
-		}
-		me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain,
-				js->user->resource);
-		purple_account_set_username(account, me);
-		g_free(me);
-	}
-
 	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
 		my_jb->subscription |= JABBER_SUB_BOTH;
 
--- a/libpurple/protocols/jabber/libxmpp.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Sun Nov 30 19:41:51 2008 +0000
@@ -212,7 +212,7 @@
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 	
-	split = purple_account_user_split_new(_("Resource"), "Home", '/');
+	split = purple_account_user_split_new(_("Resource"), NULL, '/');
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 	
--- a/libpurple/protocols/jabber/message.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/message.c	Sun Nov 30 19:41:51 2008 +0000
@@ -920,7 +920,7 @@
 			if (jb) {
 				return jabber_buddy_has_capability(jb, XEP_0231_NAMESPACE);
 			} else {
-				return NULL;
+				return FALSE;
 			}
 			break;
 		default:
--- a/libpurple/protocols/jabber/pep.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/pep.c	Sun Nov 30 19:41:51 2008 +0000
@@ -54,7 +54,7 @@
 
 static void do_pep_iq_request_item_callback(JabberStream *js, xmlnode *packet, gpointer data) {
 	const char *from = xmlnode_get_attrib(packet,"from");
-	xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub#event");
+	xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub");
 	xmlnode *items = NULL;
 	JabberPEPHandler *cb = data;
 	
--- a/libpurple/protocols/jabber/presence.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/presence.c	Sun Nov 30 19:41:51 2008 +0000
@@ -513,7 +513,7 @@
 		} else if(!strcmp(y->name, "delay") && !strcmp(xmlns, "urn:xmpp:delay")) {
 			/* XXX: compare the time.  jabber:x:delay can happen on presence packets that aren't really and truly delayed */
 			delayed = TRUE;
-		} else if(!strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) {
+		} else if(xmlns && !strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) {
 			caps = y; /* store for later, when creating buddy resource */
 		} else if(!strcmp(y->name, "x")) {
 			const char *xmlns = xmlnode_get_namespace(y);
--- a/libpurple/protocols/jabber/si.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/jabber/si.c	Sun Nov 30 19:41:51 2008 +0000
@@ -1422,7 +1422,7 @@
 
 			purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg);
 			g_free(msg);
-		} else if(g_list_length(jb->resources) == 1) {
+		} else if(!jb->resources->next) {
 			/* only 1 resource online (probably our most common case)
 			 * so no need to ask who to send to */
 			jbr = jb->resources->data;
--- a/libpurple/protocols/msn/soap.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/msn/soap.c	Sun Nov 30 19:41:51 2008 +0000
@@ -1,6 +1,6 @@
 /**
  * @file soap.c
- * 	C file for SOAP connection related process
+ * Functions relating to SOAP connections.
  *
  * purple
  *
@@ -56,6 +56,7 @@
 	gboolean connected;
 
 	guint event_handle;
+	guint run_timer;
 	GString *buf;
 	gsize handled_len;
 	gsize body_len;
@@ -69,22 +70,99 @@
 	MsnSoapRequest *current_request;
 } MsnSoapConnection;
 
-static void msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data);
 static gboolean msn_soap_connection_run(gpointer data);
 
-static MsnSoapConnection *msn_soap_connection_new(MsnSession *session,
-	const char *host);
-static void msn_soap_connection_handle_next(MsnSoapConnection *conn);
-static void msn_soap_connection_destroy(MsnSoapConnection *conn);
+static MsnSoapConnection *
+msn_soap_connection_new(MsnSession *session, const char *host)
+{
+	MsnSoapConnection *conn = g_new0(MsnSoapConnection, 1);
+	conn->session = session;
+	conn->host = g_strdup(host);
+	conn->queue = g_queue_new();
+	return conn;
+}
+
+static void
+msn_soap_message_destroy(MsnSoapMessage *message)
+{
+	g_slist_foreach(message->headers, (GFunc)g_free, NULL);
+	g_slist_free(message->headers);
+	g_free(message->action);
+	if (message->xml)
+		xmlnode_free(message->xml);
+	g_free(message);
+}
+
+static void
+msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message)
+{
+	g_free(req->path);
+	if (!keep_message)
+		msn_soap_message_destroy(req->message);
+	g_free(req);
+}
+
+static void
+msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect)
+{
+	if (conn->event_handle) {
+		purple_input_remove(conn->event_handle);
+		conn->event_handle = 0;
+	}
+
+	if (conn->run_timer) {
+		purple_timeout_remove(conn->run_timer);
+		conn->run_timer = 0;
+	}
 
-static void msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path, gboolean secure,
-	MsnSoapCallback cb, gpointer cb_data, gboolean first);
+	if (conn->message) {
+		msn_soap_message_destroy(conn->message);
+		conn->message = NULL;
+	}
+
+	if (conn->buf) {
+		g_string_free(conn->buf, TRUE);
+		conn->buf = NULL;
+	}
+
+	if (conn->ssl && (disconnect || conn->close_when_done)) {
+		purple_ssl_close(conn->ssl);
+		conn->ssl = NULL;
+	}
+
+	if (conn->current_request) {
+		msn_soap_request_destroy(conn->current_request, FALSE);
+		conn->current_request = NULL;
+	}
+}
 
-static void msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message);
-static void msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect);
-static gboolean msn_soap_write_cb_internal(gpointer data, gint fd, PurpleInputCondition cond, gboolean initial);
-static void msn_soap_process(MsnSoapConnection *conn);
+static void
+msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data)
+{
+	MsnSoapRequest *req = item;
+
+	if (req->cb)
+		req->cb(req->message, NULL, req->cb_data);
+
+	msn_soap_request_destroy(req, FALSE);
+}
+
+static void
+msn_soap_connection_destroy(MsnSoapConnection *conn)
+{
+	if (conn->current_request) {
+		MsnSoapRequest *req = conn->current_request;
+		conn->current_request = NULL;
+		msn_soap_connection_destroy_foreach_cb(req, conn);
+	}
+
+	msn_soap_connection_sanitize(conn, TRUE);
+	g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
+	g_queue_free(conn->queue);
+
+	g_free(conn->host);
+	g_free(conn);
+}
 
 static gboolean
 msn_soap_cleanup_each(gpointer key, gpointer value, gpointer data)
@@ -112,13 +190,12 @@
 		g_hash_table_foreach_remove(sess->soap_table, msn_soap_cleanup_each,
 			&t);
 
-		if (g_hash_table_size(sess->soap_table) == 0) {
-			purple_timeout_remove(sess->soap_cleanup_handle);
-			sess->soap_cleanup_handle = 0;
-		}
+		if (g_hash_table_size(sess->soap_table) != 0)
+			return TRUE;
 	}
 
-	return TRUE;
+	sess->soap_cleanup_handle = 0;
+	return FALSE;
 }
 
 static MsnSoapConnection *
@@ -147,38 +224,54 @@
 	return conn;
 }
 
-static MsnSoapConnection *
-msn_soap_connection_new(MsnSession *session, const char *host)
+static void
+msn_soap_connection_handle_next(MsnSoapConnection *conn)
 {
-	MsnSoapConnection *conn = g_new0(MsnSoapConnection, 1);
-	conn->session = session;
-	conn->host = g_strdup(host);
-	conn->queue = g_queue_new();
-	return conn;
+	msn_soap_connection_sanitize(conn, FALSE);
+
+	conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
+
+	if (conn->current_request) {
+		MsnSoapRequest *req = conn->current_request;
+		conn->current_request = NULL;
+		msn_soap_connection_destroy_foreach_cb(req, conn);
+	}
 }
 
 static void
-msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl,
-		PurpleInputCondition cond)
+msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
+	const char *host, const char *path, gboolean secure,
+	MsnSoapCallback cb, gpointer cb_data, gboolean first)
 {
-	MsnSoapConnection *conn = data;
+	MsnSoapConnection *conn = msn_soap_get_connection(session, host);
+	MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
 
-	conn->connected = TRUE;
+	req->path = g_strdup(path);
+	req->message = message;
+	req->secure = secure;
+	req->cb = cb;
+	req->cb_data = cb_data;
 
-	if (conn->event_handle == 0)
-		conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, conn);
+	if (first) {
+		g_queue_push_head(conn->queue, req);
+	} else {
+		g_queue_push_tail(conn->queue, req);
+	}
+
+	if (conn->run_timer == 0)
+		conn->run_timer = purple_timeout_add(0, msn_soap_connection_run,
+			conn);
 }
 
-static void
-msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error,
-		gpointer data)
+void
+msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
+	const char *host, const char *path, gboolean secure,
+	MsnSoapCallback cb, gpointer cb_data)
 {
-	MsnSoapConnection *conn = data;
+	g_return_if_fail(message != NULL);
 
-	/* sslconn already frees the connection in case of error */
-	conn->ssl = NULL;
-
-	g_hash_table_remove(conn->session->soap_table, conn->host);
+	msn_soap_message_send_internal(session, message, host, path, secure,
+		cb, cb_data, FALSE);
 }
 
 static gboolean
@@ -259,65 +352,17 @@
 }
 
 static void
-msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
+msn_soap_message_add_header(MsnSoapMessage *message,
+		const char *name, const char *value)
 {
-	MsnSoapConnection *conn = data;
-	int count = 0, cnt, perrno;
-	/* This buffer needs to be larger than any packets received from
-		login.live.com or Adium will fail to receive the packet
-		(something weird with the login.live.com server). With NSS it works
-		fine, so I believe it's some bug with OS X */ 
-	char buf[16 * 1024];
-	gsize cursor;
-
-	if (conn->message == NULL) {
-		conn->message = msn_soap_message_new(NULL, NULL);
-	}
-
-	if (conn->buf == NULL) {
-		conn->buf = g_string_new_len(buf, 0);
-	}
-
-	cursor = conn->buf->len;
-	while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
-		purple_debug_info("soap", "read %d bytes\n", cnt);
-		count += cnt;
-		g_string_append_len(conn->buf, buf, cnt);
-	}
+	char *header = g_strdup_printf("%s: %s\r\n", name, value);
 
-	perrno = errno;
-	if (cnt < 0 && perrno != EAGAIN)
-		purple_debug_info("soap", "read: %s\n", g_strerror(perrno));
-
-#ifndef MSN_UNSAFE_DEBUG
-	if (conn->current_request->secure)
-		purple_debug_misc("soap", "Received secure request.\n");
-	else
-#endif
-	if (count != 0)
-		purple_debug_misc("soap", "current %s\n", conn->buf->str + cursor);
-
-	/* && count is necessary for Adium, on OS X the last read always
-	   return an error, so we want to proceed anyway. See #5212 for
-	   discussion on this and the above buffer size issues */
-	if(cnt < 0 && errno == EAGAIN && count == 0)
-		return;
-
-	/* msn_soap_process could alter errno */
-	msn_soap_process(conn);
-	
-	if (cnt < 0 && perrno != EAGAIN) {
-		/* It's possible msn_soap_process closed the ssl connection */
-		if (conn->ssl) {
-			purple_ssl_close(conn->ssl);
-			conn->ssl = NULL;
-			msn_soap_connection_handle_next(conn);
-		}
-	}
+	message->headers = g_slist_prepend(message->headers, header);
 }
 
 static void
-msn_soap_process(MsnSoapConnection *conn) {
+msn_soap_process(MsnSoapConnection *conn)
+{
 	gboolean handled = FALSE;
 	char *cursor;
 	char *linebreak;
@@ -429,9 +474,61 @@
 }
 
 static void
-msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond)
+msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
 {
-	msn_soap_write_cb_internal(data, fd, cond, FALSE);
+	MsnSoapConnection *conn = data;
+	int count = 0, cnt, perrno;
+	/* This buffer needs to be larger than any packets received from
+		login.live.com or Adium will fail to receive the packet
+		(something weird with the login.live.com server). With NSS it works
+		fine, so I believe it's some bug with OS X */
+	char buf[16 * 1024];
+	gsize cursor;
+
+	if (conn->message == NULL) {
+		conn->message = msn_soap_message_new(NULL, NULL);
+	}
+
+	if (conn->buf == NULL) {
+		conn->buf = g_string_new_len(buf, 0);
+	}
+
+	cursor = conn->buf->len;
+	while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
+		purple_debug_info("soap", "read %d bytes\n", cnt);
+		count += cnt;
+		g_string_append_len(conn->buf, buf, cnt);
+	}
+
+	perrno = errno;
+	if (cnt < 0 && perrno != EAGAIN)
+		purple_debug_info("soap", "read: %s\n", g_strerror(perrno));
+
+#ifndef MSN_UNSAFE_DEBUG
+	if (conn->current_request->secure)
+		purple_debug_misc("soap", "Received secure request.\n");
+	else
+#endif
+	if (count != 0)
+		purple_debug_misc("soap", "current %s\n", conn->buf->str + cursor);
+
+	/* && count is necessary for Adium, on OS X the last read always
+	   return an error, so we want to proceed anyway. See #5212 for
+	   discussion on this and the above buffer size issues */
+	if(cnt < 0 && errno == EAGAIN && count == 0)
+		return;
+
+	/* msn_soap_process could alter errno */
+	msn_soap_process(conn);
+
+	if (cnt < 0 && perrno != EAGAIN) {
+		/* It's possible msn_soap_process closed the ssl connection */
+		if (conn->ssl) {
+			purple_ssl_close(conn->ssl);
+			conn->ssl = NULL;
+			msn_soap_connection_handle_next(conn);
+		}
+	}
 }
 
 static gboolean
@@ -441,7 +538,8 @@
 	MsnSoapConnection *conn = data;
 	int written;
 
-	if (cond != PURPLE_INPUT_WRITE) return TRUE;
+	if (cond != PURPLE_INPUT_WRITE)
+		return TRUE;
 
 	written = purple_ssl_write(conn->ssl, conn->buf->str + conn->handled_len,
 		conn->buf->len - conn->handled_len);
@@ -451,7 +549,8 @@
 	else if (written <= 0) {
 		purple_ssl_close(conn->ssl);
 		conn->ssl = NULL;
-		if (!initial) msn_soap_connection_handle_next(conn);
+		if (!initial)
+			msn_soap_connection_handle_next(conn);
 		return FALSE;
 	}
 
@@ -475,13 +574,54 @@
 	return TRUE;
 }
 
+static void
+msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond)
+{
+	msn_soap_write_cb_internal(data, fd, cond, FALSE);
+}
+
+static void
+msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error,
+		gpointer data)
+{
+	MsnSoapConnection *conn = data;
+
+	/* sslconn already frees the connection in case of error */
+	conn->ssl = NULL;
+
+	g_hash_table_remove(conn->session->soap_table, conn->host);
+}
+
+static void
+msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl,
+		PurpleInputCondition cond)
+{
+	MsnSoapConnection *conn = data;
+
+	conn->connected = TRUE;
+
+	if (conn->run_timer == 0)
+		conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
+}
+
+MsnSoapMessage *
+msn_soap_message_new(const char *action, xmlnode *xml)
+{
+	MsnSoapMessage *message = g_new0(MsnSoapMessage, 1);
+
+	message->action = g_strdup(action);
+	message->xml = xml;
+
+	return message;
+}
+
 static gboolean
 msn_soap_connection_run(gpointer data)
 {
 	MsnSoapConnection *conn = data;
 	MsnSoapRequest *req = g_queue_peek_head(conn->queue);
 
-	conn->event_handle = 0;
+	conn->run_timer = 0;
 
 	if (req) {
 		if (conn->ssl == NULL) {
@@ -532,13 +672,13 @@
 			if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) {
 				/* Not connected => reconnect and retry */
 				purple_debug_info("soap", "not connected, reconnecting\n");
-				
+
 				conn->connected = FALSE;
 				conn->current_request = NULL;
 				msn_soap_connection_sanitize(conn, FALSE);
-				
+
 				g_queue_push_head(conn->queue, req);
-				conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, conn);
+				conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
 			}
 
 			g_free(body);
@@ -547,151 +687,3 @@
 
 	return FALSE;
 }
-
-void
-msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path, gboolean secure,
-	MsnSoapCallback cb, gpointer cb_data)
-{
-	msn_soap_message_send_internal(session, message, host, path, secure,
-		cb, cb_data, FALSE);
-}
-
-static void
-msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path, gboolean secure,
-	MsnSoapCallback cb, gpointer cb_data, gboolean first)
-{
-	MsnSoapConnection *conn = msn_soap_get_connection(session, host);
-	MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
-
-	req->path = g_strdup(path);
-	req->message = message;
-	req->secure = secure;
-	req->cb = cb;
-	req->cb_data = cb_data;
-
-	if (first) {
-		g_queue_push_head(conn->queue, req);
-	} else {
-		g_queue_push_tail(conn->queue, req);
-	}
-
-	if (conn->event_handle == 0)
-		conn->event_handle = purple_timeout_add(0, msn_soap_connection_run,
-			conn);
-}
-
-static void
-msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect)
-{
-	if (conn->event_handle) {
-		purple_input_remove(conn->event_handle);
-		conn->event_handle = 0;
-	}
-
-	if (conn->message) {
-		msn_soap_message_destroy(conn->message);
-		conn->message = NULL;
-	}
-
-	if (conn->buf) {
-		g_string_free(conn->buf, TRUE);
-		conn->buf = NULL;
-	}
-
-	if (conn->ssl && (disconnect || conn->close_when_done)) {
-		purple_ssl_close(conn->ssl);
-		conn->ssl = NULL;
-	}
-
-	if (conn->current_request) {
-		msn_soap_request_destroy(conn->current_request, FALSE);
-		conn->current_request = NULL;
-	}
-}
-
-static void
-msn_soap_connection_handle_next(MsnSoapConnection *conn)
-{
-	msn_soap_connection_sanitize(conn, FALSE);
-
-	conn->event_handle = purple_timeout_add(0, msn_soap_connection_run,	conn);
-
-	if (conn->current_request) {
-		MsnSoapRequest *req = conn->current_request;
-		conn->current_request = NULL;
-		msn_soap_connection_destroy_foreach_cb(req, conn);
-	}
-}
-
-static void
-msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data)
-{
-	MsnSoapRequest *req = item;
-
-	if (req->cb)
-		req->cb(req->message, NULL, req->cb_data);
-
-	msn_soap_request_destroy(req, FALSE);
-}
-
-static void
-msn_soap_connection_destroy(MsnSoapConnection *conn)
-{
-	if (conn->current_request) {
-		MsnSoapRequest *req = conn->current_request;
-		conn->current_request = NULL;
-		msn_soap_connection_destroy_foreach_cb(req, conn);
-	}
-
-	msn_soap_connection_sanitize(conn, TRUE);
-	g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
-	g_queue_free(conn->queue);
-
-	g_free(conn->host);
-	g_free(conn);
-}
-
-MsnSoapMessage *
-msn_soap_message_new(const char *action, xmlnode *xml)
-{
-	MsnSoapMessage *message = g_new0(MsnSoapMessage, 1);
-
-	message->action = g_strdup(action);
-	message->xml = xml;
-
-	return message;
-}
-
-void
-msn_soap_message_destroy(MsnSoapMessage *message)
-{
-	if (message) {
-		g_slist_foreach(message->headers, (GFunc)g_free, NULL);
-		g_slist_free(message->headers);
-		g_free(message->action);
-		if (message->xml)
-			xmlnode_free(message->xml);
-		g_free(message);
-	}
-}
-
-void
-msn_soap_message_add_header(MsnSoapMessage *message,
-		const char *name, const char *value)
-{
-	char *header = g_strdup_printf("%s: %s\r\n", name, value);
-
-	message->headers = g_slist_prepend(message->headers, header);
-}
-
-static void
-msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message)
-{
-	g_free(req->path);
-	if (!keep_message)
-		msn_soap_message_destroy(req->message);
-	g_free(req);
-}
-
--- a/libpurple/protocols/msn/soap.h	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/msn/soap.h	Sun Nov 30 19:41:51 2008 +0000
@@ -44,13 +44,8 @@
 
 MsnSoapMessage *msn_soap_message_new(const char *action, xmlnode *xml);
 
-void msn_soap_message_add_header(MsnSoapMessage *req,
-	const char *name, const char *value);
-
 void msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
 	const char *host, const char *path, gboolean secure,
 	MsnSoapCallback cb, gpointer cb_data);
 
-void msn_soap_message_destroy(MsnSoapMessage *message);
-
 #endif
--- a/libpurple/protocols/msn/switchboard.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Sun Nov 30 19:41:51 2008 +0000
@@ -81,6 +81,9 @@
 
 	swboard->destroying = TRUE;
 
+	if (swboard->reconn_timeout_h > 0)
+		purple_timeout_remove(swboard->reconn_timeout_h);
+
 	/* If it linked us is because its looking for trouble */
 	while (swboard->slplinks != NULL)
 		msn_slplink_destroy(swboard->slplinks->data);
--- a/libpurple/protocols/myspace/README	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/myspace/README	Sun Nov 30 19:41:51 2008 +0000
@@ -10,9 +10,6 @@
 
 For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM
 
-Windows installation: Unzip the archive to C:\Program Files\Pidgin
-Unix/source installation: run "make install"
-
 Usage:
 
 Login using your _email address_ you use to login to myspace.com. You can't
--- a/libpurple/protocols/myspace/message.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/myspace/message.c	Sun Nov 30 19:41:51 2008 +0000
@@ -613,6 +613,7 @@
 		const gchar *sep, 
 		const gchar *begin, const gchar *end)
 {
+	int num_items;
 	gchar **strings;
 	gchar **strings_tmp;
 	gchar *joined;
@@ -621,8 +622,10 @@
 
 	g_return_val_if_fail(msg != NULL, NULL);
 
+	num_items = g_list_length(msg);
+
 	/* Add one for NULL terminator for g_strjoinv(). */
-	strings = (gchar **)g_new0(gchar *, g_list_length(msg) + 1);
+	strings = (gchar **)g_new0(gchar *, num_items + 1);
 
 	strings_tmp = strings;
 	g_list_foreach(msg, gf, &strings_tmp);
@@ -632,7 +635,7 @@
 	g_free(joined);
 
 	/* Clean up. */
-	for (i = 0; i < g_list_length(msg); ++i) {
+	for (i = 0; i < num_items; ++i) {
 		g_free(strings[i]);
 	}
 
--- a/libpurple/protocols/qq/qq_network.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.c	Sun Nov 30 19:41:51 2008 +0000
@@ -126,8 +126,8 @@
 	/* get new server */
 	index  = rand() % count;
 	it = g_list_nth(qd->servers, index);
-    qd->curr_server = it->data;		/* do not free server_name */
-    if (qd->curr_server == NULL || strlen(qd->curr_server) <= 0 ) {
+	qd->curr_server = it->data;		/* do not free server_name */
+	if (qd->curr_server == NULL || strlen(qd->curr_server) <= 0 ) {
 		purple_debug_info("QQ", "Server name at %d is empty\n", index);
 		return FALSE;
 	}
--- a/libpurple/protocols/sametime/sametime.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Sun Nov 30 19:41:51 2008 +0000
@@ -4415,7 +4415,7 @@
     res = results->data;
 
   if(!code && res && res->matches) {
-    if(g_list_length(res->matches) == 1) {
+    if(!res->matches->next) {
       struct mwResolveMatch *match = res->matches->data;
       
       /* only one? that might be the right one! */
--- a/libpurple/protocols/yahoo/yahoochat.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Sun Nov 30 19:41:51 2008 +0000
@@ -513,12 +513,12 @@
 
 	c = purple_find_chat(gc, YAHOO_CHAT_ID);
 
-	if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) && members &&
-	   ((g_list_length(members) > 1) ||
+	if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) &&
+	    members && (members->next ||
 	     !g_ascii_strcasecmp(members->data, purple_connection_get_display_name(gc)))) {
-		int i;
+		GList *l;
 		GList *flags = NULL;
-		for (i = 0; i < g_list_length(members); i++)
+		for (l = members; l; l = l->next)
 			flags = g_list_append(flags, GINT_TO_POINTER(PURPLE_CBFLAGS_NONE));
 		if (c && purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) {
 			/* this might be a hack, but oh well, it should nicely */
--- a/libpurple/protocols/zephyr/zephyr.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Sun Nov 30 19:41:51 2008 +0000
@@ -343,15 +343,15 @@
    Converts strings to utf-8 if necessary using user specified encoding
 */
 
-static gchar *zephyr_recv_convert(PurpleConnection *gc,gchar *string, int len)
+static gchar *zephyr_recv_convert(PurpleConnection *gc, gchar *string)
 {
 	gchar *utf8;
 	GError *err = NULL;
 	zephyr_account *zephyr = gc->proto_data;
-	if (g_utf8_validate(string, len, NULL)) {
+	if (g_utf8_validate(string, -1, NULL)) {
 		return g_strdup(string);
 	} else {
-		utf8 = g_convert(string, len, "UTF-8", zephyr->encoding, NULL, NULL, &err);
+		utf8 = g_convert(string, -1, "UTF-8", zephyr->encoding, NULL, NULL, &err);
 		if (err) {
 			purple_debug_error("zephyr", "recv conversion error: %s\n", err->message);
 			utf8 = g_strdup(_("(There was an error converting this message.	 Check the 'Encoding' option in the Account Editor)"));
@@ -820,7 +820,7 @@
 		PurpleConvChat *gcc;
 		char *ptr = (char *) notice.z_message + (strlen(notice.z_message) + 1);
 		int len; 
-		char *sendertmp = g_strdup_printf("%s", zephyr->username);
+		char *stripped_sender;
 		int signature_length = strlen(notice.z_message);
 		int message_has_no_body = 0;
 		PurpleMessageFlags flags = 0;
@@ -843,24 +843,23 @@
 			tmpescape = g_markup_escape_text(buf, -1);
 			g_free(buf);
 			buf2 = zephyr_to_html(tmpescape);
-			buf3 = zephyr_recv_convert(gc,buf2, strlen(buf2));
+			buf3 = zephyr_recv_convert(gc, buf2);
 			g_free(buf2);
 			g_free(tmpescape);
 		}
 
+		stripped_sender = zephyr_strip_local_realm(zephyr,notice.z_sender);
+
 		if (!g_ascii_strcasecmp(notice.z_class, "MESSAGE") && !g_ascii_strcasecmp(notice.z_class_inst, "PERSONAL") 
 		    && !g_ascii_strcasecmp(notice.z_recipient,zephyr->username)) {
-			gchar* stripped_sender;
 			if (!g_ascii_strcasecmp(notice.z_message, "Automated reply:"))
 				flags |= PURPLE_MESSAGE_AUTO_RESP;
-			stripped_sender = zephyr_strip_local_realm(zephyr,notice.z_sender);
 			
 			if (!g_ascii_strcasecmp(notice.z_opcode,"PING"))
 				serv_got_typing(gc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, PURPLE_TYPING);
 			else
 				serv_got_im(gc, stripped_sender, buf3, flags, time(NULL));
 
-			g_free(stripped_sender);
 		} else {
 			zephyr_triple *zt1, *zt2;
 			gchar *send_inst_utf8;
@@ -878,15 +877,17 @@
 				serv_got_joined_chat(gc, zt2->id, zt2->name);
 				zephyr_chat_set_topic(gc,zt2->id,notice.z_class_inst);
 			}
-			g_free(sendertmp); /* fix memory leak? */
-			/* If the person is in the default Realm, then strip the 
-			   Realm from the sender field */
-			sendertmp = zephyr_strip_local_realm(zephyr,notice.z_sender);
-			send_inst = g_strdup_printf("%s %s",sendertmp,notice.z_class_inst);					
-			send_inst_utf8 = zephyr_recv_convert(gc,send_inst, strlen(send_inst));
-			if (!send_inst_utf8) {
-				purple_debug_error("zephyr","send_inst %s became null\n", send_inst);
-				send_inst_utf8 = "malformed instance";
+
+			if (!g_ascii_strcasecmp(notice.z_class_inst,"PERSONAL"))
+				send_inst_utf8 = g_strdup(stripped_sender);
+			else {
+				send_inst = g_strdup_printf("[%s] %s",notice.z_class_inst,stripped_sender);
+				send_inst_utf8 = zephyr_recv_convert(gc,send_inst);
+				g_free(send_inst);
+				if (!send_inst_utf8) {
+					purple_debug_error("zephyr","Failed to convert instance for sender %s.\n", stripped_sender);
+					send_inst_utf8 = g_strdup(stripped_sender);
+				}
 			}
 
 			gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
@@ -895,24 +896,22 @@
 #ifndef INET_ADDRSTRLEN
 #define INET_ADDRSTRLEN 16
 #endif
-			if (!purple_conv_chat_find_user(gcc, sendertmp)) {
+			if (!purple_conv_chat_find_user(gcc, stripped_sender)) {
 				gchar ipaddr[INET_ADDRSTRLEN];
 #ifdef HAVE_INET_NTOP
 				inet_ntop(AF_INET, &notice.z_sender_addr.s_addr, ipaddr, sizeof(ipaddr));
 #else
 				memcpy(ipaddr,inet_ntoa(notice.z_sender_addr),sizeof(ipaddr));
 #endif
-				purple_conv_chat_add_user(gcc, sendertmp, ipaddr, PURPLE_CBFLAGS_NONE, TRUE);
+				purple_conv_chat_add_user(gcc, stripped_sender, ipaddr, PURPLE_CBFLAGS_NONE, TRUE);
 			}
-			g_free(sendertmp);
 			serv_got_chat_in(gc, zt2->id, send_inst_utf8, 0, buf3, time(NULL));
-			g_free(send_inst);
 			g_free(send_inst_utf8);
-				
+
 			free_triple(zt1);
 		}
+		g_free(stripped_sender);
 		g_free(buf3);
-		
 	}
 }
 
@@ -2580,7 +2579,7 @@
 												gc->account);
 	gcc = purple_conversation_get_chat_data(gconv);
 
-	topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic,strlen(topic));
+	topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic);
 	purple_conv_chat_set_topic(gcc,sender,topic_utf8);
 	g_free(topic_utf8);
 	return;
--- a/libpurple/purple-remote	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/purple-remote	Sun Nov 30 19:41:51 2008 +0000
@@ -172,6 +172,10 @@
         status_id = purple.PurplePrimitiveGetIdFromType(status_type)
         return status_id
 
+    elif command == "getstatusmessage":
+        current = purple.PurpleSavedstatusGetCurrent()
+        return purple.PurpleSavedstatusGetMessage(current)
+
     elif command == "getinfo":
         account = findaccount(accountname, protocol)
         connection = cpurple.PurpleAccountGetConnection(account)
--- a/libpurple/request.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/request.c	Sun Nov 30 19:41:51 2008 +0000
@@ -887,7 +887,7 @@
 	purple_request_field_list_clear_selected(field);
 
 	if (!purple_request_field_list_get_multi_select(field) &&
-		g_list_length(items) > 1)
+		items && items->next)
 	{
 		purple_debug_warning("request",
 						   "More than one item added to non-multi-select "
--- a/libpurple/roomlist.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/libpurple/roomlist.c	Sun Nov 30 19:41:51 2008 +0000
@@ -265,6 +265,11 @@
 	g_return_if_fail(room != NULL);
 	g_return_if_fail(list->fields != NULL);
 
+	/* If this is the first call for this room, grab the first field in
+	 * the Roomlist's fields.  Otherwise, grab the field that is one
+	 * more than the number of fields already present for the room.
+         * (This works because g_list_nth_data() is zero-indexed and
+         * g_list_length() is one-indexed.) */
 	if (!room->fields)
 		f = list->fields->data;
 	else
--- a/pidgin/Makefile.am	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/Makefile.am	Sun Nov 30 19:41:51 2008 +0000
@@ -5,7 +5,6 @@
 		Makefile.mingw \
 		pidgin.pc.in \
 		pidgin-uninstalled.pc.in \
-		pidginstock-artwork.c \
 		win32/IdleTracker/Makefile.mingw \
 		win32/IdleTracker/idletrack.c \
 		win32/IdleTracker/idletrack.h \
--- a/pidgin/gtkblist.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/gtkblist.c	Sun Nov 30 19:41:51 2008 +0000
@@ -3320,6 +3320,7 @@
 	if (PURPLE_BLIST_NODE_IS_CHAT(node))
 	{
 		PurpleChat *chat;
+		GList *connections;
 		GList *cur;
 		struct proto_chat_entry *pce;
 		char *name, *value;
@@ -3330,7 +3331,8 @@
 		prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-		if (g_list_length(purple_connections_get_all()) > 1)
+		connections = purple_connections_get_all();
+		if (connections && connections->next)
 		{
 			tmp = g_markup_escape_text(chat->account->username, -1);
 			g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
@@ -3400,6 +3402,7 @@
 		PurpleBuddy *b;
 		PurplePresence *presence;
 		PurpleNotifyUserInfo *user_info;
+		GList *connections;
 		char *tmp;
 		time_t idle_secs, signon;
 
@@ -3421,7 +3424,8 @@
 		user_info = purple_notify_user_info_new();
 
 		/* Account */
-		if (full && g_list_length(purple_connections_get_all()) > 1)
+		connections = purple_connections_get_all();
+		if (full && connections && connections->next)
 		{
 			tmp = g_markup_escape_text(purple_account_get_username(
 									   purple_buddy_get_account(b)), -1);
--- a/pidgin/gtkconv.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/gtkconv.c	Sun Nov 30 19:41:51 2008 +0000
@@ -2759,26 +2759,16 @@
 {
 	PidginConversation *gtkconv = (PidginConversation *)user_data;
 	PurpleConversation *conv = gtkconv->active_conv;
-	FILE *fp;
 	PurpleBuddyIcon *icon;
 	const void *data;
 	size_t len;
 
-	if ((fp = g_fopen(filename, "wb")) == NULL) {
-		purple_notify_error(gtkconv, NULL, _("Unable to open file."), NULL);
-		return;
-	}
-
 	icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
 	data = purple_buddy_icon_get_data(icon, &len);
 
-	if ((len <= 0) || (data == NULL) || (fwrite(data, 1, len, fp) != len)) {
+	if ((len <= 0) || (data == NULL) || !purple_util_write_data_to_file_absolute(filename, data, len)) {
 		purple_notify_error(gtkconv, NULL, _("Unable to save icon file to disk."), NULL);
-		fclose(fp);
-		g_unlink(filename);
-		return;
-	}
-	fclose(fp);
+	}
 }
 
 static void
--- a/pidgin/gtknotify.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/gtknotify.c	Sun Nov 30 19:41:51 2008 +0000
@@ -730,7 +730,6 @@
 	GtkListStore *model = data->model;
 	GtkTreeIter iter;
 	GdkPixbuf *pixbuf;
-	guint col_num;
 	GList *row, *column;
 	guint n;
 
@@ -738,9 +737,6 @@
 
 	pixbuf = pidgin_create_prpl_icon(purple_connection_get_account(gc), 0.5);
 
-	/* +1 is for the automagically created Status column. */
-	col_num = g_list_length(results->columns) + 1;
-
 	for (row = results->rows; row != NULL; row = row->next) {
 
 		gtk_list_store_append(model, &iter);
@@ -776,6 +772,7 @@
 	guint col_num;
 	GList *columniter;
 	guint i;
+	GList *l;
 
 	GtkWidget *vbox;
 	GtkWidget *label;
@@ -869,8 +866,8 @@
 		i++;
 	}
 
-	for (i = 0; i < g_list_length(results->buttons); i++) {
-		PurpleNotifySearchButton *b = g_list_nth_data(results->buttons, i);
+	for (l = results->buttons; l; l = l->next) {
+		PurpleNotifySearchButton *b = l->data;
 		GtkWidget *button = NULL;
 		switch (b->type) {
 			case PURPLE_NOTIFY_BUTTON_LABELED:
--- a/pidgin/gtkrequest.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/gtkrequest.c	Sun Nov 30 19:41:51 2008 +0000
@@ -853,12 +853,11 @@
 create_choice_field(PurpleRequestField *field)
 {
 	GtkWidget *widget;
-	GList *labels;
+	GList *labels = purple_request_field_choice_get_labels(field);
+	int num_labels = g_list_length(labels);
 	GList *l;
 
-	labels = purple_request_field_choice_get_labels(field);
-
-	if (g_list_length(labels) > 5)
+	if (num_labels > 5)
 	{
 		GtkWidget *menu;
 		GtkWidget *item;
@@ -892,7 +891,7 @@
 		GtkWidget *radio;
 		gint i;
 
-		if (g_list_length(labels) == 2)
+		if (num_labels == 2)
 			box = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 		else
 			box = gtk_vbox_new(FALSE, 0);
--- a/pidgin/gtksavedstatuses.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/gtksavedstatuses.c	Sun Nov 30 19:41:51 2008 +0000
@@ -331,7 +331,8 @@
 	}
 	g_list_free(sel_paths);
 
-	if (g_list_length(sel_titles) == 1) {
+	g_return_if_fail(sel_titles != NULL);
+	if (!sel_titles->next) {
 		title = g_strdup_printf(_("Are you sure you want to delete %s?"),
 				(const gchar *)sel_titles->data);
 		handle = purple_savedstatus_find(sel_titles->data);
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in	Sun Nov 30 19:41:51 2008 +0000
@@ -392,3 +392,20 @@
 wink.png	    ;-)     ;)
 sad.png		    :[
 kiss.png            :x
+
+[XMPP]
+# XMPP emoticons
+smile.png                 :)    :-)    =)
+smile-big.png             :D    :-D    =D
+wink.png                  ;)    ;-)    ;^)
+shock.png                 :-o
+tongue.png                :P    :-P
+glasses-cool.png          B-)
+angry.png                 X-(
+sad.png                   :(
+crying.png                :'(
+neutral.png               :-|
+thinking.png              :-/
+love.png                  <3
+monkey.png                :(|)
+victory.png               \\m/
--- a/pidgin/pixmaps/emotes/small/16/small.theme.in	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/pixmaps/emotes/small/16/small.theme.in	Sun Nov 30 19:41:51 2008 +0000
@@ -154,3 +154,20 @@
 wink.png	    ;-)     ;)
 sad.png		    :[
 kiss.png            :x
+
+[XMPP]
+# XMPP emoticons
+smile.png                 :)    :-)    =)
+smile-big.png             :D    :-D    =D
+wink.png                  ;)    ;-)    ;^)
+shock.png                 :-o
+tongue.png                :P    :-P
+glasses-cool.png          B-)
+angry.png                 X-(
+sad.png                   :(
+crying.png                :'(
+neutral.png               :-|
+thinking.png              :-/
+love.png                  <3
+monkey.png                :(|)
+victory.png               \\m/
--- a/pidgin/plugins/history.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/plugins/history.c	Sun Nov 30 19:41:51 2008 +0000
@@ -47,10 +47,11 @@
 
 	convtype = purple_conversation_get_type(c);
 	gtkconv = PIDGIN_CONVERSATION(c);
-	if (gtkconv == NULL)
-		return;
+	g_return_if_fail(gtkconv != NULL);
 
-	if (convtype == PURPLE_CONV_TYPE_IM && g_list_length(gtkconv->convs) < 2)
+	/* An IM which is the first active conversation. */
+	g_return_if_fail(gtkconv->convs != NULL);
+	if (convtype == PURPLE_CONV_TYPE_IM && !gtkconv->convs->next)
 	{
 		GSList *buddies;
 		GSList *cur;
--- a/pidgin/win32/winpidgin.c	Mon Nov 24 22:12:36 2008 +0000
+++ b/pidgin/win32/winpidgin.c	Sun Nov 30 19:41:51 2008 +0000
@@ -621,9 +621,22 @@
 	char *tmp;
 	int pidgin_argc = __argc;
 	char **pidgin_argv = __argv;
+	int i;
+	BOOL debug = FALSE, help = FALSE, version = FALSE, multiple = FALSE;
 
 	/* If debug or help or version flag used, create console for output */
-	if (strstr(lpszCmdLine, "-d") || strstr(lpszCmdLine, "-h") || strstr(lpszCmdLine, "-v")) {
+	for (i = 1; i < __argc; i++) {
+		if (strstr(__argv[i], "-d") || strstr(__argv[i], "--debug"))
+			debug = TRUE;
+		else if (strstr(__argv[i], "-h") || strstr(__argv[i], "--help"))
+			help = TRUE;
+		else if (strstr(__argv[i], "-v") || strstr(__argv[i], "--version"))
+			version = TRUE;
+		else if (strstr(__argv[i], "-m") || strstr(__argv[i], "--multiple"))
+			multiple = TRUE;
+	}
+
+	if (debug || help || version) {
 		/* If stdout hasn't been redirected to a file, alloc a console
 		 *  (_istty() doesn't work for stuff using the GUI subsystem) */
 		if (_fileno(stdout) == -1 || _fileno(stdout) == -2) {
@@ -710,8 +723,8 @@
 	winpidgin_add_stuff_to_path();
 
 	/* If help, version or multiple flag used, do not check Mutex */
-	if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v"))
-		if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && strstr(lpszCmdLine, "-m") == NULL))
+	if (!help && !version)
+		if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple))
 			return 0;
 
 	/* Now we are ready for Pidgin .. */
--- a/po/de.po	Mon Nov 24 22:12:36 2008 +0000
+++ b/po/de.po	Sun Nov 30 19:41:51 2008 +0000
@@ -11,7 +11,7 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-10-28 17:46+0100\n"
+"POT-Creation-Date: 2008-11-25 22:03+0100\n"
 "PO-Revision-Date: 2008-10-28 17:46+0100\n"
 "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
@@ -273,7 +273,6 @@
 msgid "Add Buddy Pounce"
 msgstr "Buddy-Alarm hinzufügen"
 
-#. if (q_bud && is_online(q_bud->status)) {
 msgid "Send File"
 msgstr "Datei versenden"
 
@@ -1340,7 +1339,7 @@
 #. PurpleStatusPrimitive
 #. id - use default
 #. name - use default
-#. savable
+#. saveable
 #. user_settable
 #. not independent
 #. Attributes - each status can have a message.
@@ -4977,7 +4976,7 @@
 #. primitive
 #. ID
 #. name - use default
-#. savable
+#. saveable
 #. should be user_settable some day
 #. independent
 msgid "Artist"
@@ -5190,8 +5189,7 @@
 #. *< id
 #. *< name
 #. *< version
-#. *  summary
-#. *  description
+#. *< summary
 msgid "Windows Live Messenger Protocol Plugin"
 msgstr "Windows Live Messenger Protokoll-Plugin"
 
@@ -6217,7 +6215,7 @@
 msgstr "Bewertung zum Client"
 
 msgid "Service unavailable"
-msgstr "Dienst nicht unerreichbar"
+msgstr "Dienst nicht verfügbar"
 
 msgid "Service not defined"
 msgstr "Dienst nicht definiert"
@@ -6425,6 +6423,7 @@
 "Leerzeichen enthalten oder nur aus Ziffern bestehen."
 
 #. Unregistered screen name
+#. uid is not exist
 msgid "Invalid username."
 msgstr "Ungültiger Benutzername."
 
@@ -6858,10 +6857,12 @@
 "beginnen und nur Buchstaben, Ziffern und Leerzeichen enthalten oder nur aus "
 "Ziffern bestehen."
 
-msgid "Unable To Add"
+#, fuzzy
+msgid "Unable to Add"
 msgstr "Kann nicht hinzufügen"
 
-msgid "Unable To Retrieve Buddy List"
+#, fuzzy
+msgid "Unable to Retrieve Buddy List"
 msgstr "Konnte Buddy-Liste nicht laden"
 
 msgid ""
@@ -7086,42 +7087,6 @@
 "ist notwendig für IM-Bilder. Da Ihre IP-Adresse verwendet wird, kann dies "
 "eine Verletzung der Privatsphäre bedeuten."
 
-msgid "Primary Information"
-msgstr "Primäre Informationen"
-
-msgid "Personal Introduction"
-msgstr "Persönliche Vorstellung"
-
-msgid "QQ Number"
-msgstr "QQ-Nummer"
-
-msgid "Country/Region"
-msgstr "Land/Region"
-
-msgid "Province/State"
-msgstr "Provinz/Staat"
-
-msgid "Horoscope Symbol"
-msgstr "Horoskopsymbol"
-
-msgid "Zodiac Sign"
-msgstr "Sternzeichen"
-
-msgid "Blood Type"
-msgstr "Blutgruppe"
-
-msgid "College"
-msgstr "College"
-
-msgid "Zipcode"
-msgstr "PLZ"
-
-msgid "Cellphone Number"
-msgstr "Handy-Telefonnummer"
-
-msgid "Phone Number"
-msgstr "Telefonnummer"
-
 msgid "Aquarius"
 msgstr "Wassermann"
 
@@ -7197,100 +7162,189 @@
 msgid "Other"
 msgstr "Andere"
 
-msgid "Modify information"
+#, fuzzy
+msgid "Visible"
+msgstr "Unsichtbar"
+
+msgid "Firend Only"
+msgstr ""
+
+#, fuzzy
+msgid "Private"
+msgstr "Privatsphäre"
+
+msgid "QQ Number"
+msgstr "QQ-Nummer"
+
+msgid "Country/Region"
+msgstr "Land/Region"
+
+msgid "Province/State"
+msgstr "Provinz/Staat"
+
+msgid "Zipcode"
+msgstr "PLZ"
+
+msgid "Phone Number"
+msgstr "Telefonnummer"
+
+#, fuzzy
+msgid "Authorize adding"
+msgstr "Buddy autorisieren?"
+
+msgid "Cellphone Number"
+msgstr "Handy-Telefonnummer"
+
+msgid "Personal Introduction"
+msgstr "Persönliche Vorstellung"
+
+#, fuzzy
+msgid "City/Area"
+msgstr "Stadt"
+
+#, fuzzy
+msgid "Publish Mobile"
+msgstr "Handy (privat)"
+
+#, fuzzy
+msgid "Publish Contact"
+msgstr "Kontakt-Alias"
+
+msgid "College"
+msgstr "College"
+
+#, fuzzy
+msgid "Horoscope"
+msgstr "Horoskopsymbol"
+
+#, fuzzy
+msgid "Zodiac"
+msgstr "Sternzeichen"
+
+#, fuzzy
+msgid "Blood"
+msgstr "Blockiert"
+
+#, fuzzy
+msgid "True"
+msgstr "Stier"
+
+#, fuzzy
+msgid "False"
+msgstr "Gescheitert"
+
+#, fuzzy
+msgid "Modify Contact"
+msgstr "Konto bearbeiten"
+
+#, fuzzy
+msgid "Modify Address"
+msgstr "Privatadresse"
+
+#, fuzzy
+msgid "Modify Extended Information"
 msgstr "Informationen bearbeiten"
 
-msgid "Update information"
-msgstr "Informationen aktualisieren"
-
-#. TODO: We don't really need to notify the user about this, do we?
-#. TODO: Does the user really need to be notified about this?
-msgid "QQ Buddy"
-msgstr "QQ-Buddy"
-
-msgid "Successed:"
-msgstr "Erfolgreich:"
-
-msgid "Change buddy information."
+#, fuzzy
+msgid "Modify Information"
+msgstr "Informationen bearbeiten"
+
+#, fuzzy
+msgid "Update"
+msgstr "Letzte Aktualisierung"
+
+#, fuzzy
+msgid "Could not change buddy information."
 msgstr "Buddy-Informationen bearbeiten"
 
 #, c-format
-msgid ""
-"Setting custom faces is not currently supported. Please choose an image from "
-"%s."
-msgstr ""
-"Das Setzen von benutzerdefinierten Gesichtern wird momentan nicht "
-"unterstützt. Bitte wählen Sie ein Bild von %s."
-
-msgid "Invalid QQ Face"
-msgstr "Ungültiges QQ-Gesicht"
-
-# c-format
-#, c-format
-msgid "You rejected %d's request"
-msgstr "Sie haben die Anfrage von %d abgelehnt"
-
-msgid "Reject request"
-msgstr "Anfrage ablehnen"
-
-#. title
-msgid "Sorry, you are not my style..."
+msgid "%d needs Q&A"
+msgstr ""
+
+#, fuzzy
+msgid "Add buddy Q&A"
+msgstr "Buddy hinzufügen"
+
+#, fuzzy
+msgid "Input answer here"
+msgstr "Anfrage hier eingeben"
+
+msgid "Send"
+msgstr "Senden"
+
+#, fuzzy
+msgid "Invalid answer."
+msgstr "Ungültiger Benutzername."
+
+msgid "Authorization denied message:"
+msgstr "Nachricht für die Ablehnung der Autorisierung:"
+
+#, fuzzy
+msgid "Sorry, You are not my style."
 msgstr "Tut mir Leid, du bist nicht mein Typ..."
 
-msgid "Add buddy with auth request failed"
-msgstr "Benutzer hinzufügen, wenn Autorisierungsanfrage fehlschlug"
-
-msgid "Failed:"
-msgstr "Gescheitert:"
-
-msgid "Remove buddy"
-msgstr "Buddy entfernen"
-
-msgid "Remove from other's buddy list"
-msgstr "Von der Liste des Buddys entfernen"
-
 #, c-format
 msgid "%d needs authentication"
 msgstr "%d benötigt Authentifizierung"
 
+#, fuzzy
+msgid "Add buddy authorize"
+msgstr "Benutzer zu Ihrer Buddy-Liste hinzufügen?"
+
 msgid "Input request here"
 msgstr "Anfrage hier eingeben"
 
-#. TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands
 msgid "Would you be my friend?"
 msgstr "Möchten Sie mein Freund sein?"
 
-#. multiline
-#. masked
-#. hint
-msgid "Send"
-msgstr "Senden"
-
-#, c-format
-msgid "Add into %d's buddy list"
-msgstr "Zu %ds Buddy-Liste hinzufügen"
-
-msgid "QQ Number Error"
-msgstr "Fehler in QQ-Nummer"
+msgid "QQ Buddy"
+msgstr "QQ-Buddy"
+
+#, fuzzy
+msgid "Add buddy"
+msgstr "Buddy hinzufügen"
 
 msgid "Invalid QQ Number"
 msgstr "Ungültige QQ-Nummer"
 
+#, fuzzy
+msgid "Failed sending authorize"
+msgstr "Bitte autorisiere mich!"
+
+#, fuzzy, c-format
+msgid "Failed removing buddy %d"
+msgstr "Kontakt konnte nicht entfernt werden"
+
+#, fuzzy, c-format
+msgid "Failed removing me from %d's buddy list"
+msgstr "Von der Liste des Buddys entfernen"
+
+#, fuzzy
+msgid "No reason given"
+msgstr "Kein Grund angegeben."
+
+#. only need to get value
+#, c-format
+msgid "You have been added by %s"
+msgstr "Sie wurden von %s hinzugefügt"
+
+msgid "Would you like to add him?"
+msgstr "Möchten Sie ihn hinzufügen?"
+
+#, fuzzy, c-format
+msgid "Rejected by %s"
+msgstr "Anfrage abgelehnt von %s"
+
+#, c-format
+msgid "Message: %s"
+msgstr "Nachricht: %s"
+
 msgid "ID: "
 msgstr "ID: "
 
 msgid "Group ID"
 msgstr "Gruppen-ID"
 
-msgid "Creator"
-msgstr "Ersteller"
-
-msgid "Group Description"
-msgstr "Gruppenbeschreibung"
-
-msgid "Auth"
-msgstr "Autorisieren"
-
 msgid "QQ Qun"
 msgstr "QQ-Qun"
 
@@ -7300,75 +7354,71 @@
 msgid "You can only search for permanent Qun\n"
 msgstr "Sie können nur nach permanenten Qun suchen\n"
 
-#, c-format
-msgid "%d request to join Qun %d"
-msgstr "%d möchte dem Qun %d beitreten"
-
-#, c-format
-msgid "Message: %s"
-msgstr "Nachricht: %s"
-
-msgid "QQ Qun Operation"
-msgstr "QQ-Qun-Operation"
-
-msgid "Approve"
-msgstr "Akzeptieren"
-
-#, c-format
-msgid "Failed to join Qun %d, operated by admin %d"
-msgstr "Dem Qun %d, moderiert von admin %d, konnte nicht beigetreten werden"
-
-#, c-format
-msgid "Successed to join Qun %d, operated by admin %d"
-msgstr "Erfolgreicher Beitritt in den Qun %d, moderiert vom Admin %d"
-
-#, c-format
-msgid "[%d] removed from Qun \"%d\""
-msgstr "[%d] vom Qun „%d“ entfernt"
-
-msgid "Notice:"
+#, fuzzy
+msgid "Not member"
+msgstr "Ich bin kein Mitglied"
+
+msgid "Member"
+msgstr "Mitglied"
+
+#, fuzzy
+msgid "Requesting"
+msgstr "Anfrage-Dialog"
+
+#, fuzzy
+msgid "Admin"
+msgstr "Adium"
+
+#, fuzzy
+msgid "Notice"
 msgstr "Bemerkung:"
 
-#, c-format
-msgid "[%d] added to Qun \"%d\""
-msgstr "[%d] zum Qun „%d“ hinzugefügt"
-
-msgid "I am not a member"
-msgstr "Ich bin kein Mitglied"
-
-msgid "I am a member"
-msgstr "Ich bin Mitglied"
-
-msgid "I am requesting"
-msgstr "Ich frage an"
-
-msgid "I am the admin"
-msgstr "Ich bin der Admin"
-
-msgid "Unknown status"
-msgstr "Unbekannter Status"
+#, fuzzy
+msgid "Detail"
+msgstr "Standard"
+
+msgid "Creator"
+msgstr "Ersteller"
+
+#, fuzzy
+msgid "About me"
+msgstr "Über %s"
+
+#, fuzzy
+msgid "Category"
+msgstr "Chatfehler"
 
 msgid "The Qun does not allow others to join"
 msgstr "Diesen Qun können andere nicht beitreten"
 
-msgid "Remove from Qun"
-msgstr "vom Qun entfernen"
-
-msgid "Join to Qun"
+#, fuzzy
+msgid "Join QQ Qun"
 msgstr "Qun betreten"
 
 #, c-format
+msgid "Successfully joined Qun %s (%d)"
+msgstr ""
+
+#, fuzzy
+msgid "Successfully joined Qun"
+msgstr "Sie haben einen Qun angelegt"
+
+#, c-format
 msgid "Qun %d denied to join"
 msgstr "Qun %d hat Ihren Beitritt abgelehnt"
 
+msgid "QQ Qun Operation"
+msgstr "QQ-Qun-Operation"
+
+msgid "Failed:"
+msgstr "Gescheitert:"
+
 msgid "Join Qun, Unknow Reply"
 msgstr "Qun-Beitritt, Unbekannte Antwort"
 
-msgid "You entered a group ID outside the acceptable range"
-msgstr "Sie haben eine Gruppen-ID außerhalb des erlaubten Bereichs angegeben"
-
-msgid "Are you sure you want to leave this Qun?"
-msgstr "Wollen Sie dieses Qun wirklich verlassen?"
+#, fuzzy
+msgid "Quit Qun"
+msgstr "QQ-Qun"
 
 msgid ""
 "Note, if you are the creator, \n"
@@ -7377,43 +7427,51 @@
 "Beachten Sie, dass diese Operation den Qun entfernen könnte, \n"
 "wenn Sie der Ersteller sind."
 
-#. we want to see window
-msgid "Do you want to approve the request?"
-msgstr "Wollen sie die Anfrage akzeptieren?"
-
-msgid "Change Qun member"
+#, fuzzy
+msgid "Sorry, you are not our style ..."
+msgstr "Tut mir Leid, du bist nicht mein Typ..."
+
+#, fuzzy
+msgid "Successfully changed Qun member"
 msgstr "Qun-Mitglied ändern"
 
-msgid "Change Qun information"
+#, fuzzy
+msgid "Successfully changed Qun information"
 msgstr "Qun-Informationen bearbeiten"
 
 msgid "You have successfully created a Qun"
 msgstr "Sie haben einen Qun angelegt"
 
-msgid "Would you like to set up the detail information now?"
+#, fuzzy
+msgid "Would you like to set detailed information now?"
 msgstr "Möchten Sie jetzt Detail-Informationen einstellen?"
 
 msgid "Setup"
 msgstr "Setup"
 
-#, c-format
-msgid ""
-"%s\n"
-"\n"
-"%s"
-msgstr ""
-"%s\n"
-"\n"
-"%s"
-
-msgid "QQ Server News"
-msgstr "QQ-Server-News"
-
-msgid "System Message"
-msgstr "Systemnachricht"
-
-msgid "Failed to send IM."
-msgstr "Senden der Nachricht fehlgeschlagen."
+#, fuzzy, c-format
+msgid "%d requested to join Qun %d for %s"
+msgstr "%d möchte dem Qun %d beitreten"
+
+#, c-format
+msgid "%d request to join Qun %d"
+msgstr "%d möchte dem Qun %d beitreten"
+
+#, c-format
+msgid "Failed to join Qun %d, operated by admin %d"
+msgstr "Dem Qun %d, moderiert von admin %d, konnte nicht beigetreten werden"
+
+#, c-format
+msgid "<b>Joining Qun %d is approved by admin %d for %s</b>"
+msgstr ""
+
+#, fuzzy, c-format
+msgid "<b>Removed buddy %d.</b>"
+msgstr "Buddy entfernen"
+
+#, c-format
+msgid "<b>New buddy %d joined.</b>"
+msgstr ""
 
 #, c-format
 msgid "Unknown-%d"
@@ -7422,9 +7480,6 @@
 msgid "Level"
 msgstr "Stufe"
 
-msgid "Member"
-msgstr "Mitglied"
-
 msgid " VIP"
 msgstr " VIP"
 
@@ -7452,24 +7507,36 @@
 msgid "Invalid name"
 msgstr "QQ: Ungültiger Name"
 
-#, c-format
-msgid "<b>Current Online</b>: %d<br>\n"
+#, fuzzy
+msgid "Select icon..."
+msgstr "Ordner auswählen..."
+
+#, fuzzy, c-format
+msgid "<b>Login time</b>: %d-%d-%d, %d:%d:%d<br>\n"
+msgstr "<b>Anmeldezeit</b>: %s<br>\n"
+
+#, fuzzy, c-format
+msgid "<b>Total Online Buddies</b>: %d<br>\n"
 msgstr "<b>Aktuell online:</b> %d<br>\n"
 
-#, c-format
-msgid "<b>Last Refresh</b>: %s<br>\n"
+#, fuzzy, c-format
+msgid "<b>Last Refresh</b>: %d-%d-%d, %d:%d:%d<br>\n"
 msgstr "<b>Letzte Aktualisierung</b>: %s<br>\n"
 
 #, c-format
 msgid "<b>Server</b>: %s<br>\n"
 msgstr "<b>Server</b>: %s<br>\n"
 
+#, fuzzy, c-format
+msgid "<b>Client Tag</b>: %s<br>\n"
+msgstr "<b>Anmeldezeit</b>: %s<br>\n"
+
 #, c-format
 msgid "<b>Connection Mode</b>: %s<br>\n"
 msgstr "<b>Verbindungsmodus</b>: %s<br>\n"
 
-#, c-format
-msgid "<b>My Internet Address</b>: %s<br>\n"
+#, fuzzy, c-format
+msgid "<b>My Internet IP</b>: %s:%d<br>\n"
 msgstr "<b>Meine Internet-Adresse</b>: %s<br>\n"
 
 #, c-format
@@ -7492,23 +7559,44 @@
 msgid "<b>Received Duplicate</b>: %lu<br>\n"
 msgstr "<b>Duplikat empfangen</b>: %lu<br>\n"
 
-#, c-format
-msgid "<b>Login Time</b>: %s<br>\n"
+#, fuzzy, c-format
+msgid "<b>Time</b>: %d-%d-%d, %d:%d:%d<br>\n"
 msgstr "<b>Anmeldezeit</b>: %s<br>\n"
 
-#, c-format
-msgid "<b>Last Login IP</b>: %s<br>\n"
-msgstr "<b>Letzte Anmelde-IP</b>: %s<br>\n"
-
-#, c-format
-msgid "<b>Last Login Time</b>: %s\n"
-msgstr "<b>Letzte Anmeldezeit</b>: %s\n"
+#, fuzzy, c-format
+msgid "<b>IP</b>: %s<br>\n"
+msgstr "<b>Server</b>: %s<br>\n"
 
 msgid "Login Information"
 msgstr "Login-Informationen"
 
-msgid "Set My Information"
-msgstr "Meine Informationen festlegen"
+msgid "<p><b>Original Author</b>:<br>\n"
+msgstr ""
+
+msgid "<p><b>Code Contributors</b>:<br>\n"
+msgstr ""
+
+#, fuzzy
+msgid "<p><b>Lovely Patch Writers</b>:<br>\n"
+msgstr "<b>Letzte Aktualisierung</b>: %s<br>\n"
+
+#, fuzzy
+msgid "<p><b>Acknowledgement</b>:<br>\n"
+msgstr "<b>Gesendet</b>: %lu<br>\n"
+
+msgid "<p><i>And, all the boys in the backroom...</i><br>\n"
+msgstr ""
+
+msgid "<i>Feel free to join us!</i> :)"
+msgstr ""
+
+#, fuzzy, c-format
+msgid "About OpenQ r%s"
+msgstr "Über %s"
+
+#, fuzzy
+msgid "Change Icon"
+msgstr "Icon speichern"
 
 msgid "Change Password"
 msgstr "Passwort ändern"
@@ -7516,11 +7604,12 @@
 msgid "Account Information"
 msgstr "Kontoinformationen"
 
-msgid "Leave the QQ Qun"
-msgstr "Diesen QQ-Qun verlassen"
-
-msgid "Block this buddy"
-msgstr "Diesen Buddy blockieren"
+msgid "Update all QQ Quns"
+msgstr ""
+
+#, fuzzy
+msgid "About OpenQ"
+msgstr "Über %s"
 
 #. *< type
 #. *< ui_requirement
@@ -7532,12 +7621,27 @@
 #. *< version
 #. *  summary
 #. *  description
-msgid "QQ Protocol\tPlugin"
+#, fuzzy
+msgid "QQ Protocol Plugin"
 msgstr "QQ-Protokoll-Plugin"
 
 msgid "Auto"
 msgstr "Auto"
 
+#, fuzzy
+msgid "Select Server"
+msgstr "Benutzer wählen"
+
+msgid "QQ2005"
+msgstr ""
+
+msgid "QQ2007"
+msgstr ""
+
+msgid "QQ2008"
+msgstr ""
+
+#. #endif
 msgid "Connect by TCP"
 msgstr "Über TCP verbinden"
 
@@ -7547,40 +7651,82 @@
 msgid "Show server news"
 msgstr "Server-News anzeigen"
 
-msgid "Keep alive interval(s)"
+#, fuzzy
+msgid "Keep alive interval (seconds)"
 msgstr "Intervall(e) zum Aufrechterhalten der Verbindung (Keep alive)"
 
-msgid "Update interval(s)"
+#, fuzzy
+msgid "Update interval (seconds)"
 msgstr "Aktualisierungsintervall(e)"
 
-#, c-format
-msgid "Invalid token reply code, 0x%02X"
-msgstr "Ungültiger Token-Antwort-Code, 0x%02X"
+#, fuzzy
+msgid "Can not decrypt server reply"
+msgstr "Kann die Antwort der Anmeldung nicht entschlüsseln"
+
+#, fuzzy
+msgid "Can not decrypt get server reply"
+msgstr "Kann die Antwort der Anmeldung nicht entschlüsseln"
+
+#, c-format
+msgid "Failed requesting token, 0x%02X"
+msgstr ""
 
 #, c-format
 msgid "Invalid token len, %d"
 msgstr "Ungültige Länge des Tokens, %d"
 
-msgid "Unable login for not support Redirect_EX now"
-msgstr "Anmeldung nicht möglich, Redirect_EX wird noch nicht unterstützt"
-
-#, c-format
-msgid "Error password: %s"
-msgstr "Passwort-Fehler: %s"
-
-#, c-format
-msgid "Need active: %s"
-msgstr "Brauche aktiv: %s"
-
-#, c-format
-msgid "Unable login for unknow reply code 0x%02X"
+#. extend redirect used in QQ2006
+msgid "Redirect_EX is not currently supported"
+msgstr ""
+
+#. need activation
+#. need activation
+#. need activation
+#, fuzzy
+msgid "Activation required"
+msgstr "Registrierung erforderlich"
+
+#, fuzzy, c-format
+msgid "Unknow reply code when login (0x%02X)"
 msgstr "Anmeldung nicht möglich, unbekannter Antwort-Code 0x%02X"
 
 msgid "Keep alive error"
 msgstr "Fehler beim Aufrechterhalten der Verbindung (Keep alive)"
 
-msgid "Failed to connect all servers"
-msgstr "Konnte nicht alle Server verbinden"
+#, fuzzy
+msgid "Requesting captcha ..."
+msgstr "Bitte um %ss Aufmerksamkeit..."
+
+msgid "Checking code of captcha ..."
+msgstr ""
+
+msgid "Failed captcha verify"
+msgstr ""
+
+#, fuzzy
+msgid "Captcha Image"
+msgstr "Bild speichern"
+
+#, fuzzy
+msgid "Enter code"
+msgstr "Geben Sie ein Passwort ein"
+
+msgid "QQ Captcha Verifing"
+msgstr ""
+
+#, fuzzy
+msgid "Enter the text from the image"
+msgstr "Bitte geben Sie den Namen der Gruppe ein"
+
+#, c-format
+msgid "Unknow reply code when checking password (0x%02X)"
+msgstr ""
+
+#, c-format
+msgid ""
+"Unknow reply code when login (0x%02X):\n"
+"%s"
+msgstr ""
 
 #. we didn't successfully connect. tdt->toc_fd is valid here
 msgid "Unable to connect."
@@ -7606,7 +7752,10 @@
 msgid "Connection lost"
 msgstr "Verbindung verloren"
 
-#. Update the login progress status display
+#, fuzzy
+msgid "Get server ..."
+msgstr "Benutzer-Info setzen..."
+
 msgid "Request token"
 msgstr "Anfragekürzel"
 
@@ -7616,13 +7765,34 @@
 msgid "Invalid server or port"
 msgstr "Ungültiger Server oder Port"
 
-#, c-format
-msgid "Connecting server %s, retries %d"
-msgstr "Verbinde zu Server %s, %d Wiederholungen"
+#, fuzzy
+msgid "Connecting server ..."
+msgstr "Verbindungsserver"
 
 msgid "QQ Error"
 msgstr "QQ-Fehler"
 
+msgid "Failed to send IM."
+msgstr "Senden der Nachricht fehlgeschlagen."
+
+#, fuzzy, c-format
+msgid ""
+"Server News:\n"
+"%s\n"
+"%s\n"
+"%s"
+msgstr "QQ-Server-News"
+
+#, c-format
+msgid "From %s:"
+msgstr "Von %s:"
+
+#, fuzzy, c-format
+msgid ""
+"Server notice From %s: \n"
+"%s"
+msgstr "Anleitung vom Server: %s"
+
 msgid "Unknow SERVER CMD"
 msgstr "Unbekanntes SERVER-CMD"
 
@@ -7637,16 +7807,21 @@
 msgid "QQ Qun Command"
 msgstr "QQ-Qun-Kommando"
 
-#, c-format
-msgid "You are not a member of QQ Qun \"%s\"\n"
+#, fuzzy, c-format
+msgid "Not a member of room \"%s\"\n"
 msgstr "Sie sind kein Mitglied des Qun „%s“\n"
 
 msgid "Can not decrypt login reply"
 msgstr "Kann die Antwort der Anmeldung nicht entschlüsseln"
 
-msgid "Unknow reply CMD"
+#, fuzzy
+msgid "Unknow LOGIN CMD"
 msgstr "Unbekanntes Antwort-CMD"
 
+#, fuzzy
+msgid "Unknow CLIENT CMD"
+msgstr "Unbekanntes SERVER-CMD"
+
 #, c-format
 msgid "%d has declined the file %s"
 msgstr "%d hat die Datei %s abgelehnt"
@@ -7658,58 +7833,6 @@
 msgid "%d canceled the transfer of %s"
 msgstr "%d hat die Übertragung von %s abgebrochen"
 
-msgid "Do you approve the requestion?"
-msgstr "Wollen sie die Anfrage akzeptieren?"
-
-msgid "Do you add the buddy?"
-msgstr "Möchten Sie diesen Buddy hinzufügen?"
-
-#. only need to get value
-#, c-format
-msgid "You have been added by %s"
-msgstr "Sie wurden von %s hinzugefügt"
-
-msgid "Would you like to add him?"
-msgstr "Möchten Sie ihn hinzufügen?"
-
-#, c-format
-msgid "%s added you [%s] to buddy list"
-msgstr "%s hat Sie [%s] zur Buddy-Liste hinzugefügt"
-
-msgid "QQ Budy"
-msgstr "QQ-Buddy"
-
-#, c-format
-msgid "Requestion rejected by %s"
-msgstr "Anfrage abgelehnt von %s"
-
-#, c-format
-msgid "Requestion approved by %s"
-msgstr "Anfrage akzeptiert von %s"
-
-#. TODO: this should go through purple_account_request_authorization()
-#, c-format
-msgid "%s wants to add you [%s] as a friend"
-msgstr "%s möchte Sie [%s] als Freund hinzufügen"
-
-#, c-format
-msgid "%s is not in buddy list"
-msgstr "%s ist nicht in der Buddy-Liste"
-
-msgid "Would you add?"
-msgstr "Möchten Sie ihn hinzufügen?"
-
-#, c-format
-msgid "From %s:"
-msgstr "Von %s:"
-
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-msgid "QQ Server Notice"
-msgstr "QQ-Server-Nachricht"
-
 msgid "Connection closed (writing)"
 msgstr "Verbindung geschlossen (schreibend)"
 
@@ -9408,9 +9531,6 @@
 msgid "Yahoo! system message for %s:"
 msgstr "Yahoo!-Systemnachricht für %s:"
 
-msgid "Authorization denied message:"
-msgstr "Nachricht für die Ablehnung der Autorisierung:"
-
 #, c-format
 msgid ""
 "%s has (retroactively) denied your request to add them to your list for the "
@@ -10297,14 +10417,14 @@
 msgid "Protocol"
 msgstr "Protokoll"
 
-#, c-format
+#, fuzzy, c-format
 msgid ""
 "<span size='larger' weight='bold'>Welcome to %s!</span>\n"
 "\n"
 "You have no IM accounts configured. To start connecting with %s press the "
-"<b>Add</b> button below and configure your first account. If you want %s to "
-"connect to multiple IM accounts, press <b>Add</b> again to configure them "
-"all.\n"
+"<b>Add...</b> button below and configure your first account. If you want %s "
+"to connect to multiple IM accounts, press <b>Add...</b> again to configure "
+"them all.\n"
 "\n"
 "You can come back to this window to add, edit, or remove accounts from "
 "<b>Accounts->Manage Accounts</b> in the Buddy List window"
@@ -10745,7 +10865,8 @@
 msgid "Auto_join when account becomes online."
 msgstr "Automatisch _beitreten, wenn das Konto online geht."
 
-msgid "_Hide chat when the window is closed."
+#, fuzzy
+msgid "_Remain in chat after window is closed."
 msgstr "_Chat verstecken, wenn das Fenster geschlossen wird."
 
 msgid "Please enter the name of the group to be added."
@@ -12035,7 +12156,7 @@
 "                      nur das erste Konto aktiviert).\n"
 "  -v, --version       zeigt aktuelle Version und beendet das Programm\n"
 
-#, c-format
+#, fuzzy, c-format
 msgid ""
 "%s %s has segfaulted and attempted to dump a core file.\n"
 "This is a bug in the software and has happened through\n"
@@ -12049,11 +12170,6 @@
 "and post the backtrace from the core file.  If you do not know\n"
 "how to get the backtrace, please read the instructions at\n"
 "%swiki/GetABacktrace\n"
-"\n"
-"If you need further assistance, please IM either SeanEgn or \n"
-"LSchiere (via AIM).  Contact information for Sean and Luke \n"
-"on other protocols is at\n"
-"%swiki/DeveloperPages\n"
 msgstr ""
 "%s %s hat einen Speicherzugriffsfehler festgestellt und \n"
 "versucht, eine Core-Datei zu schreiben.  Dies ist ein \n"
@@ -12913,9 +13029,14 @@
 msgid "_Invite"
 msgstr "_Einladen"
 
-msgid "_Modify"
+#, fuzzy
+msgid "_Modify..."
 msgstr "_Bearbeiten"
 
+#, fuzzy
+msgid "_Add..."
+msgstr "_Hinzufügen"
+
 msgid "_Open Mail"
 msgstr "Mail ö_ffnen"
 
@@ -12937,6 +13058,13 @@
 msgid "none"
 msgstr "keine"
 
+#, fuzzy
+msgid "Small"
+msgstr "E-Mail"
+
+msgid "Smaller versions of the default smilies"
+msgstr ""
+
 msgid "Response Probability:"
 msgstr "Antwortwahrscheinlichkeit:"
 
@@ -13595,20 +13723,20 @@
 "Sie das Debug-Fenster."
 
 #, c-format
-msgid ""
-"You are using %s version %s.  The current version is %s.  You can get it "
-"from <a href=\"%s\">%s</a><hr>"
-msgstr ""
-"Sie verwenden gerade %s Version %s.  Die aktuelle Version ist %s.  Sie "
-"können Pidgin von <a href=\"%s\">%s</a> herunterladen.<hr>"
-
-#, c-format
-msgid "<b>ChangeLog:</b><br>%s"
-msgstr "<b>Änderungen:</b><br>%s"
+msgid "You can upgrade to %s %s today."
+msgstr ""
 
 msgid "New Version Available"
 msgstr "Neue Version verfügbar"
 
+#, fuzzy
+msgid "Later"
+msgstr "Datum"
+
+#, fuzzy
+msgid "Download Now"
+msgstr "Download %s: %s"
+
 #. *< type
 #. *< ui_requirement
 #. *< flags
@@ -13918,3 +14046,169 @@
 msgid "This plugin is useful for debbuging XMPP servers or clients."
 msgstr ""
 "Dieses Plugin ist nützlich zur Fehlersuche in XMPP-Servern oder -Clients."
+
+#~ msgid "Primary Information"
+#~ msgstr "Primäre Informationen"
+
+#~ msgid "Blood Type"
+#~ msgstr "Blutgruppe"
+
+#~ msgid "Update information"
+#~ msgstr "Informationen aktualisieren"
+
+#~ msgid "Successed:"
+#~ msgstr "Erfolgreich:"
+
+#~ msgid ""
+#~ "Setting custom faces is not currently supported. Please choose an image "
+#~ "from %s."
+#~ msgstr ""
+#~ "Das Setzen von benutzerdefinierten Gesichtern wird momentan nicht "
+#~ "unterstützt. Bitte wählen Sie ein Bild von %s."
+
+#~ msgid "Invalid QQ Face"
+#~ msgstr "Ungültiges QQ-Gesicht"
+
+# c-format
+#~ msgid "You rejected %d's request"
+#~ msgstr "Sie haben die Anfrage von %d abgelehnt"
+
+#~ msgid "Reject request"
+#~ msgstr "Anfrage ablehnen"
+
+#~ msgid "Add buddy with auth request failed"
+#~ msgstr "Benutzer hinzufügen, wenn Autorisierungsanfrage fehlschlug"
+
+#~ msgid "Add into %d's buddy list"
+#~ msgstr "Zu %ds Buddy-Liste hinzufügen"
+
+#~ msgid "QQ Number Error"
+#~ msgstr "Fehler in QQ-Nummer"
+
+#~ msgid "Group Description"
+#~ msgstr "Gruppenbeschreibung"
+
+#~ msgid "Auth"
+#~ msgstr "Autorisieren"
+
+#~ msgid "Approve"
+#~ msgstr "Akzeptieren"
+
+#~ msgid "Successed to join Qun %d, operated by admin %d"
+#~ msgstr "Erfolgreicher Beitritt in den Qun %d, moderiert vom Admin %d"
+
+#~ msgid "[%d] removed from Qun \"%d\""
+#~ msgstr "[%d] vom Qun „%d“ entfernt"
+
+#~ msgid "[%d] added to Qun \"%d\""
+#~ msgstr "[%d] zum Qun „%d“ hinzugefügt"
+
+#~ msgid "I am a member"
+#~ msgstr "Ich bin Mitglied"
+
+#~ msgid "I am requesting"
+#~ msgstr "Ich frage an"
+
+#~ msgid "I am the admin"
+#~ msgstr "Ich bin der Admin"
+
+#~ msgid "Unknown status"
+#~ msgstr "Unbekannter Status"
+
+#~ msgid "Remove from Qun"
+#~ msgstr "vom Qun entfernen"
+
+#~ msgid "You entered a group ID outside the acceptable range"
+#~ msgstr ""
+#~ "Sie haben eine Gruppen-ID außerhalb des erlaubten Bereichs angegeben"
+
+#~ msgid "Are you sure you want to leave this Qun?"
+#~ msgstr "Wollen Sie dieses Qun wirklich verlassen?"
+
+#~ msgid "Do you want to approve the request?"
+#~ msgstr "Wollen sie die Anfrage akzeptieren?"
+
+#~ msgid ""
+#~ "%s\n"
+#~ "\n"
+#~ "%s"
+#~ msgstr ""
+#~ "%s\n"
+#~ "\n"
+#~ "%s"
+
+#~ msgid "System Message"
+#~ msgstr "Systemnachricht"
+
+#~ msgid "<b>Last Login IP</b>: %s<br>\n"
+#~ msgstr "<b>Letzte Anmelde-IP</b>: %s<br>\n"
+
+#~ msgid "<b>Last Login Time</b>: %s\n"
+#~ msgstr "<b>Letzte Anmeldezeit</b>: %s\n"
+
+#~ msgid "Set My Information"
+#~ msgstr "Meine Informationen festlegen"
+
+#~ msgid "Leave the QQ Qun"
+#~ msgstr "Diesen QQ-Qun verlassen"
+
+#~ msgid "Block this buddy"
+#~ msgstr "Diesen Buddy blockieren"
+
+#~ msgid "Invalid token reply code, 0x%02X"
+#~ msgstr "Ungültiger Token-Antwort-Code, 0x%02X"
+
+#~ msgid "Unable login for not support Redirect_EX now"
+#~ msgstr "Anmeldung nicht möglich, Redirect_EX wird noch nicht unterstützt"
+
+#~ msgid "Error password: %s"
+#~ msgstr "Passwort-Fehler: %s"
+
+#~ msgid "Need active: %s"
+#~ msgstr "Brauche aktiv: %s"
+
+#~ msgid "Failed to connect all servers"
+#~ msgstr "Konnte nicht alle Server verbinden"
+
+#~ msgid "Connecting server %s, retries %d"
+#~ msgstr "Verbinde zu Server %s, %d Wiederholungen"
+
+#~ msgid "Do you approve the requestion?"
+#~ msgstr "Wollen sie die Anfrage akzeptieren?"
+
+#~ msgid "Do you add the buddy?"
+#~ msgstr "Möchten Sie diesen Buddy hinzufügen?"
+
+#~ msgid "%s added you [%s] to buddy list"
+#~ msgstr "%s hat Sie [%s] zur Buddy-Liste hinzugefügt"
+
+#~ msgid "QQ Budy"
+#~ msgstr "QQ-Buddy"
+
+#~ msgid "Requestion approved by %s"
+#~ msgstr "Anfrage akzeptiert von %s"
+
+#~ msgid "%s wants to add you [%s] as a friend"
+#~ msgstr "%s möchte Sie [%s] als Freund hinzufügen"
+
+#~ msgid "%s is not in buddy list"
+#~ msgstr "%s ist nicht in der Buddy-Liste"
+
+#~ msgid "Would you add?"
+#~ msgstr "Möchten Sie ihn hinzufügen?"
+
+#~ msgid "%s"
+#~ msgstr "%s"
+
+#~ msgid "QQ Server Notice"
+#~ msgstr "QQ-Server-Nachricht"
+
+#~ msgid ""
+#~ "You are using %s version %s.  The current version is %s.  You can get it "
+#~ "from <a href=\"%s\">%s</a><hr>"
+#~ msgstr ""
+#~ "Sie verwenden gerade %s Version %s.  Die aktuelle Version ist %s.  Sie "
+#~ "können Pidgin von <a href=\"%s\">%s</a> herunterladen.<hr>"
+
+#~ msgid "<b>ChangeLog:</b><br>%s"
+#~ msgstr "<b>Änderungen:</b><br>%s"