changeset 23561:b1457c51da46

propagate from branch 'im.pidgin.pidgin' (head 99fe11b8da675f3b74b853ea29a16d8c9564cb95) to branch 'im.pidgin.cpw.qulogic.msn' (head 86d2aabc8c0973823a48a28d3c74e0a8b988d8dd)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Wed, 09 Jul 2008 02:06:38 +0000
parents 7e16d193bb57 (current diff) 08bbba359cc2 (diff)
children 7f4473544c64
files libpurple/protocols/msn/soap2.c libpurple/protocols/msn/soap2.h
diffstat 44 files changed, 706 insertions(+), 198 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jul 09 01:46:10 2008 +0000
+++ b/ChangeLog	Wed Jul 09 02:06:38 2008 +0000
@@ -16,7 +16,7 @@
 	* Resize large incoming custom smileys to a maximum of 96px on either
 	  side.
 	* Offer to add new buddies into the same contact as existing buddies
-          in the same group if the alias given is the same.
+	  in the same group if the alias given is the same.
 
 	General:
 	* Group and Chat buddy list entries can now be given custom buddy
@@ -28,12 +28,25 @@
 	  logs.
 	* Added '/msgcolor' command to change colors of different classes of
 	  messages in a conversation. See '/help msgcolor' for details.
+	* Added tab-completion for commands in conversation windows.
 
-version 2.4.3 (??/??/2008):
+version 2.4.3 (07/01/2008):
 	libpurple:
 	* Yahoo! Japan now uses UTF-8, matching the behavior of official clients
 	  and restoring compatibility with the web messenger (Yusuke Odate)
 	* Setting your buddy icon once again works for Yahoo! accounts.
+	* Fixes in the Yahoo! protocol to prevent a double free, crashes on
+	  aliases, and alias functionality
+	* Fix crashes in the bonjour protocol
+	* Always use UTF-8 for Yahoo! (#5973)
+	* Fix a crash when the given jabber id is invalid.
+	* Make the IRC "unknown message" debugging messages UTF-8 safe.
+	* Fix connecting to ICQ
+	* Fix a memleak when handling jabber xforms.
+
+	Pidgin:
+	* Include the send button plugin in the win32 build
+	* Various memory leak fixes
 
 version 2.4.2 (05/17/2008):
 	libpurple:
--- a/ChangeLog.API	Wed Jul 09 01:46:10 2008 +0000
+++ b/ChangeLog.API	Wed Jul 09 02:06:38 2008 +0000
@@ -17,6 +17,9 @@
 		* purple_buddy_icons_node_set_custom_icon_from_file
 		* purple_notify_user_info_prepend_section_break
 		* purple_notify_user_info_prepend_section_header
+		* "website" and "dev_website" items to the ui_info hash table
+		* purple_cmds_get_handle, purple_cmds_init, purple_cmds_uninit
+		* cmd-added and cmd-removed signals
 
 		Deprecated:
 		* purple_blist_update_buddy_icon
--- a/ChangeLog.win32	Wed Jul 09 01:46:10 2008 +0000
+++ b/ChangeLog.win32	Wed Jul 09 02:06:38 2008 +0000
@@ -1,4 +1,4 @@
-version 2.4.3 (??/??/2008):
+version 2.4.3 (07/01/2008):
 	* No changes
 
 version 2.4.2 (05/17/2008):
--- a/NEWS	Wed Jul 09 01:46:10 2008 +0000
+++ b/NEWS	Wed Jul 09 02:06:38 2008 +0000
@@ -1,5 +1,9 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+2.4.3 (07/01/2008):
+	Richard: This release includes important bug fixes.  I'm just cutting
+	the release.  Thank you to the real heroes who did the fixing!
+
 2.4.2 (5/17/2008):
 	Sadrul: We added some usability changes in this release, including the
 	typing notification, buddyicon and input area size in the conversation
--- a/configure.ac	Wed Jul 09 01:46:10 2008 +0000
+++ b/configure.ac	Wed Jul 09 02:06:38 2008 +0000
@@ -47,7 +47,7 @@
 m4_define([purple_major_version], [2])
 m4_define([purple_minor_version], [5])
 m4_define([purple_micro_version], [0])
-m4_define([purple_version_suffix], [devel])
+m4_define([purple_version_suffix], [])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
 m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix]))
@@ -56,7 +56,7 @@
 m4_define([gnt_major_version], [2])
 m4_define([gnt_minor_version], [5])
 m4_define([gnt_micro_version], [0])
-m4_define([gnt_version_suffix], [devel])
+m4_define([gnt_version_suffix], [])
 m4_define([gnt_version],
           [gnt_major_version.gnt_minor_version.gnt_micro_version])
 m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
@@ -336,6 +336,10 @@
 	AC_DEFINE_UNQUOTED(DISPLAY_VERSION, "$VERSION", [display version info])
 fi
 
+AC_ARG_ENABLE(missing-dependencies, [AC_HELP_STRING([--disable-missing-dependencies],
+		[skip missing dependencies instead of aborting configure])],
+	force_deps="$enableval", force_deps="yes")
+
 AC_ARG_WITH(x, [],
 	with_x="$withval", with_x="yes")
 AC_ARG_ENABLE(gtkui, [AC_HELP_STRING([--disable-gtkui],
@@ -419,10 +423,12 @@
 					X11_LIBS="$x_libpath_add"
 					X11_CFLAGS="$x_incpath_add"
 				else
-					AC_MSG_ERROR([
+					if test "x$force_deps" = "xyes" ; then
+						AC_MSG_ERROR([
 X11 development headers not found.
 Use --without-x if you do not need X11 support.
 ])
+					fi
 				fi
 			])
 		AC_SUBST(X11_LIBS)
@@ -461,11 +467,13 @@
 				AC_DEFINE(USE_SCREENSAVER, 1, [Define if we're using XScreenSaver.])
 				AC_SUBST(XSS_LIBS)
 			else
-				AC_MSG_ERROR([
+				if test "x$force_deps" = "xyes" ; then
+					AC_MSG_ERROR([
 XScreenSaver extension development headers not found.
 Use --disable-screensaver if you do not need XScreenSaver extension support,
 this is required for detecting idle time by mouse and keyboard usage.
 ])
+				fi
 			fi
 		else
 			AC_MSG_ERROR([X support is required to build with XScreenSaver extensions])
@@ -490,10 +498,12 @@
 				AC_DEFINE(USE_SM, 1, [Define if we're using X Session Management.])
 				AC_SUBST(SM_LIBS)
 			else
-				AC_MSG_ERROR([
+				if test "x$force_deps" = "xyes" ; then
+					AC_MSG_ERROR([
 X session management development headers not found.
 Use --disable-sm if you do not need session management support.
 ])
+				fi
 			fi
 		else
 			AC_MSG_ERROR([X support is required to build with X session management support])
@@ -515,10 +525,12 @@
 	if test "x$enable_startup_notification" = "xyes"; then
 		PKG_CHECK_MODULES(STARTUP_NOTIFICATION, [libstartup-notification-1.0 >= 0.5], , [
 			AC_MSG_RESULT(no)
-			AC_MSG_ERROR([
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
 Startup notification development headers not found.
 Use --disable-startup-notification if you do not need it.
-])])
+])
+			fi])
 
 		if test "x$enable_startup_notification" = "xyes"; then
 			AC_DEFINE(HAVE_STARTUP_NOTIFICATION, 1, [Define if we're using libstartup-notification.])
@@ -533,10 +545,12 @@
 	if test "x$enable_gtkspell" = "xyes" ; then
 		PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, , [
 			AC_MSG_RESULT(no)
-			AC_MSG_ERROR([
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
 GtkSpell development headers not found.
 Use --disable-gtkspell if you do not need it.
-])])
+])
+			fi])
 		if test "x$enable_gtkspell" = "xyes" ; then
 			AC_DEFINE(USE_GTKSPELL, 1, [Define if we're using GtkSpell])
 			AC_SUBST(GTKSPELL_CFLAGS)
@@ -566,10 +580,12 @@
 			AC_SUBST(EVOLUTION_ADDRESSBOOK_CFLAGS)
 			AC_SUBST(EVOLUTION_ADDRESSBOOK_LIBS)
 		else
-			AC_MSG_ERROR([
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
 Evolution development headers not found.
 Use --disable-gevolution if you do not need it.
 ])
+			fi
 		fi
 	fi
 
@@ -579,10 +595,12 @@
 	if test "x$enable_cap" = "xyes"; then
 		PKG_CHECK_MODULES(SQLITE3, sqlite3 >= 3.3,,[
 			AC_MSG_RESULT(no)
-			AC_MSG_ERROR([
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
 sqlite3 development headers not found.
 Use --disable-cap if you do not need the Contact Availability Prediction plugin.
-])])
+])
+			fi])
 	fi
         
 
@@ -719,10 +737,12 @@
 			[], [$GSTREAMER_LIBS])
 	], [
 		AC_MSG_RESULT(no)
-		AC_MSG_ERROR([
+		if test "x$force_deps" = "xyes" ; then
+			AC_MSG_ERROR([
 GStreamer development headers not found.
 Use --disable-gstreamer if you do not need GStreamer (sound) support.
-])])
+])
+		fi])
 fi
 
 dnl #######################################################################
@@ -737,10 +757,12 @@
 		have_meanwhile="yes"
 	], [
 		have_meanwhile="no"
-		AC_MSG_ERROR([
+		if test "x$force_deps" = "xyes" ; then
+			AC_MSG_ERROR([
 Meanwhile development headers not found.
 Use --disable-meanwhile if you do not need meanwhile (Sametime) support.
-])])
+])
+		fi])
 fi
 AC_SUBST(MEANWHILE_CFLAGS)
 AC_SUBST(MEANWHILE_LIBS)
@@ -783,7 +805,7 @@
 fi
 AC_CHECK_LIB(avahi-client, avahi_client_new, [avahilibs=yes], [avahilibs=no], $AVAHI_LIBS)
 
-if test "x$enable_avahi" = "xyes" -a \( "x$avahiincludes" = "xno" -o "x$avahilibs" = "xno" \); then
+if test "x$enable_avahi" = "xyes" -a "x$force_deps" = "xyes" -a \( "x$avahiincludes" = "xno" -o "x$avahilibs" = "xno" \); then
 	AC_MSG_ERROR([
 avahi development headers not found.
 Use --disable-avahi if you do not need avahi (Bonjour) support.
@@ -1155,7 +1177,6 @@
 			"-Wmissing-declarations" \
 			"-Wmissing-noreturn" \
 			"-Wmissing-prototypes" \
-			"-Wnested-externs" \
 			"-Wpointer-arith" \
 			"-Wundef" \
 	; do
@@ -1220,10 +1241,12 @@
 		AC_SUBST(DBUS_LIBS)
 		enable_dbus=yes
 	], [
+	if test "x$force_deps" = "xyes" ; then
 		AC_MSG_ERROR([
 D-Bus development headers not found.
 Use --disable-dbus if you do not need D-Bus support.
-])])
+])
+	fi])
 
 dnl Check for NetworkManager.h; if we don't have it, oh well
 	if test "x$enable_nm" = "xyes" ; then
@@ -1232,10 +1255,12 @@
 			AC_SUBST(NETWORKMANAGER_LIBS)
 			AC_DEFINE(HAVE_NETWORKMANAGER, 1, [Define if we have NetworkManager.])
 		], [
-			AC_MSG_ERROR([
+			if test "x$force_deps" = "xyes" ; then
+				AC_MSG_ERROR([
 NetworkManager development headers not found.
 Use --disable-nm if you do not need NetworkManager support.
-])])
+])
+			fi])
 	fi
 else
 	enable_nm=no
@@ -1548,7 +1573,7 @@
 	AM_CONDITIONAL(USE_PERL, false)
 fi
 
-if test "x$looked_for_perl" = "xyes" -a "x$enable_perl" = "xno"; then
+if test "x$looked_for_perl" = "xyes" -a "x$enable_perl" = "xno" -a "x$force_deps" = "xyes"; then
 	AC_MSG_ERROR([
 Perl development headers not found.
 Use --disable-perl if you do not need Perl scripting support.
@@ -1959,19 +1984,19 @@
 	msg_ssl=$msg_nss
 elif test "x$msg_gnutls" != "x"; then
 	msg_ssl=$msg_gnutls
-elif test "x$looked_for_gnutls" = "xyes" -a "x$looked_for_nss" = "xyes"; then
+elif test "x$looked_for_gnutls" = "xyes" -a "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then
 	AC_MSG_ERROR([
 Neither GnuTLS or NSS SSL development headers found.
 Use --disable-nss --disable-gnutls if you do not need SSL support.
 MSN, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!
 ])
-elif test "x$looked_for_gnutls" = "xyes"; then
+elif test "x$looked_for_gnutls" = "xyes" -a "x$force_deps" = "xyes" ; then
 	AC_MSG_ERROR([
 GnuTLS SSL development headers not found.
 Use --disable-gnutls if you do not need SSL support.
 MSN, Novell Groupwise and Google Talk will not work without SSL support.
 ])
-elif test "x$looked_for_nss" = "xyes"; then
+elif test "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then
 	AC_MSG_ERROR([
 NSS SSL development headers not found.
 Use --disable-nss if you do not need SSL support.
@@ -2010,10 +2035,12 @@
 	if test "$TCLCONFIG" = "no"; then
 		AC_MSG_RESULT([no])
 		enable_tcl=no
-		AC_MSG_ERROR([
+		if test "x$force_deps" = "xyes" ; then
+			AC_MSG_ERROR([
 Tcl development headers not found.
 Use --disable-tcl if you do not need Tcl scripting support.
 ])
+		fi
 	else
 		. $TCLCONFIG
 		AC_MSG_CHECKING([Tcl version compatability])
@@ -2078,10 +2105,12 @@
 	if test "$TKCONFIG" = "no"; then
 		AC_MSG_RESULT([no])
 		enable_tk=no
-		AC_MSG_ERROR([
+		if test "x$force_deps" = "xyes" ; then
+			AC_MSG_ERROR([
 Tk development headers not found.
 Use --disable-tk if you do not need Tk scripting support.
 ])
+		fi
 	else
 		. $TKCONFIG
 		eval "TK_LIB_SPEC=\"$TK_LIB_SPEC\""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/cmd-signals.dox	Wed Jul 09 02:06:38 2008 +0000
@@ -0,0 +1,29 @@
+/** @page cmd-signals Command Signals
+  @signals
+  	@signal cmd-added
+	@signal cmd-removed
+  @endsignals
+
+  @see cmds.h
+
+  @signaldef cmd-added
+  	@signalproto
+void (*cmd_added)(const char *command, PurpleCmdPriority priority,
+                  PurpleCmdFlag flag);
+	@endsignalproto
+	@signaldesc
+	 Emitted when a new command is added.
+	@param command   The new command.
+	@param priority  The priority of the new command.
+	@param flag      The command flags.
+  @endsignaldef
+
+  @signaldef cmd-removed
+  	@signalproto
+void (*cmd_removed)(const char *command);
+	@endsignalproto
+	@signaldesc
+	 Emitted when a command is removed.
+	@param command   The removed command.
+  @endsignaldef
+*/
--- a/finch/finch.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/finch/finch.c	Wed Jul 09 02:06:38 2008 +0000
@@ -63,6 +63,8 @@
 
 		g_hash_table_insert(ui_info, "name", (char*)_("Finch"));
 		g_hash_table_insert(ui_info, "version", VERSION);
+		g_hash_table_insert(ui_info, "website", "http://pidgin.im");
+		g_hash_table_insert(ui_info, "dev_website", "http://developer.pidgin.im");
 	}
 
 	return ui_info;
--- a/finch/gntconv.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/finch/gntconv.c	Wed Jul 09 02:06:38 2008 +0000
@@ -692,11 +692,48 @@
 static void
 completion_cb(GntEntry *entry, const char *start, const char *end)
 {
-	if (start == entry->start)
+	if (start == entry->start && *start != '/')
 		gnt_widget_key_pressed(GNT_WIDGET(entry), ": ");
 }
 
 static void
+gg_setup_commands(FinchConv *fconv, gboolean remove_first)
+{
+	GList *commands;
+	char command[256] = "/";
+
+	if (remove_first) {
+		commands = purple_cmd_list(NULL);
+		for (; commands; commands = g_list_delete_link(commands, commands)) {
+			g_strlcpy(command + 1, commands->data, sizeof(command) - 1);
+			gnt_entry_remove_suggest(GNT_ENTRY(fconv->entry), command);
+		}
+	}
+
+	commands = purple_cmd_list(fconv->active_conv);
+	for (; commands; commands = g_list_delete_link(commands, commands)) {
+		g_strlcpy(command + 1, commands->data, sizeof(command) - 1);
+		gnt_entry_add_suggest(GNT_ENTRY(fconv->entry), command);
+	}
+}
+
+static void
+cmd_added_cb(const char *cmd, PurpleCmdPriority prior, PurpleCmdFlag flags,
+		FinchConv *fconv)
+{
+	gg_setup_commands(fconv, TRUE);
+}
+
+static void
+cmd_removed_cb(const char *cmd, FinchConv *fconv)
+{
+	char command[256] = "/";
+	g_strlcpy(command + 1, cmd, sizeof(command) - 1);
+	gnt_entry_remove_suggest(GNT_ENTRY(fconv->entry), command);
+	gg_setup_commands(fconv, TRUE);
+}
+
+static void
 finch_create_conversation(PurpleConversation *conv)
 {
 	FinchConv *ggc = FINCH_GET_DATA(conv);
@@ -819,6 +856,12 @@
 		ggc->flags |= FINCH_CONV_NO_SOUND;
 
 	gg_create_menu(ggc);
+	gg_setup_commands(ggc, FALSE);
+
+	purple_signal_connect(purple_cmds_get_handle(), "cmd-added", ggc,
+			G_CALLBACK(cmd_added_cb), ggc);
+	purple_signal_connect(purple_cmds_get_handle(), "cmd-removed", ggc,
+			G_CALLBACK(cmd_removed_cb), ggc);
 
 	g_free(title);
 	gnt_box_give_focus_to_child(GNT_BOX(ggc->window), ggc->entry);
@@ -831,11 +874,14 @@
 	/* do stuff here */
 	FinchConv *ggc = FINCH_GET_DATA(conv);
 	ggc->list = g_list_remove(ggc->list, conv);
-	if (ggc->list && conv == ggc->active_conv)
+	if (ggc->list && conv == ggc->active_conv) {
 		ggc->active_conv = ggc->list->data;
-	
+		gg_setup_commands(ggc, TRUE);
+	}
+
 	if (ggc->list == NULL) {
 		g_free(ggc->u.chat);
+		purple_signals_disconnect_by_handle(ggc);
 		if (ggc->window)
 			gnt_widget_destroy(ggc->window);
 		g_free(ggc);
@@ -1404,8 +1450,11 @@
 
 	g_return_if_fail(ggconv);
 	g_return_if_fail(g_list_find(ggconv->list, conv));
+	if (ggconv->active_conv == conv)
+		return;
 
 	ggconv->active_conv = conv;
+	gg_setup_commands(ggconv, TRUE);
 	account = purple_conversation_get_account(conv);
 	title = get_conversation_title(conv, account);
 	gnt_screen_rename_widget(ggconv->window, title);
--- a/finch/libgnt/gntbutton.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/finch/libgnt/gntbutton.c	Wed Jul 09 02:06:38 2008 +0000
@@ -77,18 +77,6 @@
 }
 
 static gboolean
-gnt_button_key_pressed(GntWidget *widget, const char *key)
-{
-	if (strcmp(key, GNT_KEY_ENTER) == 0 ||
-			strcmp(key, SAFE(cursor_down)) == 0)
-	{
-		gnt_widget_activate(widget);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static gboolean
 gnt_button_clicked(GntWidget *widget, GntMouseEvent event, int x, int y)
 {
 	if (event == GNT_LEFT_MOUSE_DOWN) {
@@ -106,23 +94,33 @@
 	g_free(button->priv);
 }
 
+static gboolean
+button_activate(GntBindable *bind, GList *null)
+{
+	gnt_widget_activate(GNT_WIDGET(bind));
+	return TRUE;
+}
+
 static void
 gnt_button_class_init(GntWidgetClass *klass)
 {
 	char *style;
+	GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
 
 	parent_class = GNT_WIDGET_CLASS(klass);
 	parent_class->draw = gnt_button_draw;
 	parent_class->map = gnt_button_map;
 	parent_class->size_request = gnt_button_size_request;
-	parent_class->key_pressed = gnt_button_key_pressed;
 	parent_class->clicked = gnt_button_clicked;
 	parent_class->destroy = gnt_button_destroy;
 
 	style = gnt_style_get_from_name(NULL, "small-button");
 	small_button = gnt_style_parse_bool(style);
 	g_free(style);
-	GNTDEBUG;
+
+	gnt_bindable_class_register_action(bindable, "activate", button_activate,
+				GNT_KEY_ENTER, NULL);
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 }
 
 static void
--- a/finch/libgnt/gntkeys.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/finch/libgnt/gntkeys.c	Wed Jul 09 02:06:38 2008 +0000
@@ -80,6 +80,9 @@
 	INSERT_KEY("down",   GNT_KEY_DOWN);
 
 	INSERT_KEY("tab",    "\t");
+	INSERT_KEY("escape", "\033");
+	INSERT_KEY("space", " ");
+	INSERT_KEY("return", GNT_KEY_ENTER);
 	INSERT_KEY("menu",   GNT_KEY_POPUP);
 
 	INSERT_KEY("f1",   GNT_KEY_F1);
@@ -119,6 +122,9 @@
 				code[ind] = (c ? 1 : 'a') + ch;
 				INSERT_COMB(str, code);
 			}
+			if (c == 0) {
+				INSERT_COMB("tab", "\033\t");
+			}
 		}
 	}
 	c = 0;
--- a/libpurple/cmds.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/cmds.c	Wed Jul 09 02:06:38 2008 +0000
@@ -81,6 +81,8 @@
 
 	cmds = g_list_insert_sorted(cmds, c, (GCompareFunc)cmds_compare_func);
 
+	purple_signal_emit(purple_cmds_get_handle(), "cmd-added", cmd, p, f);
+
 	return id;
 }
 
@@ -103,6 +105,7 @@
 
 		if (c->id == id) {
 			cmds = g_list_remove(cmds, c);
+			purple_signal_emit(purple_cmds_get_handle(), "cmd-removed", c->cmd);
 			purple_cmd_free(c);
 			return;
 		}
@@ -361,3 +364,28 @@
 	return ret;
 }
 
+gpointer purple_cmds_get_handle(void)
+{
+	static int handle;
+	return &handle;
+}
+
+void purple_cmds_init(void)
+{
+	gpointer handle = purple_cmds_get_handle();
+
+	purple_signal_register(handle, "cmd-added",
+			purple_marshal_VOID__POINTER_INT_INT, NULL, 3,
+			purple_value_new(PURPLE_TYPE_STRING),
+			purple_value_new(PURPLE_TYPE_INT),
+			purple_value_new(PURPLE_TYPE_INT));
+	purple_signal_register(handle, "cmd-removed",
+			purple_marshal_VOID__POINTER, NULL, 1,
+			purple_value_new(PURPLE_TYPE_STRING));
+}
+
+void purple_cmds_uninit(void)
+{
+	purple_signals_unregister_by_instance(purple_cmds_get_handle());
+}
+
--- a/libpurple/cmds.h	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/cmds.h	Wed Jul 09 02:06:38 2008 +0000
@@ -1,6 +1,7 @@
 /**
  * @file cmds.h Commands API
  * @ingroup core
+ * @see @ref cmd-signals
  */
 
 /* Copyright (C) 2003 Timothy Ringenbach <omarvo@hotmail.com>
@@ -221,6 +222,25 @@
  */
 GList *purple_cmd_help(PurpleConversation *conv, const gchar *cmd);
 
+/**
+ * Get the handle for the commands API
+ * @return The handle
+ * @since 2.5.0
+ */
+gpointer purple_cmds_get_handle(void);
+
+/**
+ * Initialize the commands subsystem.
+ * @since 2.5.0
+ */
+void purple_cmds_init(void);
+
+/**
+ * Uninitialize the commands subsystem.
+ * @since 2.5.0
+ */
+void purple_cmds_uninit(void);
+
 /*@}*/
 
 #ifdef __cplusplus
--- a/libpurple/conversation.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/conversation.c	Wed Jul 09 02:06:38 2008 +0000
@@ -1621,7 +1621,7 @@
 		}
 
 		quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(),
-						 "chat-buddy-joining", conv, user, flag)) |
+						 "chat-buddy-joining", conv, user, flag)) ||
 				purple_conv_chat_is_user_ignored(chat, user);
 
 		cbuddy = purple_conv_chat_cb_new(user, alias, flag);
@@ -1633,18 +1633,18 @@
 		cbuddies = g_list_prepend(cbuddies, cbuddy);
 
 		if (!quiet && new_arrivals) {
-			char *escaped = g_markup_escape_text(alias, -1);
+			char *alias_esc = g_markup_escape_text(alias, -1);
 			char *tmp;
 
 			if (extra_msg == NULL)
-				tmp = g_strdup_printf(_("%s entered the room."), escaped);
+				tmp = g_strdup_printf(_("%s entered the room."), alias_esc);
 			else {
-				char *escaped2 = g_markup_escape_text(extra_msg, -1);
+				char *extra_msg_esc = g_markup_escape_text(extra_msg, -1);
 				tmp = g_strdup_printf(_("%s [<I>%s</I>] entered the room."),
-									  escaped, escaped2);
-				g_free(escaped2);
+				                      alias_esc, extra_msg_esc);
+				g_free(extra_msg_esc);
 			}
-			g_free(escaped);
+			g_free(alias_esc);
 
 			purple_conversation_write(conv, NULL, tmp,
 					PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY,
@@ -1832,7 +1832,7 @@
 
 		if (!quiet) {
 			const char *alias = user;
-			char *escaped;
+			char *alias_esc;
 			char *tmp;
 
 			if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
@@ -1842,17 +1842,17 @@
 					alias = purple_buddy_get_contact_alias(buddy);
 			}
 
-			escaped = g_markup_escape_text(alias, -1);
+			alias_esc = g_markup_escape_text(alias, -1);
 
 			if (reason == NULL || !*reason)
-				tmp = g_strdup_printf(_("%s left the room."), escaped);
+				tmp = g_strdup_printf(_("%s left the room."), alias_esc);
 			else {
-				char *escaped2 = g_markup_escape_text(reason, -1);
+				char *reason_esc = g_markup_escape_text(reason, -1);
 				tmp = g_strdup_printf(_("%s left the room (%s)."),
-									  escaped, escaped2);
-				g_free(escaped2);
+				                      alias_esc, reason_esc);
+				g_free(reason_esc);
 			}
-			g_free(escaped);
+			g_free(alias_esc);
 
 			purple_conversation_write(conv, NULL, tmp,
 					PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY,
--- a/libpurple/conversation.h	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/conversation.h	Wed Jul 09 02:06:38 2008 +0000
@@ -285,11 +285,21 @@
  */
 struct _PurpleConvChatBuddy
 {
-	char *name;                      /**< The name                      */
-	char *alias;					 /**< The alias 					*/
-	char *alias_key;				 /**< The alias key					*/
-	gboolean buddy;					 /**< ChatBuddy is on the blist		*/
-	PurpleConvChatBuddyFlags flags;    /**< Flags (ops, voice etc.)       */
+	char *name;                      /**< The chat participant's name in the chat. */
+	char *alias;                     /**< The chat participant's alias, if known;
+	                                  *   @a NULL otherwise.
+	                                  */
+	char *alias_key;                 /**< A string by which this buddy will be sorted,
+	                                  *   or @c NULL if the buddy should be sorted by
+	                                  *   its @c name.  (This is currently always @c
+	                                  *   NULL.)
+	                                  */
+	gboolean buddy;                  /**< @a TRUE if this chat participant is on the
+	                                  *   buddy list; @a FALSE otherwise.
+	                                  */
+	PurpleConvChatBuddyFlags flags;  /**< A bitwise OR of flags for this participant,
+	                                  *   such as whether they are a channel operator.
+	                                  */
 };
 
 /**
--- a/libpurple/core.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/core.c	Wed Jul 09 02:06:38 2008 +0000
@@ -26,6 +26,7 @@
 #include "internal.h"
 #include "cipher.h"
 #include "certificate.h"
+#include "cmds.h"
 #include "connection.h"
 #include "conversation.h"
 #include "core.h"
@@ -169,6 +170,7 @@
 	purple_xfers_init();
 	purple_idle_init();
 	purple_smileys_init();
+	purple_cmds_init();
 
 	/*
 	 * Call this early on to try to auto-detect our IP address and
@@ -197,6 +199,7 @@
 	purple_connections_disconnect_all();
 
 	/* Save .xml files, remove signals, etc. */
+	purple_cmds_uninit();
 	purple_smileys_uninit();
 	purple_idle_uninit();
 	purple_ssl_uninit();
--- a/libpurple/core.h	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/core.h	Wed Jul 09 02:06:38 2008 +0000
@@ -180,6 +180,12 @@
  *
  *   <dt><tt>version</tt></dt>
  *   <dd>a user-readable description of the current version of the UI.</dd>
+ *
+ *   <dt><tt>website</tt></dt>
+ *   <dd>the UI's website, such as http://pidgin.im.</dd>
+ *
+ *   <dt><tt>dev_website</tt></dt>
+ *   <dd>the UI's development/support website, such as http://developer.pidgin.im.</dd>
  * </dl>
  *
  * @return A GHashTable with strings for keys and values.  This
--- a/libpurple/protocols/irc/msgs.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/irc/msgs.c	Wed Jul 09 02:06:38 2008 +0000
@@ -1007,6 +1007,9 @@
 	irc->reqnick = newnick;
 	irc->nickused = TRUE;
 
+	purple_connection_set_display_name(
+		purple_account_get_connection(irc->account), newnick);
+
 	buf = irc_format(irc, "vn", "NICK", newnick);
 	irc_send(irc, buf);
 	g_free(buf);
--- a/libpurple/protocols/jabber/google.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/jabber/google.c	Wed Jul 09 02:06:38 2008 +0000
@@ -314,11 +314,6 @@
 		buddies = buddies->next;
 	}
 
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-
-	query = xmlnode_get_child(iq->node, "query");
-	item = xmlnode_new_child(query, "item");
-
 	xmlnode_set_attrib(item, "jid", who);
 	xmlnode_set_attrib(item, "name", b->alias ? b->alias : "");
 	xmlnode_set_attrib(item, "gr:t", "B");
@@ -385,11 +380,6 @@
 		buddies = buddies->next;
 	}
 
-	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-
-	query = xmlnode_get_child(iq->node, "query");
-	item = xmlnode_new_child(query, "item");
-
 	xmlnode_set_attrib(item, "jid", who);
 	xmlnode_set_attrib(item, "name", b->alias ? b->alias : "");
 	xmlnode_set_attrib(query, "xmlns:gr", "google:roster");
--- a/libpurple/protocols/jabber/jabber.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed Jul 09 02:06:38 2008 +0000
@@ -430,12 +430,17 @@
 			jabber_stream_init(js);
 	}
 
-	if(errno == EAGAIN)
+	if(len < 0 && errno == EAGAIN)
 		return;
-	else
+	else {
+		if (len == 0)
+			purple_debug_info("jabber", "Server closed the connection.\n");
+		else
+			purple_debug_info("jabber", "Disconnected: %s\n", g_strerror(errno));
 		purple_connection_error_reason (js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Read Error"));
+	}
 }
 
 static void
@@ -470,9 +475,13 @@
 		jabber_parser_process(js, buf, len);
 		if(js->reinit)
 			jabber_stream_init(js);
-	} else if(errno == EAGAIN) {
+	} else if(len < 0 && errno == EAGAIN) {
 		return;
 	} else {
+		if (len == 0)
+			purple_debug_info("jabber", "Server closed the connection.\n");
+		else
+			purple_debug_info("jabber", "Disconnected: %s\n", g_strerror(errno));
 		purple_connection_error_reason (js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 			_("Read Error"));
--- a/libpurple/protocols/jabber/parser.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/jabber/parser.c	Wed Jul 09 02:06:38 2008 +0000
@@ -132,6 +132,18 @@
 	xmlnode_insert_data(js->current, (const char*) text, text_len);
 }
 
+static void
+jabber_parser_structured_error_handler(void *user_data, xmlErrorPtr error)
+{
+	JabberStream *js = user_data;
+
+	purple_debug_error("jabber", "XML parser error for JabberStream %p: "
+								 "Domain %i, code %i, level %i: %s\n",
+					   js,
+					   error->domain, error->code, error->level,
+					   (error->message ? error->message : "(null)"));
+}
+
 static xmlSAXHandler jabber_parser_libxml = {
 	NULL,									/*internalSubset*/
 	NULL,									/*isStandalone*/
@@ -164,7 +176,7 @@
 	NULL,									/*_private*/
 	jabber_parser_element_start_libxml,		/*startElementNs*/
 	jabber_parser_element_end_libxml,		/*endElementNs*/
-	NULL									/*serror*/
+	jabber_parser_structured_error_handler	/*serror*/
 };
 
 void
@@ -187,15 +199,25 @@
 
 void jabber_parser_process(JabberStream *js, const char *buf, int len)
 {
-	if (js->context ==  NULL) {
+	int ret;
+
+	if (js->context == NULL) {
 		/* libxml inconsistently starts parsing on creating the
 		 * parser, so do a ParseChunk right afterwards to force it. */
 		js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL);
 		xmlParseChunk(js->context, "", 0, 0);
-	} else if (xmlParseChunk(js->context, buf, len, 0) < 0) {
-		purple_connection_error_reason (js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("XML Parse error"));
+	} else if ((ret = xmlParseChunk(js->context, buf, len, 0)) != XML_ERR_OK) {
+		purple_debug_error("jabber", "xmlParseChunk returned error %i", ret);
+
+		if ((ret >= XML_ERR_INVALID_HEX_CHARREF) && (ret <= XML_ERR_INVALID_CHAR)) {
+			/* If the error involves an invalid character, just drop this message.
+			 * We'll create a new parser next time it's needed. */
+			jabber_parser_free(js);
+		} else {
+			purple_connection_error_reason (js->gc,
+				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+				_("XML Parse error"));
+		}
 	}
 }
 
--- a/libpurple/protocols/jabber/presence.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/jabber/presence.c	Wed Jul 09 02:06:38 2008 +0000
@@ -141,6 +141,11 @@
 	/* check for buzz support */
 	allowBuzz = purple_status_get_attr_boolean(status,"buzz");
 	/* changing the buzz state has to trigger a re-broadcasting of the presence for caps */
+
+	if (js->googletalk && stripped == NULL && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) {
+		tune = purple_presence_get_status(p, "tune");
+		stripped = jabber_google_presence_outgoing(tune);
+	}
 	
 #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \
 					  (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b)))
@@ -149,11 +154,6 @@
 		js->old_priority != priority || CHANGED(js->old_avatarhash, js->avatar_hash)) {
 		js->allowBuzz = allowBuzz;
 
-		if (js->googletalk && stripped == NULL && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) {
-			tune = purple_presence_get_status(p, "tune");
-			stripped = jabber_google_presence_outgoing(tune);
-		}
-
 		presence = jabber_presence_create_js(js, state, stripped, priority);
 
 		if(js->avatar_hash) {
@@ -178,9 +178,9 @@
 		js->old_avatarhash = g_strdup(js->avatar_hash);
 		js->old_state = state;
 		js->old_priority = priority;
-		g_free(stripped);
 	}
-					  	
+	g_free(stripped);
+
 	/* next, check if there are any changes to the tune values */
 	tune = purple_presence_get_status(p, "tune");
 	if (tune && purple_status_is_active(tune)) {
--- a/libpurple/protocols/jabber/roster.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/jabber/roster.c	Wed Jul 09 02:06:38 2008 +0000
@@ -316,7 +316,6 @@
 {
 	JabberStream *js = gc->proto_data;
 	char *who;
-	GSList *groups = NULL;
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
 	char *my_bare_jid;
@@ -329,20 +328,7 @@
 
 	jb = jabber_buddy_find(js, buddy->name, FALSE);
 
-	/*
-	 * For some reason if we're waiting for our subscription request
-	 * to be approved and we try to add the buddy to another group
-	 * then we remove the buddy from the old group.  I don't understand
-	 * the rationale for this, can someone please explain it?  It seems
-	 * like we should pass NULL as the groups parameter to
-	 * jabber_roster_update().
-	 */
-	if(!jb || !(jb->subscription & JABBER_SUB_TO)) {
-		groups = g_slist_append(groups, group->name);
-	}
-
-	jabber_roster_update(js, who, groups);
-	g_slist_free(groups);
+	jabber_roster_update(js, who, NULL);
 
 	my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
 	if(!strcmp(who, my_bare_jid)) {
--- a/libpurple/protocols/oscar/oscar.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Wed Jul 09 02:06:38 2008 +0000
@@ -1519,10 +1519,14 @@
 			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
 			break;
 		case 0x1c:
+		{
 			/* client too old */
-			g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), PURPLE_WEBSITE);
+			GHashTable *ui_info = purple_core_get_ui_info();
+			g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"),
+					   ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
 			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf);
 			break;
+		}
 		case 0x1d:
 			/* IP address connecting too frequently */
 			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
@@ -1640,8 +1644,10 @@
 	}
 	if (in != '\n') {
 		char buf[256];
+		GHashTable *ui_info = purple_core_get_ui_info();		
 		g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly.  You may want to use TOC until "
-			"this is fixed.  Check %s for updates."), PURPLE_WEBSITE);
+			"this is fixed.  Check %s for updates."),
+				   ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
 		purple_notify_warning(pos->gc, NULL,
 							_("Unable to get a valid AIM login hash."),
 							buf);
@@ -1684,8 +1690,10 @@
 	pos->fd = source;
 
 	if (source < 0) {
+		GHashTable *ui_info = purple_core_get_ui_info();				
 		buf = g_strdup_printf(_("You may be disconnected shortly.  "
-				"Check %s for updates."), PURPLE_WEBSITE);
+				"Check %s for updates."),
+				((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
 		purple_notify_warning(pos->gc, NULL,
 							_("Unable to get a valid AIM login hash."),
 							buf);
@@ -1781,10 +1789,13 @@
 			straight_to_hell, pos) == NULL)
 	{
 		char buf[256];
+		GHashTable *ui_info = purple_core_get_ui_info();
 		g_free(pos->modname);
 		g_free(pos);
+
 		g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly.  "
-			"Check %s for updates."), PURPLE_WEBSITE);
+			"Check %s for updates."),
+			((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
 		purple_notify_warning(pos->gc, NULL,
 							_("Unable to get a valid login hash."),
 							buf);
@@ -4917,11 +4928,6 @@
 	purple_debug_info("oscar",
 			   "ssi: syncing local list and server list\n");
 
-	if ((timestamp == 0) || (numitems == 0)) {
-		purple_debug_info("oscar", "Got AIM SSI with a 0 timestamp or 0 numitems--not syncing.  This probably means your buddy list is empty.\n");
-		return 1;
-	}
-
 	/* Clean the buddy list */
 	aim_ssi_cleanlist(od);
 
--- a/libpurple/protocols/oscar/oscar.h	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Wed Jul 09 02:06:38 2008 +0000
@@ -258,6 +258,15 @@
 	"us", "en", \
 }
 
+#define CLIENTINFO_ICQ6_6_0_6059 { \
+	"ICQ Client", \
+	0x010a, \
+	0x0006, 0x0000, \
+	0x0000, 0x17ab, \
+	0x00007535, \
+	"us", "en", \
+}
+
 #define CLIENTINFO_ICQBASIC_14_3_1068 { \
 	"ICQBasic", \
 	0x010a, \
@@ -302,9 +311,9 @@
 #define CLIENTINFO_PURPLE_ICQ { \
 	"Purple/" VERSION, \
 	0x010a, \
-	0x0014, 0x0034, \
-	0x0000, 0x0bb8, \
-	0x0000043d, \
+	0x0006, 0x0000, \
+	0x0000, 0x17ab, \
+	0x00007535, \
 	"us", "en", \
 }
 
--- a/libpurple/protocols/qq/AUTHORS	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/AUTHORS	Wed Jul 09 02:06:38 2008 +0000
@@ -9,11 +9,27 @@
 rakescar    : provided filter for HTML tag
 yyw         : improved performance on PPC linux
 lvxiang     : provided ip to location original code
-csyfek      : faces
 markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007
+ccpaging    : maintainer since 2007
+icesky      : maintainer since 2007
+csyfek      : faces, maintainer since 2007
+
+Lovely Patch Writers
+=====
+Gnap.An     : message displaying, documentation
+manphiz     : qun processing
+moo         : qun processing
+Coly Li     : qun processing
 
 Acknowledgement
 =====
 Shufeng Tan : http://sf.net/projects/perl-oicq
 Jeff Ye     : http://www.sinomac.com
 Hu Zheng    : http://forlinux.yeah.net
+yunfan      : http://www.myswear.net
+khc@pidgin.im
+qulogic@pidgin.im
+rlaager@pidgin.im
+OpenQ Team
+LumaQQ Team
+OpenQ@GoogleGroup
--- a/libpurple/protocols/qq/ChangeLog	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/ChangeLog	Wed Jul 09 02:06:38 2008 +0000
@@ -1,3 +1,14 @@
+2008.06.29 - csyfek <csyfek(at)gmail.com>
+	* Minor bug fix
+	* Add some doxygen syntax for preparing development documentation
+	* References #6199
+
+2008.06.28 - ccpaging <ecc_hy(at)hotmail.com>, moo <phpxcache(at)gmail.com>
+	* Patches from moo<phpxcache@gmail.com> and ccpaging<ccpaging@foxmail.com>.
+	* Tickets:
+	* Fixes #4956.
+	* Fixes #2998.
+
 2008.06.07 - ccpaging <ecc_hy(at)hotmail.com>, csyfek <csyfek(at)gmail.com>
 	* Clean code and apply patches from QuLogic
 
--- a/libpurple/protocols/qq/buddy_list.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/buddy_list.c	Wed Jul 09 02:06:38 2008 +0000
@@ -147,6 +147,7 @@
 {
 	qq_data *qd;
 	gint len, bytes, bytes_buddy;
+	gint count;
 	guint8 *data, position;
 	PurpleBuddy *b;
 	qq_buddy *q_bud;
@@ -173,6 +174,7 @@
 	fe = g_newa(qq_friends_online_entry, 1);
 	fe->s = g_newa(qq_buddy_status, 1);
 
+	count = 0;
 	while (bytes < len) {
 		/* set flag */
 		bytes_buddy = bytes;
@@ -217,6 +219,7 @@
 			q_bud->flag1 = fe->flag1;
 			q_bud->comm_flag = fe->comm_flag;
 			qq_update_buddy_contact(gc, q_bud);
+			count++;
 		} else {
 			purple_debug(PURPLE_DEBUG_ERROR, "QQ", 
 					"Got an online buddy %d, but not in my buddy list\n", fe->s->uid);
@@ -232,10 +235,14 @@
 	}
 
 	if (position != QQ_FRIENDS_ONLINE_POSITION_END) {
-		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Has more online buddies, position from %d\n", position);
-
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d online buddies, nextposition=%u\n",
+								count, (guint) position);
+		if (position != QQ_FRIENDS_ONLINE_POSITION_START) {
+			purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more online buddies\n"); 
+		}
 		qq_send_packet_get_buddies_online(gc, position);
 	} else {
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "All online buddies received\n"); 
 		qq_send_packet_get_buddies_levels(gc);
 		qq_refresh_all_buddy_status(gc);
 	}
@@ -247,7 +254,7 @@
 {
 	qq_data *qd;
 	qq_buddy *q_bud;
-	gint len, bytes_expected, i;
+	gint len, bytes_expected, count;
 	gint bytes, buddy_bytes;
 	guint16 position, unknown;
 	guint8 *data, pascal_len;
@@ -267,7 +274,7 @@
 	bytes = 0;
 	bytes += qq_get16(&position, data + bytes);
 	/* the following data is buddy list in this packet */
-	i = 0;
+	count = 0;
 	while (bytes < len) {
 		q_bud = g_new0(qq_buddy, 1);
 		/* set flag */
@@ -306,7 +313,7 @@
 			g_free(q_bud);
 			continue;
 		} else {
-			i++;
+			count++;
 		}
 
 		if (QQ_DEBUG) {
@@ -332,11 +339,16 @@
 		purple_debug(PURPLE_DEBUG_ERROR, "QQ", 
 				"qq_process_get_buddies_list_reply: Dangerous error! maybe protocol changed, notify developers!");
 	}
-	if (position == QQ_FRIENDS_LIST_POSITION_END) {
-		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get friends list done, %d buddies\n", i);
-		qq_send_packet_get_buddies_online(gc, QQ_FRIENDS_ONLINE_POSITION_START);
+
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies, nextposition=%u\n",
+		count, (guint) position);
+	if (position != QQ_FRIENDS_LIST_POSITION_START
+		&& position != QQ_FRIENDS_LIST_POSITION_END) { 
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies\n"); 
+		qq_send_packet_get_buddies_list(gc, position);
 	} else {
-		qq_send_packet_get_buddies_list(gc, position);
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies received. Requesting for online buddies list\n");
+		qq_send_packet_get_buddies_online(gc, QQ_FRIENDS_LIST_POSITION_START); 
 	}
 }
 
@@ -419,4 +431,11 @@
 	}
 
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Get all list done, %d buddies and %d Quns\n", i, j);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position);
+	if (position != QQ_FRIENDS_ALL_LIST_POSITION_START && position != QQ_FRIENDS_ALL_LIST_POSITION_START) {
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n");
+		qq_send_packet_get_all_list_with_group(gc, position);
+	} else {
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); 
+	}
 }
--- a/libpurple/protocols/qq/buddy_list.h	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/buddy_list.h	Wed Jul 09 02:06:38 2008 +0000
@@ -32,6 +32,8 @@
 #define QQ_FRIENDS_LIST_POSITION_END 		0xffff
 #define QQ_FRIENDS_ONLINE_POSITION_START 	0x00
 #define QQ_FRIENDS_ONLINE_POSITION_END 		0xff
+#define QQ_FRIENDS_ALL_LIST_POSITION_START  0x00000000
+#define QQ_FRIENDS_ALL_LIST_POSITION_END  0xffffffff
 
 void qq_send_packet_get_buddies_online(PurpleConnection *gc, guint8 position);
 void qq_process_get_buddies_online_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
--- a/libpurple/protocols/qq/char_conv.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/char_conv.c	Wed Jul 09 02:06:38 2008 +0000
@@ -123,9 +123,14 @@
 	return g_strdup(QQ_NULL_MSG);
 }
 
-/* take the input as a pascal string and return a converted c-string in UTF-8
+/**
+ * @brief 把输入作为一个pascal字符串并返回一个用UFT-8转换的c-字符串.\n
+ * 返回已读入的字节数,或者当遇到错误时返回-1.该完成转换的UTF-8字符串被保存到ret中
+ *
+ * take the input as a pascal string and return a converted c-string in UTF-8
  * returns the number of bytes read, return -1 if fatal error
- * the converted UTF-8 will be saved in ret */
+ * the converted UTF-8 will be saved in ret
+ */ 
 gint convert_as_pascal_string(guint8 *data, gchar **ret, const gchar *from_charset) 
 {
 	guint8 len;
--- a/libpurple/protocols/qq/group_info.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/group_info.c	Wed Jul 09 02:06:38 2008 +0000
@@ -141,6 +141,9 @@
 	qq_send_group_cmd(gc, group, raw_data, bytes);
 }
 
+/**
+ * @brief 处理群信息.当前群信息的处理还不完善,由于版本的不同导致协议的解读有差异.
+ */
 void qq_process_group_cmd_get_group_info(guint8 *data, gint len, PurpleConnection *gc)
 {
 	qq_group *group;
@@ -163,7 +166,7 @@
 	g_return_if_fail(internal_group_id > 0);
 
 	bytes += qq_get32(&(external_group_id), data + bytes);
-	g_return_if_fail(internal_group_id > 0);
+	g_return_if_fail(external_group_id > 0);
 
 	pending_id = qq_get_pending_id(qd->adding_groups_from_server, internal_group_id);
 	if (pending_id != NULL) {
@@ -183,13 +186,24 @@
 	bytes += qq_get32(&(group->group_category), data + bytes);
 	bytes += qq_get16(&max_members, data + bytes);
 	bytes += qq_get8(&unknown1, data + bytes);
-	bytes += qq_get32(&(unknown4), data + bytes);	/* versionID */
-
+	/* XXX
+	 * the following, while Eva:
+	 * 4(unk), 4(verID), 1(nameLen), nameLen(qunNameContent), 1(0x00),
+	 * 2(qunNoticeLen), qunNoticeLen(qunNoticeContent, 1(qunDescLen),
+	 * qunDestLen(qunDestcontent)) */
+	bytes += qq_get8(&unknown1, data + bytes);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "type=%u creatorid=%u category=%u\n",
+			group->group_type, group->creator_uid, group->group_category);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "maxmembers=%u", max_members); 
+	
 	/* strlen + <str content> */
 	bytes += convert_as_pascal_string(data + bytes, &(group->group_name_utf8), QQ_CHARSET_DEFAULT);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "group \"%s\"\n", group->group_name_utf8); 
 	bytes += qq_get16(&unknown, data + bytes);	/* 0x0000 */
 	bytes += convert_as_pascal_string(data + bytes, &(group->notice_utf8), QQ_CHARSET_DEFAULT);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "notice \"%s\"\n", group->notice_utf8); 
 	bytes += convert_as_pascal_string(data + bytes, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT);
+	purple_debug(PURPLE_DEBUG_INFO, "QQ", "group_desc \"%s\"\n", group->group_desc_utf8); 
 
 	num = 0;
 	/* now comes the member list separated by 0x00 */
--- a/libpurple/protocols/qq/group_internal.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/group_internal.c	Wed Jul 09 02:06:38 2008 +0000
@@ -230,7 +230,9 @@
 		*list = g_slist_remove(*list, GINT_TO_POINTER(id));
 }
 
-/* Return the location of id in list, or NULL if not found */
+/**
+ * @brief Return the location of id in list, or NULL if not found (返回id在链表中的位置,没有找到则返回NULL)
+ */
 GSList *qq_get_pending_id(GSList *list, guint32 id)
 {
         return g_slist_find(list, GINT_TO_POINTER(id));
--- a/libpurple/protocols/qq/im.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/im.c	Wed Jul 09 02:06:38 2008 +0000
@@ -384,8 +384,9 @@
 			im_unprocessed->length = len - bytes;
 			/* a simple process here, maybe more later */
 			purple_debug (PURPLE_DEBUG_WARNING, "QQ",
-					"Normal IM, unprocessed type [0x%04x], unknown [0x%02x], len %d\n",
-					common->normal_im_type, im_unprocessed->unknown, im_unprocessed->length);
+					"Normal IM, unprocessed type [0x%04x], len %d\n",
+					common->normal_im_type, im_unprocessed->length);
+			qq_show_packet ("QQ unk-im", im_unprocessed->unknown, im_unprocessed->length);
 			g_free (common->session_md5);
 			return;
 	}
--- a/libpurple/protocols/qq/qq_network.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.c	Wed Jul 09 02:06:38 2008 +0000
@@ -933,7 +933,7 @@
 			return;
 		}
 
-	purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Connection failed: %d\n", g_strerror(errno));
+	purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Connection failed: %s\n", g_strerror(errno));
 	close(fd);
 }
 
--- a/libpurple/protocols/qq/utils.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/qq/utils.c	Wed Jul 09 02:06:38 2008 +0000
@@ -293,12 +293,12 @@
 	str = g_string_new("");
 	for (i = 0; i < bytes; i += 16) {
 		/* length label */
-		g_string_append_printf(str, "%04d: ", i);
+		g_string_append_printf(str, "%07x: ", i);
 
 		/* dump hex value */
 		for (j = 0; j < 16; j++)
 			if ((i + j) < bytes)
-				g_string_append_printf(str, " %02X", buffer[i + j]);
+				g_string_append_printf(str, " %02x", buffer[i + j]);
 			else
 				g_string_append(str, "   ");
 		g_string_append(str, "  ");
--- a/libpurple/protocols/silc/silc.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/silc/silc.c	Wed Jul 09 02:06:38 2008 +0000
@@ -22,6 +22,7 @@
 #include "silcpurple.h"
 #include "version.h"
 #include "wb.h"
+#include "core.h"
 
 extern SilcClientOperations ops;
 static PurplePlugin *silc_plugin = NULL;
@@ -669,13 +670,31 @@
 #if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
 	SilcPurpleTask task;
 #endif /* __SILC_TOOLKIT_VERSION */
+	GHashTable *ui_info;
+	const char *ui_name = NULL, *ui_website = NULL;
+	char *quit_msg;
 
 	g_return_if_fail(sg != NULL);
 
+	ui_info = purple_core_get_ui_info();
+	
+	if(ui_info) {
+		ui_name = g_hash_table_lookup(ui_info, "name");
+		ui_website = g_hash_table_lookup(ui_info, "website");
+	}
+	
+	if(!ui_name || !ui_website) {
+		ui_name = "Pidgin";
+		ui_website = PURPLE_WEBSITE;
+	}
+	quit_msg = g_strdup_printf(_("Download %s: %s"),
+							   ui_name, ui_website);
+
 	/* Send QUIT */
 	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", "Download Pidgin: " PURPLE_WEBSITE,
+				 "QUIT", quit_msg,
 				 NULL);
+	g_free(quit_msg);
 
 	if (sg->conn)
 		silc_client_close_connection(sg->client, sg->conn);
@@ -1816,7 +1835,10 @@
 {
 	PurpleConnection *gc;
 	SilcPurple sg;
-
+	GHashTable *ui_info;
+	const char *ui_name = NULL, *ui_website = NULL;
+	char *quit_msg;
+								   
 	gc = purple_conversation_get_gc(conv);
 
 	if (gc == NULL)
@@ -1827,8 +1849,23 @@
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
+	ui_info = purple_core_get_ui_info();
+	
+	if(ui_info) {
+		ui_name = g_hash_table_lookup(ui_info, "name");
+		ui_website = g_hash_table_lookup(ui_info, "website");
+	}
+	
+	if(!ui_name || !ui_website) {
+		ui_name = "Pidgin";
+		ui_website = PURPLE_WEBSITE;
+	}
+	quit_msg = g_strdup_printf(_("Download %s: %s"),
+							   ui_name, ui_website);
+
 	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", (args && args[0]) ? args[0] : "Download Pidgin: " PURPLE_WEBSITE, NULL);
+				 "QUIT", (args && args[0]) ? args[0] : quit_msg, NULL);
+	g_free(quit_msg);
 
 	return PURPLE_CMD_RET_OK;
 }
--- a/libpurple/protocols/silc10/silc.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/silc10/silc.c	Wed Jul 09 02:06:38 2008 +0000
@@ -22,6 +22,7 @@
 #include "silcpurple.h"
 #include "version.h"
 #include "wb.h"
+#include "core.h"
 
 extern SilcClientOperations ops;
 static PurplePlugin *silc_plugin = NULL;
@@ -384,12 +385,30 @@
 silcpurple_close(PurpleConnection *gc)
 {
 	SilcPurple sg = gc->proto_data;
+	GHashTable *ui_info;
+	const char *ui_name = NULL, *ui_website = NULL;
+	char *quit_msg;
+	
+	g_return_if_fail(sg != NULL);
 
-	g_return_if_fail(sg != NULL);
+	ui_info = purple_core_get_ui_info();
+
+	if(ui_info) {
+		ui_name = g_hash_table_lookup(ui_info, "name");
+		ui_website = g_hash_table_lookup(ui_info, "website");
+	}
+
+	if(!ui_name || !ui_website) {
+		ui_name = "Pidgin";
+		ui_website = PURPLE_WEBSITE;
+	}
+	quit_msg = g_strdup_printf(_("Download %s: %s"),
+							   ui_name, ui_website);
 
 	/* Send QUIT */
 	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", "Download this: " PURPLE_WEBSITE, NULL);
+				 "QUIT", quit_msg, NULL);
+	g_free(quit_msg);
 
 	if (sg->conn)
 		silc_client_close_connection(sg->client, sg->conn);
@@ -1535,7 +1554,10 @@
 {
 	PurpleConnection *gc;
 	SilcPurple sg;
-
+	GHashTable *ui_info;
+	const char *ui_name = NULL, *ui_website = NULL;
+	char *quit_msg;
+	
 	gc = purple_conversation_get_gc(conv);
 
 	if (gc == NULL)
@@ -1546,8 +1568,23 @@
 	if (sg == NULL)
 		return PURPLE_CMD_RET_FAILED;
 
+	ui_info = purple_core_get_ui_info();
+
+	if(ui_info) {
+		ui_name = g_hash_table_lookup(ui_info, "name");
+		ui_website = g_hash_table_lookup(ui_info, "website");
+	}
+
+	if(!ui_name || !ui_website) {
+		ui_name = "Pidgin";
+		ui_website = PURPLE_WEBSITE;
+	}
+	quit_msg = g_strdup_printf(_("Download %s: %s"),
+							   ui_name, ui_website);
+
 	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", (args && args[0]) ? args[0] : "Download this: " PURPLE_WEBSITE, NULL);
+				 "QUIT", (args && args[0]) ? args[0] : quit_msg, NULL);
+	g_free(quit_msg);
 
 	return PURPLE_CMD_RET_OK;
 }
--- a/libpurple/protocols/yahoo/yahoo.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Wed Jul 09 02:06:38 2008 +0000
@@ -1995,13 +1995,19 @@
 			yahoo_process_auth_new(gc, seed);
 			break;
 		default:
-			buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized "
-						"authentication method.  You will probably not be able "
-						"to successfully sign on to Yahoo.  Check %s for updates."), PURPLE_WEBSITE);
-			purple_notify_error(gc, "", _("Failed Yahoo! Authentication"),
-					  buf);
-			g_free(buf);
-			yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */
+			{
+				GHashTable *ui_info = purple_core_get_ui_info();
+
+				buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized "
+							"authentication method.  You will probably not be able "
+							"to successfully sign on to Yahoo.  Check %s for updates."),
+							((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
+				purple_notify_error(gc, "", _("Failed Yahoo! Authentication"),
+							buf);
+				g_free(buf);
+				yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */
+				break;
+			}
 		}
 	}
 }
--- a/libpurple/purple-url-handler	Wed Jul 09 01:46:10 2008 +0000
+++ b/libpurple/purple-url-handler	Wed Jul 09 02:06:38 2008 +0000
@@ -6,7 +6,15 @@
 import time
 import urllib
 
-obj = dbus.SessionBus().get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
+bus = dbus.SessionBus()
+obj = None
+try:
+    obj = bus.get_object("im.pidgin.purple.PurpleService",
+                         "/im/pidgin/purple/PurpleObject")
+except dbus.DBusException, e:
+    if e._dbus_error_name == "org.freedesktop.DBus.Error.ServiceUnknown":
+        print "Error: no libpurple-powered client is running. Try starting Pidgin or Finch."
+        sys.exit(1)
 purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
 
 class CheckedObject:
@@ -50,20 +58,39 @@
     except:
         return value
 
-def findaccount(protocolname, accountname=""):
+def account_not_found():
+    print "No matching account found."
+    sys.exit(1)
+
+def bring_account_online(account):
+    if not cpurple.PurpleAccountIsConnected(account):
+        # The last argument is meant to be a GList * but the D-Bus binding
+        # generator thing just wants a UInt32, which is pretty failing.
+        # Happily, passing a 0 to mean an empty list turns out to work anyway.
+        purple.PurpleAccountSetStatusList(account, "online", 1, 0)
+        purple.PurpleAccountConnect(account)
+
+def findaccount(protocolname, accountname="", matcher=None):
+    if matcher:
+        for account in cpurple.PurpleAccountsGetAll():
+            if accountname != "" and accountname != cpurple.PurpleAccountGetUsername(a):
+                continue
+            if matcher(account):
+                bring_account_online(account)
+                return account
+        account_not_found()
+
     # prefer connected accounts
     account = cpurple.PurpleAccountsFindConnected(accountname, protocolname)
     if (account != 0):
-	return account
+        return account
 
     # try to get any account and connect it
     account = cpurple.PurpleAccountsFindAny(accountname, protocolname)
     if (account == 0):
-        print "No matching account found."
-	sys.exit(1)
+        account_not_found()
 
-    purple.PurpleAccountSetStatusVargs(account, "online", 1)
-    purple.PurpleAccountConnect(account)
+    bring_account_online(account)
     return account
 
 def goim(account, screenname, message=None):
@@ -178,12 +205,16 @@
             key, value = extendlist(param.split("=", 1), 2, "")
             params[key] = urllib.unquote_plus(value)
 
-    account = findaccount(protocol)
+    def correct_server(account):
+        username = cpurple.PurpleAccountGetUsername(account)
+        return (server == (username.split("@"))[1])
+
+    account = findaccount(protocol, matcher=correct_server)
 
     if (target != ""):
         if (isnick):
             goim(account, urllib.unquote_plus(target.split(",")[0]), params.get("msg"))
-	else:
+        else:
             channel = urllib.unquote_plus(target.split(",")[0])
             if channel[0] != "#":
                 channel = "#" + channel
@@ -213,9 +244,9 @@
         addbuddy(account, screenname)
 
 def myim(uri):
-	protocol = "prpl-myspace"
-	print "TODO: send uri: ", uri
-	assert False, "Not implemented"
+        protocol = "prpl-myspace"
+        print "TODO: send uri: ", uri
+        assert False, "Not implemented"
 
 def sip(uri):
     protocol = "prpl-simple"
@@ -328,9 +359,9 @@
             ymsgr(uri)
         else:
             print "Unknown protocol: %s" % type
-    except dbus.dbus_bindings.DBusException:
-        print "ERROR: Is there a libpurple-powered client (e.g. Pidgin or Finch) running?"
-
+    except dbus.DBusException, e:
+        print "Error: %s" % (e.message)
+        sys.exit(1)
 
 if __name__ == "__main__":
     main()
--- a/pidgin/gtkmain.c	Wed Jul 09 01:46:10 2008 +0000
+++ b/pidgin/gtkmain.c	Wed Jul 09 02:06:38 2008 +0000
@@ -350,6 +350,8 @@
 
 		g_hash_table_insert(ui_info, "name", (char*)PIDGIN_NAME);
 		g_hash_table_insert(ui_info, "version", VERSION);
+		g_hash_table_insert(ui_info, "website", "http://pidgin.im");
+		g_hash_table_insert(ui_info, "dev_website", "http://developer.pidgin.im");
 	}
 
 	return ui_info;
--- a/po/POTFILES.in	Wed Jul 09 01:46:10 2008 +0000
+++ b/po/POTFILES.in	Wed Jul 09 02:06:38 2008 +0000
@@ -143,12 +143,9 @@
 libpurple/protocols/qq/keep_alive.c
 libpurple/protocols/qq/login_logout.c
 libpurple/protocols/qq/qq.c
-libpurple/protocols/qq/qq_proxy.c
-libpurple/protocols/qq/recv_core.c
+libpurple/protocols/qq/qq_network.c
 libpurple/protocols/qq/send_file.c
-libpurple/protocols/qq/sendqueue.c
 libpurple/protocols/qq/sys_msg.c
-libpurple/protocols/qq/udp_proxy_s5.c
 libpurple/protocols/sametime/sametime.c
 libpurple/protocols/silc/buddy.c
 libpurple/protocols/silc/chat.c
--- a/po/de.po	Wed Jul 09 01:46:10 2008 +0000
+++ b/po/de.po	Wed Jul 09 02:06:38 2008 +0000
@@ -11,9 +11,9 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-06-25 23:30+0200\n"
-"PO-Revision-Date: 2008-06-25 23:27+0200\n"
-"Last-Translator: Bjoern Voigt <bjoern@cs.tu-berlin.de>\n"
+"POT-Creation-Date: 2008-07-06 14:20+0200\n"
+"PO-Revision-Date: 2008-07-06 14:20+0200\n"
+"Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -6369,7 +6369,6 @@
 "versuchen Sie es noch einmal. Wenn Sie es weiterversuchen, müssen Sie sogar "
 "noch länger warten."
 
-#. client too old
 #, c-format
 msgid "The client version you are using is too old. Please upgrade at %s"
 msgstr ""
@@ -7336,10 +7335,6 @@
 msgid "Unable to login"
 msgstr "Anmeldung fehlgeschlagen"
 
-#. we didn't successfully connect. tdt->toc_fd is valid here
-msgid "Unable to connect."
-msgstr "Verbindung nicht möglich."
-
 #, c-format
 msgid "Unknown-%d"
 msgstr "Unbekannt-%d"
@@ -7365,12 +7360,16 @@
 msgstr "<b>Letzte Aktualisierung</b>: %s<br>\n"
 
 #, c-format
+msgid "<b>Server</b>: %s: %d<br>\n"
+msgstr "<b>Server</b>: %s: %d<br>\n"
+
+#, c-format
 msgid "<b>Connection Mode</b>: %s<br>\n"
 msgstr "<b>Verbindungsmodus</b>: %s<br>\n"
 
 #, c-format
-msgid "<b>Server IP</b>: %s: %d<br>\n"
-msgstr "<b>Server-IP</b>: %s: %d<br>\n"
+msgid "<b>Real hostname</b>: %s: %d<br>\n"
+msgstr "<b>Wirklicher Hostname</b>: %s: %d<br>\n"
 
 #, c-format
 msgid "<b>My Public IP</b>: %s<br>\n"
@@ -7422,12 +7421,49 @@
 msgid "Connect using TCP"
 msgstr "Über TCP verbinden"
 
+msgid "Failed to connect server"
+msgstr "Verbinden zum Server fehlgeschlagen"
+
 msgid "Socket error"
 msgstr "Socket-Fehler"
 
+#, c-format
+msgid ""
+"Lost connection with server:\n"
+"%d, %s"
+msgstr ""
+"Verbindung zum Server verloren:\n"
+"%d, %s"
+
 msgid "Unable to read from socket"
 msgstr "Socket kann nicht gelesen werden"
 
+msgid "Write Error"
+msgstr "Schreibfehler"
+
+msgid "Connection lost"
+msgstr "Verbindung verloren"
+
+msgid "Login failed, no reply"
+msgstr "Anmeldung fehlgeschlagen, keine Antwort"
+
+msgid "Couldn't resolve host"
+msgstr "Kann den Hostnamen nicht auflösen"
+
+msgid "hostname is NULL or port is 0"
+msgstr "Hostname ist NULL oder Port ist 0"
+
+#, c-format
+msgid "Connecting server %s, retries %d"
+msgstr "Verbinde zu Server %s, %d Wiederholungen"
+
+#. we didn't successfully connect. tdt->toc_fd is valid here
+msgid "Unable to connect."
+msgstr "Verbindung nicht möglich."
+
+msgid "Could not resolve hostname"
+msgstr "Konnte den Hostnamen nicht auflösen"
+
 #, c-format
 msgid "%d has declined the file %s"
 msgstr "%d hat die Datei %s abgelehnt"
@@ -7439,12 +7475,6 @@
 msgid "%d canceled the transfer of %s"
 msgstr "%d hat die Übertragung von %s abgebrochen"
 
-msgid "Connection lost"
-msgstr "Verbindung verloren"
-
-msgid "Login failed, no reply"
-msgstr "Anmeldung fehlgeschlagen, keine Antwort"
-
 msgid "Do you want to add this buddy?"
 msgstr "Möchten Sie diesen Buddy hinzufügen?"
 
@@ -8502,6 +8532,10 @@
 msgid "Error loading SILC key pair"
 msgstr "Fehler beim Laden des SILC-Schlüsselpaares"
 
+#, c-format
+msgid "Download %s: %s"
+msgstr "Download %s: %s"
+
 msgid "Your Current Mood"
 msgstr "Ihre momentane Stimmung"
 
@@ -8946,12 +8980,6 @@
 msgid "Could not create listen socket"
 msgstr "Kann Listen-Socket nicht erstellen"
 
-msgid "Couldn't resolve host"
-msgstr "Kann den Hostnamen nicht auflösen"
-
-msgid "Could not resolve hostname"
-msgstr "Konnte den Hostnamen nicht auflösen"
-
 msgid "SIP usernames may not contain whitespaces or @ symbols"
 msgstr "SIP-Benutzernamen dürfen keine Leerzeichen oder @-Symbole enthalten"
 
@@ -9398,9 +9426,6 @@
 msgid "%s is trying to send you a group of %d files.\n"
 msgstr "%s versucht, Ihnen eine Gruppe von %d Dateien zu senden.\n"
 
-msgid "Write Error"
-msgstr "Schreibfehler"
-
 msgid "Yahoo! Japan Profile"
 msgstr "Yahoo!-Japan-Profil"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/ca-certs/CAcert_Class3.pem	Wed Jul 09 02:06:38 2008 +0000
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290
+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB
+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA
+Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS
+BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v
+cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9
+4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB
+Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J
+0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ
+FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx
+bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q
+SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb
+6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV
+m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g
+eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG
+kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7
+6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG
+CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc
+aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB
+gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w
+aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6
+tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0
+nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M
+77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV
+Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L
+ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM
+zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU
+rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF
+YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT
+oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu
+FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB
+0m6lG5kngOcLqagA
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/ca-certs/CAcert_Root.pem	Wed Jul 09 02:06:38 2008 +0000
@@ -0,0 +1,41 @@
+-----BEGIN CERTIFICATE-----
+MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290
+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB
+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA
+Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO
+BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi
+MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ
+ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ
+8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6
+zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y
+fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7
+w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc
+G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k
+epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q
+laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ
+QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU
+fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826
+YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w
+ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY
+gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe
+MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0
+IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy
+dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw
+czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0
+dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl
+aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC
+AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg
+b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB
+ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc
+nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg
+18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c
+gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl
+Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY
+sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T
+SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF
+CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum
+GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk
+zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW
+omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD
+-----END CERTIFICATE-----
--- a/share/ca-certs/Makefile.am	Wed Jul 09 01:46:10 2008 +0000
+++ b/share/ca-certs/Makefile.am	Wed Jul 09 02:06:38 2008 +0000
@@ -1,4 +1,6 @@
 CERTIFICATES = \
+		CAcert_Root.pem \
+		CAcert_Class3.pem \
 		Equifax_Secure_CA.pem \
 		GTE_CyberTrust_Global_Root.pem \
 		Microsoft_Secure_Server_Authority.pem \