changeset 30295:77aba27f64da

merged from im.pidgin.pidgin. removed our modification to jabber file transfer for now.
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Wed, 05 May 2010 15:42:34 +0900
parents 28dd2b7331fd (current diff) 711cd774ea84 (diff)
children ad6777045e41
files libpurple/protocols/irc/irc.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/message.c libpurple/protocols/jabber/si.c libpurple/protocols/msn/msn.c libpurple/protocols/oscar/oscar.c libpurple/protocols/yahoo/libyahoo.c libpurple/protocols/yahoo/libyahoojp.c libpurple/util.c
diffstat 52 files changed, 1421 insertions(+), 626 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Wed Apr 28 19:22:17 2010 +0900
+++ b/COPYRIGHT	Wed May 05 15:42:34 2010 +0900
@@ -330,6 +330,7 @@
 Andrei Mozzhuhin
 Christian Muise
 MXit Lifestyle (Pty) Ltd.
+Alexander Nartov
 Richard Nelson
 Dennis Nezic
 Matthew A. Nicholson
--- a/ChangeLog	Wed Apr 28 19:22:17 2010 +0900
+++ b/ChangeLog	Wed May 05 15:42:34 2010 +0900
@@ -4,8 +4,8 @@
 	General:
 	* Changed GTK+ minimum version requirement to 2.10.0.
 	* Changed GLib minimum version requirement to 2.12.0.
-	* Using the --disable-nls argument to configre now works properly. You
-	  will no longer be forced to have intltool to configure and build.
+	* Using the --disable-nls argument to configure now works properly.
+	  You will no longer be forced to have intltool to configure and build.
 	* Fix two related crashes in the GnuTLS and NSS plugins when they
 	  suffer internal errors immediately upon attempting to establish
 	  an SSL connection.
@@ -50,7 +50,9 @@
 	* The 'Message Timestamp Formats' plugin allows forcing 12-hour
 	  timestamps.  (Jonathan Maltz)
 	* Fix pastes from Chrome (rich-text pastes and probably URLs
-	  having garbage appended to them)
+	  having garbage appended to them).
+	* Show file transfer thumbnails for images on supporting protocols
+	  (currently only supported on MSN).
 
 	Bonjour:
 	* Added support for IPv6. (Thanks to T_X for testing)
@@ -72,10 +74,13 @@
 	  authentication fails due to an incorrect password.  (This is the same
 	  behavior as the legacy authentication method)
 	* Support sending and receiving HTML-formatted messages for ICQ.
+	* Use the proper URL for "View web profile" link for ICQ buddies.
+	  (Alexander Nartov)
 
 	MSN:
 	* Support for version 9 of the MSN protocol has been removed.  This
 	  version is no longer supported on the servers.
+	* Support file transfer thumbnails (previews) for images.
 
 	XMPP:
 	* Direct messages to a specific resource only upon receipt of a message
@@ -93,6 +98,11 @@
 	  minutes).  This fixes an issue with Openfire disconnecting a
 	  libpurple-baesd client that has just been quiet for about 6
 	  minutes.
+	* Only support Google Talk's JID Domain Discovery extension
+	  (allowing a user to log in with "@gmail.com" or "@googlemail.com"
+	  interchangeably) for those two domains.  This change was made
+	  due to interoperability issues with some BOSH Connection Managers
+	  and namespaced attributes.
 
 	Yahoo/Yahoo JAPAN:
 	* Attempt to better handle transparent proxies interfering with
--- a/ChangeLog.API	Wed Apr 28 19:22:17 2010 +0900
+++ b/ChangeLog.API	Wed May 05 15:42:34 2010 +0900
@@ -9,14 +9,26 @@
 		   * account-connection-error
 		* purple_account_get_name_for_display
 		* purple_account_get_privacy_type
+		* purple_account_get_public_alias
 		* purple_account_set_privacy_type
+		* purple_account_set_public_alias
+		* buddy-caps-changed blist signal
+		* Added media_caps to the PurpleBuddy struct
 		* purple_buddy_get_media_caps
 		* purple_buddy_set_media_caps
+		* purple_certificates_import for importing multiple
+		  certificates from a single file (and corresponding
+		  import_certificates member of PurpleCertificateScheme struct)
+		* autojoin connection signal
 		* purple_contact_get_group
+		* sent-attention conversation signal
+		* got-attention conversation signal
+		* ui-caps-changed media manager signal
 		* purple_media_candidate_copy
 		* purple_media_codec_copy
 		* purple_media_manager_get_backend_type
 		* purple_media_manager_set_backend_type
+		* PurpleMood struct in status.h
 		* purple_network_get_all_local_system_ips, which returns all
 		  local IPs on the system.  On systems with the getifaddrs()
 		  function, this will return both IPv4 and IPv6 addresses
@@ -29,20 +41,16 @@
 		  only supported if the getaddrinfo() function is available
 		  at build-time (not the case on Windows, currently).
 		* purple_prpl_got_media_caps
+		* purple_request_action_with_icon
+		* purple_request_action_with_icon_varg
 		* purple_socket_get_family
 		* purple_socket_speaks_ipv4
 		* purple_unescape_text
 		* purple_uuid_random
-		* media_caps to the PurpleBuddy struct
-		* buddy-caps-changed blist signal
-		* ui-caps-changed media manager signal
-		* sent-attention conversation signal
-		* got-attention conversation signal
-		* PurpleMood struct in status.h
-		* purple_certificates_import for importing multiple
-		  certificates from a single file (and corresponding
-		  import_certificates member of PurpleCertificateScheme struct)
-		* autojoin connection signal 
+		* purple_xfer_get_thumbnail
+		* purple_xfer_get_thumbnail_mimetype
+		* purple_xfer_set_thumbnail
+		* purple_xfer_prepare_thumbnail
 
 	Pidgin:
 		Added:
--- a/libpurple/account.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/account.c	Wed May 05 15:42:34 2010 +0900
@@ -1782,6 +1782,92 @@
 	schedule_accounts_save();
 }
 
+struct public_alias_closure
+{
+	PurpleAccount *account;
+	gpointer failure_cb;
+};
+
+static gboolean
+set_public_alias_unsupported(gpointer data)
+{
+	struct public_alias_closure *closure = data;
+	PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
+
+	failure_cb(closure->account,
+	           _("This protocol does not support setting a public alias."));
+	g_free(closure);
+
+	return FALSE;
+}
+
+void
+purple_account_set_public_alias(PurpleAccount *account,
+		const char *alias, PurpleSetPublicAliasSuccessCallback success_cb,
+		PurpleSetPublicAliasFailureCallback failure_cb)
+{
+	PurpleConnection *gc;
+	PurplePlugin *prpl = NULL;
+	PurplePluginProtocolInfo *prpl_info = NULL;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(purple_account_is_connected(account));
+
+	gc = purple_account_get_connection(account);
+	prpl = purple_connection_get_prpl(gc);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, set_public_alias))
+		prpl_info->set_public_alias(gc, alias, success_cb, failure_cb);
+	else {
+		struct public_alias_closure *closure =
+				g_new0(struct public_alias_closure, 1);
+		closure->account = account;
+		closure->failure_cb = failure_cb;
+		purple_timeout_add(0, set_public_alias_unsupported, closure);
+	}
+}
+
+static gboolean
+get_public_alias_unsupported(gpointer data)
+{
+	struct public_alias_closure *closure = data;
+	PurpleGetPublicAliasFailureCallback failure_cb = closure->failure_cb;
+
+	failure_cb(closure->account,
+	           _("This protocol does not support fetching the public alias."));
+	g_free(closure);
+
+	return FALSE;
+}
+
+void
+purple_account_get_public_alias(PurpleAccount *account,
+		PurpleGetPublicAliasSuccessCallback success_cb,
+		PurpleGetPublicAliasFailureCallback failure_cb)
+{
+	PurpleConnection *gc;
+	PurplePlugin *prpl = NULL;
+	PurplePluginProtocolInfo *prpl_info = NULL;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(purple_account_is_connected(account));
+
+	gc = purple_account_get_connection(account);
+	prpl = purple_connection_get_prpl(gc);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_public_alias))
+		prpl_info->get_public_alias(gc, success_cb, failure_cb);
+	else {
+		struct public_alias_closure *closure =
+				g_new0(struct public_alias_closure, 1);
+		closure->account = account;
+		closure->failure_cb = failure_cb;
+		purple_timeout_add(0, get_public_alias_unsupported, closure);
+	}
+}
+
 void
 purple_account_clear_settings(PurpleAccount *account)
 {
--- a/libpurple/account.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/account.h	Wed May 05 15:42:34 2010 +0900
@@ -39,6 +39,10 @@
 typedef void (*PurpleAccountRequestAuthorizationCb)(void *);
 typedef void (*PurpleAccountRegistrationCb)(PurpleAccount *account, gboolean succeeded, void *user_data);
 typedef void (*PurpleAccountUnregistrationCb)(PurpleAccount *account, gboolean succeeded, void *user_data);
+typedef void (*PurpleSetPublicAliasSuccessCallback)(PurpleAccount *account, const char *new_alias);
+typedef void (*PurpleSetPublicAliasFailureCallback)(PurpleAccount *account, const char *error);
+typedef void (*PurpleGetPublicAliasSuccessCallback)(PurpleAccount *account, const char *alias);
+typedef void (*PurpleGetPublicAliasFailureCallback)(PurpleAccount *account, const char *error);
 
 #include "connection.h"
 #include "log.h"
@@ -462,6 +466,42 @@
 	const char *status_id, gboolean active, GList *attrs);
 
 /**
+ * Set a server-side (public) alias for this account.  The account
+ * must already be connected.
+ *
+ * Currently, the public alias is not stored locally, although this
+ * may change in a later version.
+ *
+ * @param account    The account
+ * @param alias      The new public alias for this account or NULL
+ *                   to unset the alias/nickname (or return it to
+ *                   a protocol-specific "default", like the username)
+ * @param success_cb A callback which will be called if the alias
+ *                   is successfully set on the server (or NULL).
+ * @param failure_cb A callback which will be called if the alias
+ *                   is not successfully set on the server (or NULL).
+ *
+ * @since 2.7.0
+ */
+void purple_account_set_public_alias(PurpleAccount *account,
+	const char *alias, PurpleSetPublicAliasSuccessCallback success_cb,
+	PurpleSetPublicAliasFailureCallback failure_cb);
+
+/**
+ * Fetch the server-side (public) alias for this account.  The account
+ * must already be connected.
+ *
+ * @param account    The account
+ * @param success_cb A callback which will be called with the alias
+ * @param failure_cb A callback which will be called if the prpl is
+ *                   unable to retrieve the server-side alias.
+ * @since 2.7.0
+ */
+void purple_account_get_public_alias(PurpleAccount *account,
+	PurpleGetPublicAliasSuccessCallback success_cb,
+	PurpleGetPublicAliasFailureCallback failure_cb);
+
+/**
  * Clears all protocol-specific settings on an account.
  *
  * @param account The account.
--- a/libpurple/ft.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/ft.c	Wed May 05 15:42:34 2010 +0900
@@ -60,6 +60,10 @@
 
 	/* TODO: Should really use a PurpleCircBuffer for this. */
 	GByteArray *buffer;
+
+	gpointer thumbnail_data;		/**< thumbnail image */
+	gsize thumbnail_size;
+	gchar *thumbnail_mimetype;
 } PurpleXferPrivData;
 
 static int purple_xfer_choose_file(PurpleXfer *xfer);
@@ -72,6 +76,10 @@
 	if (priv->buffer)
 		g_byte_array_free(priv->buffer, TRUE);
 
+	g_free(priv->thumbnail_data);
+
+	g_free(priv->thumbnail_mimetype);
+
 	g_free(priv);
 }
 
@@ -266,15 +274,21 @@
 	}
 }
 
-void purple_xfer_conversation_write(PurpleXfer *xfer, char *message, gboolean is_error)
+static void 
+purple_xfer_conversation_write_internal(PurpleXfer *xfer,
+	const char *message, gboolean is_error, gboolean print_thumbnail)
 {
 	PurpleConversation *conv = NULL;
 	PurpleMessageFlags flags = PURPLE_MESSAGE_SYSTEM;
 	char *escaped;
+	gconstpointer thumbnail_data;
+	gsize size;
 
 	g_return_if_fail(xfer != NULL);
 	g_return_if_fail(message != NULL);
 
+	thumbnail_data = purple_xfer_get_thumbnail(xfer, &size);
+
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who,
 											   purple_xfer_get_account(xfer));
 
@@ -286,10 +300,39 @@
 	if (is_error)
 		flags |= PURPLE_MESSAGE_ERROR;
 
-	purple_conversation_write(conv, NULL, escaped, flags, time(NULL));
+	if (print_thumbnail && thumbnail_data) {
+		gchar *message_with_img;
+		gpointer data = g_memdup(thumbnail_data, size); 
+		int id = purple_imgstore_add_with_id(data, size, NULL);
+
+		message_with_img = 
+			g_strdup_printf("<img id='%d'> %s", id, escaped);
+		purple_conversation_write(conv, NULL, message_with_img, flags, 
+			time(NULL));
+		purple_imgstore_unref_by_id(id);
+		g_free(message_with_img);
+	} else {
+		purple_conversation_write(conv, NULL, escaped, flags, time(NULL));
+	}
 	g_free(escaped);
 }
 
+void
+purple_xfer_conversation_write(PurpleXfer *xfer, gchar *message,
+	gboolean is_error)
+{
+	purple_xfer_conversation_write_internal(xfer, message, is_error, FALSE);
+}
+
+/* maybe this one should be exported publically? */
+static void
+purple_xfer_conversation_write_with_thumbnail(PurpleXfer *xfer,
+	const gchar *message)
+{
+	purple_xfer_conversation_write_internal(xfer, message, FALSE, TRUE);
+}
+
+
 static void purple_xfer_show_file_error(PurpleXfer *xfer, const char *filename)
 {
 	int err = errno;
@@ -448,6 +491,8 @@
 {
 	char *buf, *size_buf;
 	size_t size;
+	gconstpointer thumb;
+	gsize thumb_size;
 
 	/* If we have already accepted the request, ask the destination file
 	   name directly */
@@ -473,13 +518,19 @@
 			serv_got_im(purple_account_get_connection(xfer->account),
 								 xfer->who, xfer->message, 0, time(NULL));
 
-		purple_request_accept_cancel(xfer, NULL, buf, NULL,
-								  PURPLE_DEFAULT_ACTION_NONE,
-								  xfer->account, xfer->who, NULL,
-								  xfer,
-								  G_CALLBACK(purple_xfer_choose_file),
-								  G_CALLBACK(cancel_recv_cb));
-
+		if ((thumb = purple_xfer_get_thumbnail(xfer, &thumb_size))) {
+			purple_request_accept_cancel_with_icon(xfer, NULL, buf, NULL,
+				PURPLE_DEFAULT_ACTION_NONE, xfer->account, xfer->who, NULL,
+				thumb, thumb_size, xfer,
+				G_CALLBACK(purple_xfer_choose_file),
+				G_CALLBACK(cancel_recv_cb));
+		} else {
+			purple_request_accept_cancel(xfer, NULL, buf, NULL,
+				PURPLE_DEFAULT_ACTION_NONE, xfer->account, xfer->who, NULL,
+				xfer, G_CALLBACK(purple_xfer_choose_file),
+				G_CALLBACK(cancel_recv_cb));
+		}
+			
 		g_free(buf);
 	} else
 		purple_xfer_choose_file(xfer);
@@ -547,10 +598,12 @@
 		{
 			gchar* message = NULL;
 			PurpleBuddy *buddy = purple_find_buddy(xfer->account, xfer->who);
+
 			message = g_strdup_printf(_("%s is offering to send file %s"),
 				buddy ? purple_buddy_get_alias(buddy) : xfer->who, purple_xfer_get_filename(xfer));
-			purple_xfer_conversation_write(xfer, message, FALSE);
+			purple_xfer_conversation_write_with_thumbnail(xfer, message);
 			g_free(message);
+
 			/* Ask for a filename to save to if it's not already given by a plugin */
 			if (xfer->local_filename == NULL)
 				purple_xfer_ask_recv(xfer);
@@ -1580,6 +1633,52 @@
 		ui_ops->update_progress(xfer, purple_xfer_get_progress(xfer));
 }
 
+gconstpointer
+purple_xfer_get_thumbnail(const PurpleXfer *xfer, gsize *len)
+{
+	PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
+
+	if (len)
+		*len = priv->thumbnail_size;
+
+	return priv->thumbnail_data;
+}
+
+const gchar *
+purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer)
+{
+	PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
+
+	return priv->thumbnail_mimetype;
+}
+
+void
+purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
+	gsize size, const gchar *mimetype)
+{
+	PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
+
+	g_free(priv->thumbnail_data);
+	g_free(priv->thumbnail_mimetype);
+
+	if (thumbnail && size > 0) {
+		priv->thumbnail_data = g_memdup(thumbnail, size);
+		priv->thumbnail_size = size;
+		priv->thumbnail_mimetype = g_strdup(mimetype);
+	} else {
+		priv->thumbnail_data = NULL;
+		priv->thumbnail_size = 0;
+		priv->thumbnail_mimetype = NULL;
+	}
+}
+
+void
+purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats)
+{
+	if (xfer->ui_ops->add_thumbnail) {
+		xfer->ui_ops->add_thumbnail(xfer, formats);
+	}
+}
 
 /**************************************************************************
  * File Transfer Subsystem API
--- a/libpurple/ft.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/ft.h	Wed May 05 15:42:34 2010 +0900
@@ -120,7 +120,12 @@
 	 */
 	void (*data_not_sent)(PurpleXfer *xfer, const guchar *buffer, gsize size);
 
-	void (*_purple_reserved1)(void);
+	/**
+	 * Op to create a thumbnail image for a file transfer
+	 *
+	 * @param xfer   The file transfer structure
+	 */
+	void (*add_thumbnail)(PurpleXfer *xfer, const gchar *formats);
 } PurpleXferUiOps;
 
 /**
@@ -687,6 +692,51 @@
  */
 void purple_xfer_prpl_ready(PurpleXfer *xfer);
 
+/**
+ * Gets the thumbnail data for a transfer
+ *
+ * @param xfer The file transfer to get the thumbnail for
+ * @param len  If not @c NULL, the length of the thumbnail data returned
+ *             will be set in the location pointed to by this.
+ * @return The thumbnail data, or NULL if there is no thumbnail
+ * @since 2.7.0
+ */
+gconstpointer purple_xfer_get_thumbnail(const PurpleXfer *xfer, gsize *len);
+
+/**
+ * Gets the mimetype of the thumbnail preview for a transfer
+ *
+ * @param xfer The file transfer to get the mimetype for
+ * @return The mimetype of the thumbnail, or @c NULL if not thumbnail is set
+ * @since 2.7.0
+ */
+const gchar *purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer);
+	
+	
+/**
+ * Sets the thumbnail data for a transfer
+ *
+ * @param xfer The file transfer to set the data for
+ * @param thumbnail A pointer to the thumbnail data, this will be copied
+ * @param size The size in bytes of the passed in thumbnail data
+ * @param mimetype The mimetype of the generated thumbnail
+ * @since 2.7.0
+ */
+void purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
+	gsize size, const gchar *mimetype);
+
+/**
+ * Prepare a thumbnail for a transfer (if the UI supports it)
+ * will be no-op in case the UI doesn't implement thumbnail creation
+ *
+ * @param xfer The file transfer to create a thumbnail for
+ * @param formats A comma-separated list of mimetypes for image formats
+ *	 	  the protocols can use for thumbnails.
+ * @since 2.7.0
+ */
+void purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats);
+
+
 /*@}*/
 
 /**************************************************************************/
--- a/libpurple/protocols/bonjour/bonjour.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/bonjour/bonjour.c	Wed May 05 15:42:34 2010 +0900
@@ -528,7 +528,9 @@
 	NULL,                                                    /* get_account_text_table */
 	NULL,                                                    /* initiate_media */
 	NULL,                                                    /* get_media_caps */
-	NULL                                                     /* get_moods */
+	NULL,                                                    /* get_moods */
+	NULL,                                                    /* set_public_alias */
+	NULL                                                     /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/gg/gg.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/gg/gg.c	Wed May 05 15:42:34 2010 +0900
@@ -1601,12 +1601,6 @@
 			}
 			break;
 		case GG_EVENT_NOTIFY60:
-			purple_debug_info("gg",
-				"notify60_pre: (%d) status=%d; version=%d; descr=%s\n",
-				ev->event.notify60->uin, GG_S(ev->event.notify60->status),
-				ev->event.notify60->version,
-				ev->event.notify60->descr ? ev->event.notify60->descr : "(null)");
-
 			for (i = 0; ev->event.notify60[i].uin; i++) {
 				purple_debug_info("gg",
 					"notify60: (%d) status=%d; version=%d; descr=%s\n",
@@ -1737,7 +1731,7 @@
 							  ggp_callback_recv, gc);
 				
 				ggp_buddylist_send(gc);
-				purple_connection_update_progress(gc, _("Connected"), 2, 2);
+				purple_connection_update_progress(gc, _("Connected"), 1, 2);
 				purple_connection_set_state(gc, PURPLE_CONNECTED);
 			}
 			break;
@@ -1990,7 +1984,7 @@
 		purple_debug_info("gg", "Trying to retrieve address from gg appmsg service\n");
 
 	info->session = gg_login(glp);
-	purple_connection_update_progress(gc, _("Connecting"), 1, 2); 			
+	purple_connection_update_progress(gc, _("Connecting"), 0, 2); 			
 	if (info->session == NULL) {
 		purple_connection_error_reason (gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -2512,7 +2506,9 @@
 	NULL,                           /* get_account_text_table */
 	NULL,                           /* initiate_media */
 	NULL,                            /* can_do_media */
-	NULL 				/* get_moods */
+	NULL,				/* get_moods */
+	NULL,				/* set_public_alias */
+	NULL				/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/protocols/gg/search.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/gg/search.c	Wed May 05 15:42:34 2010 +0900
@@ -207,7 +207,7 @@
 {
 	char *tmp;
 
-	tmp = charset_convert(gg_pubdir50_get(res, num, field), "CP1250", "UTF-8");
+	tmp = g_strdup(gg_pubdir50_get(res, num, field));
 
 	return (tmp == NULL) ? g_strdup("") : tmp;
 }
--- a/libpurple/protocols/irc/irc.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/irc/irc.c	Wed May 05 15:42:34 2010 +0900
@@ -945,7 +945,9 @@
 	NULL,                    /* get_account_text_table */
 	NULL,                    /* initiate_media */
 	NULL,					 /* get_media_caps */
-	NULL					 /* get_moods */
+	NULL,					 /* get_moods */
+	NULL,					 /* set_public_alias */
+	NULL					 /* get_public_alias */
 };
 
 static gboolean load_plugin (PurplePlugin *plugin) {
--- a/libpurple/protocols/jabber/auth.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/auth.c	Wed May 05 15:42:34 2010 +0900
@@ -45,35 +45,6 @@
                                JabberIqType type, const char *id,
                                xmlnode *packet, gpointer data);
 
-gboolean
-jabber_process_starttls(JabberStream *js, xmlnode *packet)
-{
-	PurpleAccount *account;
-	xmlnode *starttls;
-
-	account = purple_connection_get_account(js->gc);
-
-	if((starttls = xmlnode_get_child(packet, "starttls"))) {
-		if(purple_ssl_is_supported()) {
-			jabber_send_raw(js,
-					"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1);
-			return TRUE;
-		} else if(xmlnode_get_child(starttls, "required")) {
-			purple_connection_error_reason(js->gc,
-				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-				_("Server requires TLS/SSL, but no TLS/SSL support was found."));
-			return TRUE;
-		} else if(purple_account_get_bool(account, "require_tls", JABBER_DEFAULT_REQUIRE_TLS)) {
-			purple_connection_error_reason(js->gc,
-				 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-				_("You require encryption, but no TLS/SSL support was found."));
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
 static void finish_plaintext_authentication(JabberStream *js)
 {
 	JabberIq *iq;
--- a/libpurple/protocols/jabber/auth.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/auth.h	Wed May 05 15:42:34 2010 +0900
@@ -45,7 +45,6 @@
 	void (*dispose)(JabberStream *js);
 };
 
-gboolean jabber_process_starttls(JabberStream *js, xmlnode *packet);
 void jabber_auth_start(JabberStream *js, xmlnode *packet);
 void jabber_auth_start_old(JabberStream *js);
 void jabber_auth_handle_challenge(JabberStream *js, xmlnode *packet);
--- a/libpurple/protocols/jabber/auth_cyrus.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/auth_cyrus.c	Wed May 05 15:42:34 2010 +0900
@@ -252,29 +252,14 @@
 					g_free(msg);
 					return JABBER_SASL_STATE_CONTINUE;
 
-				} else {
-					/* We have no mechs which can work.
-					 * Try falling back on the old jabber:iq:auth method. We get here if the server supports
-					 * one or more sasl mechs, we are compiled with cyrus-sasl support, but we support or can connect with none of
-					 * the offerred mechs. jabberd 2.0 w/ SASL and Apple's iChat Server 10.5 both handle and expect
-					 * jabber:iq:auth in this situation.  iChat Server in particular offers SASL GSSAPI by default, which is often
-					 * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails.
-					 *
-					 * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However,
-					 * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms.
-					 * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers
-					 * which would connect without issue otherwise. -evands
-					 */
-					js->auth_mech = NULL;
-					jabber_auth_start_old(js);
-					return JABBER_SASL_STATE_CONTINUE;
 				}
-				/* not reached */
+
 				break;
 
 				/* Fatal errors. Give up and go home */
 			case SASL_BADPARAM:
 			case SASL_NOMEM:
+				*error = g_strdup(_("SASL authentication failed"));
 				break;
 
 				/* For everything else, fail the mechanism and try again */
@@ -314,8 +299,11 @@
 		xmlnode_set_namespace(auth, 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 (g_str_equal(js->user->domain, "gmail.com") ||
+				g_str_equal(js->user->domain, "googlemail.com")) {
+			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) {
@@ -330,7 +318,6 @@
 		*reply = auth;
 		return JABBER_SASL_STATE_CONTINUE;
 	} else {
-		*error = g_strdup(_("SASL authentication failed"));
 		return JABBER_SASL_STATE_FAIL;
 	}
 }
@@ -404,17 +391,6 @@
 			continue;
 		}
 
-		/* Don't include Google Talk's X-GOOGLE-TOKEN mechanism
-		 * or Facebook Chat's X-FACEBOOK-PLATFORM mechansim,
-		 * as we will not support them and including them gives a false fall-back
-		 * to other mechs offerred, leading to incorrect error handling.
-		 */
-		if (g_str_equal(mech_name, "X-GOOGLE-TOKEN")
-				|| g_str_equal(mech_name, "X-FACEBOOK-PLATFORM") ) {
-			g_free(mech_name);
-			continue;
-		}
-
 		g_string_append(js->sasl_mechs, mech_name);
 		g_string_append_c(js->sasl_mechs, ' ');
 		g_free(mech_name);
@@ -542,6 +518,25 @@
 			sasl_dispose(&js->sasl);
 
 			return jabber_auth_start_cyrus(js, reply, error);
+
+		} else if ((js->auth_fail_count == 1) && 
+				   (js->current_mech && g_str_equal(js->current_mech, "GSSAPI"))) {
+			/* If we tried GSSAPI first, it failed, and it was the only method we had to try, try jabber:iq:auth
+			 * for compatibility with iChat 10.5 Server.
+			 *
+			 * iChat Server 10.5  offers SASL GSSAPI by default, which is often
+			 * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails.
+			 *
+			 * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However,
+			 * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms.
+			 * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers
+			 * which would connect without issue otherwise. -evands
+			 */
+			sasl_dispose(&js->sasl);
+			js->sasl = NULL;
+			js->auth_mech = NULL;
+			jabber_auth_start_old(js);
+			return JABBER_SASL_STATE_CONTINUE;
 		}
 	}
 
--- a/libpurple/protocols/jabber/auth_digest_md5.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/auth_digest_md5.c	Wed May 05 15:42:34 2010 +0900
@@ -188,16 +188,17 @@
 
 	if (g_hash_table_lookup(parts, "rspauth")) {
 		char *rspauth = g_hash_table_lookup(parts, "rspauth");
+		char *expected_rspauth = js->auth_mech_data;
 
-		if (rspauth && purple_strequal(rspauth, js->expected_rspauth)) {
+		if (rspauth && purple_strequal(rspauth, expected_rspauth)) {
 			reply = xmlnode_new("response");
 			xmlnode_set_namespace(reply, NS_XMPP_SASL);
 		} else {
 			*msg = g_strdup(_("Invalid challenge from server"));
 			state = JABBER_SASL_STATE_FAIL;
 		}
-		g_free(js->expected_rspauth);
-		js->expected_rspauth = NULL;
+		g_free(js->auth_mech_data);
+		js->auth_mech_data = NULL;
 	} else {
 		/* assemble a response, and send it */
 		/* see RFC 2831 */
@@ -235,7 +236,7 @@
 			g_free(a2);
 
 			a2 = g_strdup_printf(":xmpp/%s", realm);
-			js->expected_rspauth = generate_response_value(js->user,
+			js->auth_mech_data = generate_response_value(js->user,
 					purple_connection_get_password(js->gc), nonce, cnonce, a2, realm);
 			g_free(a2);
 
@@ -276,6 +277,13 @@
 	return state;
 }
 
+static void
+digest_md5_dispose(JabberStream *js)
+{
+	g_free(js->auth_mech_data);
+	js->auth_mech_data = NULL;
+}
+
 static JabberSaslMech digest_md5_mech = {
 	10, /* priority */
 	"DIGEST-MD5", /* name */
@@ -283,7 +291,7 @@
 	digest_md5_handle_challenge,
 	NULL, /* handle_success */
 	NULL, /* handle_failure */
-	NULL  /* handle_dispose */
+	digest_md5_dispose,
 };
 
 JabberSaslMech *jabber_auth_get_digest_md5_mech(void)
--- a/libpurple/protocols/jabber/auth_plain.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/auth_plain.c	Wed May 05 15:42:34 2010 +0900
@@ -40,13 +40,16 @@
 	auth = xmlnode_new("auth");
 	xmlnode_set_namespace(auth, NS_XMPP_SASL);
 
-	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 (g_str_equal(js->user->domain, "gmail.com") ||
+			g_str_equal(js->user->domain, "googlemail.com")) {
+		xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
+		xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
+	}
 
 	response = g_string_new("");
-	response = g_string_append_len(response, "\0", 1);
+	response = g_string_append_c(response, '\0');
 	response = g_string_append(response, js->user->node);
-	response = g_string_append_len(response, "\0", 1);
+	response = g_string_append_c(response, '\0');
 	response = g_string_append(response,
 			purple_connection_get_password(js->gc));
 
--- a/libpurple/protocols/jabber/auth_scram.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/auth_scram.c	Wed May 05 15:42:34 2010 +0900
@@ -47,6 +47,32 @@
 	g_return_val_if_reached(NULL);
 }
 
+static const struct {
+	const char *error;
+	const char *meaning;
+} server_errors[] = {
+	{ "invalid-encoding",
+		N_("Invalid Encoding")},
+	{ "extensions-not-supported",
+		N_("Unsupported Extension") },
+	{ "channel-bindings-dont-match",
+		N_("Unexpected response from the server.  This may indicate a possible MITM attack") },
+	{ "server-does-support-channel-binding",
+		N_("The server does support channel binding, but did not appear to advertise it.  This indicates a likely MITM attack") },
+	{ "channel-binding-not-supported",
+		N_("Server does not support channel binding") },
+	{ "unsupported-channel-binding-type",
+		N_("Unsupported channel binding method") },
+	{ "unknown-user",
+		N_("User not found") },
+	{ "invalid-username-encoding",
+		N_("Invalid Username Encoding") },
+	{ "no-resources",
+		N_("Resource Constraint") },
+	{ "other-error",
+		N_("Unknown Error") }
+};
+
 guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str,
                         GString *salt, guint iterations)
 {
--- a/libpurple/protocols/jabber/data.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/data.c	Wed May 05 15:42:34 2010 +0900
@@ -36,7 +36,7 @@
 
 JabberData *
 jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type,
-	JabberStream *js)
+	gboolean ephemeral, JabberStream *js)
 {
 	JabberData *data = g_new0(JabberData, 1);
 	gchar *checksum = jabber_calculate_data_hash(rawdata, size, "sha1");
@@ -48,6 +48,7 @@
 	data->cid = g_strdup(cid);
 	data->type = g_strdup(type);
 	data->size = size;
+	data->ephemeral = ephemeral;
 
 	data->data = g_memdup(rawdata, size);
 
@@ -110,6 +111,12 @@
 	return data;
 }
 
+void
+jabber_data_destroy(JabberData *data)
+{
+	jabber_data_delete(data);
+}
+
 const char *
 jabber_data_get_cid(const JabberData *data)
 {
@@ -289,14 +296,14 @@
 const JabberData *
 jabber_data_find_local_by_alt(const gchar *alt)
 {
-	purple_debug_info("jabber", "looking up local smiley with alt = %s\n", alt);
+	purple_debug_info("jabber", "looking up local data object with alt = %s\n", alt);
 	return g_hash_table_lookup(local_data_by_alt, alt);
 }
 
 const JabberData *
 jabber_data_find_local_by_cid(const gchar *cid)
 {
-	purple_debug_info("jabber", "lookup local smiley with cid = %s\n", cid);
+	purple_debug_info("jabber", "lookup local data object with cid = %s\n", cid);
 	return g_hash_table_lookup(local_data_by_cid, cid);
 }
 
@@ -305,7 +312,7 @@
     const gchar *cid)
 {
 	const JabberData *data = g_hash_table_lookup(remote_data_by_cid, cid);
-	purple_debug_info("jabber", "lookup remote smiley with cid = %s\n", cid);
+	purple_debug_info("jabber", "lookup remote data object with cid = %s\n", cid);
 
 	if (data == NULL) {
 		gchar *jid_cid =
@@ -323,9 +330,10 @@
 void
 jabber_data_associate_local(JabberData *data, const gchar *alt)
 {
-	purple_debug_info("jabber", "associating local smiley\n alt = %s, cid = %s\n",
-		alt, jabber_data_get_cid(data));
-	g_hash_table_insert(local_data_by_alt, g_strdup(alt), data);
+	purple_debug_info("jabber", "associating local data object\n alt = %s, cid = %s\n",
+		alt , jabber_data_get_cid(data));
+	if (alt)
+		g_hash_table_insert(local_data_by_alt, g_strdup(alt), data);
 	g_hash_table_insert(local_data_by_cid, g_strdup(jabber_data_get_cid(data)),
 		data);
 }
@@ -371,6 +379,11 @@
 		xmlnode_set_attrib(result->node, "id", id);
 		xmlnode_insert_child(result->node,
 							 jabber_data_get_xml_definition(data));
+		/* if the data object is temporary, destroy it and remove the references
+		 to it */
+		if (data->ephemeral) {
+			g_hash_table_remove(local_data_by_cid, cid);
+		}
 	}
 	jabber_iq_send(result);
 }
--- a/libpurple/protocols/jabber/data.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/data.h	Wed May 05 15:42:34 2010 +0900
@@ -34,6 +34,7 @@
 	char *type;
 	gsize size;
 	gpointer data;
+	gboolean ephemeral;
 } JabberData;
 
 typedef void (JabberDataRequestCallback)(JabberData *data, gchar *alt,
@@ -42,12 +43,16 @@
 
 /* creates a JabberData instance from raw data */
 JabberData *jabber_data_create_from_data(gconstpointer data, gsize size,
-										 const char *type, JabberStream *js);
+	const char *type, gboolean ephemeral, JabberStream *js);
 
 /* create a JabberData instance from an XML "data" element (as defined by
   XEP 0231 */
 JabberData *jabber_data_create_from_xml(xmlnode *tag);
 
+/* destroy a JabberData instance, NOT to be used on data that has been
+	associated, since they get "owned" */
+void jabber_data_destroy(JabberData *data);
+
 const char *jabber_data_get_cid(const JabberData *data);
 const char *jabber_data_get_type(const JabberData *data);
 
--- a/libpurple/protocols/jabber/jabber.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/jabber.c	Wed May 05 15:42:34 2010 +0900
@@ -210,6 +210,35 @@
 	return purple_strreplace(input, "__HOSTNAME__", hostname);
 }
 
+static gboolean
+jabber_process_starttls(JabberStream *js, xmlnode *packet)
+{
+	PurpleAccount *account;
+	xmlnode *starttls;
+
+	account = purple_connection_get_account(js->gc);
+
+	if((starttls = xmlnode_get_child(packet, "starttls"))) {
+		if(purple_ssl_is_supported()) {
+			jabber_send_raw(js,
+					"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1);
+			return TRUE;
+		} else if(xmlnode_get_child(starttls, "required")) {
+			purple_connection_error_reason(js->gc,
+				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+				_("Server requires TLS/SSL, but no TLS/SSL support was found."));
+			return TRUE;
+		} else if(purple_account_get_bool(account, "require_tls", JABBER_DEFAULT_REQUIRE_TLS)) {
+			purple_connection_error_reason(js->gc,
+				 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+				_("You require encryption, but no TLS/SSL support was found."));
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
 void jabber_stream_features_parse(JabberStream *js, xmlnode *packet)
 {
 	if(xmlnode_get_child(packet, "starttls")) {
@@ -364,8 +393,7 @@
 	int ret;
 	gboolean success = TRUE;
 
-	if (len == -1)
-		len = strlen(data);
+	g_return_val_if_fail(len > 0, FALSE);
 
 	if (js->state == JABBER_STREAM_CONNECTED)
 		jabber_stream_restart_inactivity_timer(js);
@@ -409,6 +437,12 @@
 
 void jabber_send_raw(JabberStream *js, const char *data, int len)
 {
+	PurpleConnection *gc;
+	PurpleAccount *account;
+
+	gc = js->gc;
+	account = purple_connection_get_account(gc);
+
 	/* because printing a tab to debug every minute gets old */
 	if(strcmp(data, "\t")) {
 		const char *username;
@@ -436,9 +470,9 @@
 			*data_start = '\0';
 		}
 
-		username = purple_connection_get_display_name(js->gc);
+		username = purple_connection_get_display_name(gc);
 		if (!username)
-			username = purple_account_get_username(purple_connection_get_account(js->gc));
+			username = purple_account_get_username(account);
 
 		purple_debug_misc("jabber", "Sending%s (%s): %s%s%s\n",
 				jabber_stream_is_ssl(js) ? " (ssl)" : "", username,
@@ -449,10 +483,13 @@
 		g_free(text);
 	}
 
-	purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-sending-text", js->gc, &data);
+	purple_signal_emit(purple_connection_get_prpl(gc), "jabber-sending-text", gc, &data);
 	if (data == NULL)
 		return;
 
+	if (len == -1)
+		len = strlen(data);
+
 	/* If we've got a security layer, we need to encode the data,
 	 * splitting it on the maximum buffer length negotiated */
 #ifdef HAVE_CYRUS_SASL
@@ -460,21 +497,36 @@
 		int pos = 0;
 
 		if (!js->gsc && js->fd<0)
-			return;
-
-		if (len == -1)
-			len = strlen(data);
+			g_return_if_reached();
 
 		while (pos < len) {
 			int towrite;
 			const char *out;
 			unsigned olen;
+			int rc;
 
 			towrite = MIN((len - pos), js->sasl_maxbuf);
 
-			sasl_encode(js->sasl, &data[pos], towrite, &out, &olen);
+			rc = sasl_encode(js->sasl, &data[pos], towrite,
+			                 &out, &olen);
+			if (rc != SASL_OK) {
+				gchar *error =
+					g_strdup_printf(_("SASL error: %s"),
+						sasl_errdetail(js->sasl));
+				purple_debug_error("jabber",
+					"sasl_encode error %d: %s\n", rc,
+					sasl_errdetail(js->sasl));
+				purple_connection_error_reason(gc,
+					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+					error);
+				g_free(error);
+				return;
+			}
 			pos += towrite;
 
+			/* do_jabber_send_raw returns FALSE when it throws a
+			 * connection error.
+			 */
 			if (!do_jabber_send_raw(js, out, olen))
 				break;
 		}
@@ -482,9 +534,6 @@
 	}
 #endif
 
-	if (len == -1)
-		len = strlen(data);
-
 	if (js->bosh)
 		jabber_bosh_connection_send_raw(js->bosh, data);
 	else
@@ -493,7 +542,7 @@
 
 int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len)
 {
-	JabberStream *js = (JabberStream*)gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	jabber_send_raw(js, buf, len);
 	return len;
 }
@@ -599,7 +648,7 @@
 jabber_recv_cb(gpointer data, gint source, PurpleInputCondition condition)
 {
 	PurpleConnection *gc = data;
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 	int len;
 	static char buf[4096];
 
@@ -609,14 +658,26 @@
 	if((len = read(js->fd, buf, sizeof(buf) - 1)) > 0) {
 		gc->last_received = time(NULL);
 #ifdef HAVE_CYRUS_SASL
-		if (js->sasl_maxbuf>0) {
+		if (js->sasl_maxbuf > 0) {
 			const char *out;
 			unsigned int olen;
-			sasl_decode(js->sasl, buf, len, &out, &olen);
-			if (olen>0) {
+			int rc;
+
+			rc = sasl_decode(js->sasl, buf, len, &out, &olen);
+			if (rc != SASL_OK) {
+				gchar *error =
+					g_strdup_printf(_("SASL error: %s"),
+						sasl_errdetail(js->sasl));
+				purple_debug_error("jabber",
+					"sasl_decode_error %d: %s\n", rc,
+					sasl_errdetail(js->sasl));
+				purple_connection_error_reason(gc,
+					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+					error);
+			} else if (olen > 0) {
 				purple_debug_info("jabber", "RecvSASL (%u): %s\n", olen, out);
-				jabber_parser_process(js,out,olen);
-				if(js->reinit)
+				jabber_parser_process(js, out, olen);
+				if (js->reinit)
 					jabber_stream_init(js);
 			}
 			return;
@@ -1586,7 +1647,6 @@
 	g_free(js->old_source);
 	g_free(js->old_uri);
 	g_free(js->old_track);
-	g_free(js->expected_rspauth);
 
 	if (js->vcard_timer != 0)
 		purple_timeout_remove(js->vcard_timer);
--- a/libpurple/protocols/jabber/jabber.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/jabber.h	Wed May 05 15:42:34 2010 +0900
@@ -112,7 +112,7 @@
 
 	JabberSaslMech *auth_mech;
 	gpointer auth_mech_data;
-	
+
 	/**
 	 * The header from the opening <stream/> tag.  This being NULL is treated
 	 * as a special condition in the parsing code (signifying the next
@@ -122,9 +122,6 @@
 	char *stream_id;
 	JabberStreamState state;
 
-	/* SASL authentication */
-	char *expected_rspauth;
-
 	GHashTable *buddies;
 
 	/*
--- a/libpurple/protocols/jabber/libxmpp.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/libxmpp.c	Wed May 05 15:42:34 2010 +0900
@@ -127,7 +127,9 @@
 	NULL, /* get_account_text_table */
 	jabber_initiate_media,          /* initiate_media */
 	jabber_get_media_caps,                  /* get_media_caps */
-	jabber_get_moods  							/* get_moods */
+	jabber_get_moods,  							/* get_moods */
+	NULL, /* set_public_alias */
+	NULL  /* get_public_alias */
 };
 
 static gboolean load_plugin(PurplePlugin *plugin)
--- a/libpurple/protocols/jabber/message.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/message.c	Wed May 05 15:42:34 2010 +0900
@@ -969,7 +969,7 @@
 						JabberData *new_data =
 							jabber_data_create_from_data(purple_imgstore_get_data(image),
 								purple_imgstore_get_size(image),
-								jabber_message_get_mimetype_from_ext(ext), js);
+								jabber_message_get_mimetype_from_ext(ext), FALSE, js);
 						purple_debug_info("jabber",
 							"cache local smiley alt = %s, cid = %s\n",
 							shortcut, jabber_data_get_cid(new_data));
--- a/libpurple/protocols/jabber/namespaces.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/namespaces.h	Wed May 05 15:42:34 2010 +0900
@@ -89,6 +89,9 @@
 /* XEP-0237 Roster Versioning */
 #define NS_ROSTER_VERSIONING "urn:xmpp:features:rosterver"
 
+/* XEP-0264 File Transfer Thumbnails (Thumbs) */
+#define NS_THUMBS "urn:xmpp:thumbs:0"
+
 /* Google extensions */
 #define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
 #define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
--- a/libpurple/protocols/jabber/presence.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/presence.c	Wed May 05 15:42:34 2010 +0900
@@ -924,8 +924,9 @@
 		goto out;
 	}
 
-	presence.chat = jabber_chat_find(js, presence.jid_from->node,
-	                                 presence.jid_from->domain);
+	if (presence.jid_from->node)
+		presence.chat = jabber_chat_find(js, presence.jid_from->node,
+		                                 presence.jid_from->domain);
 	if(presence.jb->error_msg) {
 		g_free(presence.jb->error_msg);
 		presence.jb->error_msg = NULL;
--- a/libpurple/protocols/jabber/si.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/jabber/si.c	Wed May 05 15:42:34 2010 +0900
@@ -32,6 +32,7 @@
 #include "notify.h"
 
 #include "buddy.h"
+#include "data.h"
 #include "disco.h"
 #include "jabber.h"
 #include "ibb.h"
@@ -39,6 +40,7 @@
 #include "si.h"
 
 #define STREAMHOST_CONNECT_TIMEOUT 15
+#define ENABLE_FT_THUMBNAILS 0
 
 #include "util.h"
 
@@ -1248,18 +1250,14 @@
 	JabberIq *iq;
 	xmlnode *si, *file, *feature, *x, *field, *option, *value;
 	char buf[32];
-	gchar *f1 = NULL, *f2 = NULL;
-	gsize dummy;
+#if ENABLE_FT_THUMBNAILS
+	gconstpointer thumb;
+	gsize thumb_size;
 
-	/* yaz */
-	f1 = g_filename_display_basename(xfer->local_filename);
-	f2 = botch_utf(f1, strlen(f1), &dummy);
-	if(f2){
-		purple_xfer_set_filename(xfer, (char *)f2);
-	}
-	g_free(f1); f1 = NULL;
-	g_free(f2); f2 = NULL;
-
+	purple_xfer_prepare_thumbnail(xfer, "jpeg,png");
+#endif
+	xfer->filename = g_path_get_basename(xfer->local_filename);
+	
 	iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
 	xmlnode_set_attrib(iq->node, "to", xfer->who);
 	si = xmlnode_new_child(iq->node, "si");
@@ -1277,6 +1275,23 @@
 	xmlnode_set_attrib(file, "size", buf);
 	/* maybe later we'll do hash and date attribs */
 
+#if ENABLE_FT_THUMBNAILS
+	/* add thumbnail, if appropriate */
+	if ((thumb = purple_xfer_get_thumbnail(xfer, &thumb_size))) {
+		const gchar *mimetype = purple_xfer_get_thumbnail_mimetype(xfer);
+		JabberData *thumbnail_data =
+			jabber_data_create_from_data(thumb, thumb_size,
+				mimetype, TRUE, jsx->js);
+		xmlnode *thumbnail = xmlnode_new_child(file, "thumbnail");
+		xmlnode_set_namespace(thumbnail, NS_THUMBS);
+		xmlnode_set_attrib(thumbnail, "cid", 
+			jabber_data_get_cid(thumbnail_data));
+		xmlnode_set_attrib(thumbnail, "mime-type", mimetype);
+		/* cache data */
+		jabber_data_associate_local(thumbnail_data, NULL);
+	}
+#endif
+						  
 	feature = xmlnode_new_child(si, "feature");
 	xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg");
 	x = xmlnode_new_child(feature, "x");
@@ -1655,12 +1670,29 @@
 		purple_xfer_request(xfer);
 }
 
+#if ENABLE_FT_THUMBNAILS
+static void
+jabber_si_thumbnail_cb(JabberData *data, gchar *alt, gpointer userdata)
+{
+	PurpleXfer *xfer = (PurpleXfer *) userdata;
+
+	if (data) {
+		purple_xfer_set_thumbnail(xfer, jabber_data_get_data(data),
+			jabber_data_get_size(data), jabber_data_get_type(data));
+		/* data is ephemeral, get rid of now (the xfer re-owned the thumbnail */
+		jabber_data_destroy(data);
+	}
+
+	purple_xfer_request(xfer);
+}
+#endif
+
 void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type,
                      const char *id, xmlnode *si)
 {
 	JabberSIXfer *jsx;
 	PurpleXfer *xfer;
-	xmlnode *file, *feature, *x, *field, *option, *value;
+	xmlnode *file, *feature, *x, *field, *option, *value, *thumbnail;
 	const char *stream_id, *filename, *filesize_c, *profile;
 	size_t filesize = 0;
 
@@ -1742,10 +1774,27 @@
 	purple_xfer_set_request_denied_fnc(xfer, jabber_si_xfer_request_denied);
 	purple_xfer_set_cancel_recv_fnc(xfer, jabber_si_xfer_cancel_recv);
 	purple_xfer_set_end_fnc(xfer, jabber_si_xfer_end);
-
+				   
 	js->file_transfers = g_list_append(js->file_transfers, xfer);
 
+#if ENABLE_FT_THUMBNAILS
+	/* if there is a thumbnail, we should request it... */
+	if ((thumbnail = xmlnode_get_child_with_namespace(file, "thumbnail",
+		NS_THUMBS))) {
+		const char *cid = xmlnode_get_attrib(thumbnail, "cid");
+		if (cid) {
+			jabber_data_request(js, cid, purple_xfer_get_remote_user(xfer),
+			    NULL, TRUE, jabber_si_thumbnail_cb, xfer);
+		} else {
+			purple_xfer_request(xfer);
+		}
+	} else {
+		purple_xfer_request(xfer);
+	}
+#else
+	thumbnail = NULL; /* Silence warning */
 	purple_xfer_request(xfer);
+#endif
 }
 
 void
--- a/libpurple/protocols/msn/msn.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/msn/msn.c	Wed May 05 15:42:34 2010 +0900
@@ -2774,7 +2774,9 @@
 	msn_get_account_text_table,             /* get_account_text_table */
 	NULL,                                   /* initiate_media */
 	NULL,                                   /* get_media_caps */
-	NULL                                    /* get_moods */
+	NULL,                                   /* get_moods */
+	NULL,                                   /* set_public_alias */
+	NULL                                    /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/msn/slp.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/msn/slp.c	Wed May 05 15:42:34 2010 +0900
@@ -422,6 +422,12 @@
 
 			xfer->data = slpcall;
 
+			if (header->type == 0 && bin_len >= sizeof(MsnFileContext)) {
+				purple_xfer_set_thumbnail(xfer, &header->preview,
+				                          bin_len - sizeof(MsnFileContext),
+				    					  "image/png");
+			}
+
 			purple_xfer_request(xfer);
 		}
 		g_free(header);
--- a/libpurple/protocols/msn/slplink.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/msn/slplink.c	Wed May 05 15:42:34 2010 +0900
@@ -692,15 +692,19 @@
 gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
 {
 	gsize size = 0;
-	MsnFileContext header;
+	MsnFileContext *header;
 	gchar *u8 = NULL;
 	gchar *ret;
 	gunichar2 *uni = NULL;
 	glong currentChar = 0;
 	glong len = 0;
+	const char *preview;
+	gsize preview_len;
 
 	size = purple_xfer_get_size(xfer);
 
+	purple_xfer_prepare_thumbnail(xfer, "png");
+
 	if (!file_name) {
 		gchar *basename = g_path_get_basename(file_path);
 		u8 = purple_utf8_try_convert(basename);
@@ -716,23 +720,33 @@
 		u8 = NULL;
 	}
 
-	header.length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1);
-	header.version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */
-	header.file_size = GUINT64_TO_LE(size);
-	header.type = GUINT32_TO_LE(1);    /* No file preview */
+	preview = purple_xfer_get_thumbnail(xfer, &preview_len);
+	header = g_malloc(sizeof(MsnFileContext) + preview_len);
+
+	header->length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1);
+	header->version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */
+	header->file_size = GUINT64_TO_LE(size);
+	if (preview)
+		header->type = GUINT32_TO_LE(0);
+	else
+		header->type = GUINT32_TO_LE(1);
 
 	len = MIN(len, MAX_FILE_NAME_LEN);
 	for (currentChar = 0; currentChar < len; currentChar++) {
-		header.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
+		header->file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
 	}
-	memset(&header.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
+	memset(&header->file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
 
-	memset(&header.unknown1, 0, sizeof(header.unknown1));
-	header.unknown2 = GUINT32_TO_LE(0xffffffff);
-	header.preview[0] = '\0';
+	memset(&header->unknown1, 0, sizeof(header->unknown1));
+	header->unknown2 = GUINT32_TO_LE(0xffffffff);
+	if (preview) {
+		memcpy(&header->preview, preview, preview_len);
+	}
+	header->preview[preview_len] = '\0';
 
 	g_free(uni);
-	ret = purple_base64_encode((const guchar *)&header, sizeof(MsnFileContext));
+	ret = purple_base64_encode((const guchar *)header, sizeof(MsnFileContext) + preview_len);
+	g_free(header);
 	return ret;
 }
 
--- a/libpurple/protocols/mxit/mxit.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/mxit/mxit.c	Wed May 05 15:42:34 2010 +0900
@@ -635,7 +635,9 @@
 	mxit_get_text_table,	/* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* get_media_caps */
-	NULL					/* get_moods */
+	NULL,					/* get_moods */
+	NULL,					/* set_public_alias */
+	NULL					/* get_public_alias */
 };
 
 
--- a/libpurple/protocols/myspace/myspace.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/myspace/myspace.c	Wed May 05 15:42:34 2010 +0900
@@ -3094,7 +3094,9 @@
 	msim_get_account_text_table,              /* get_account_text_table */
 	NULL,                   /* initiate_media */
 	NULL,                   /* get_media_caps */
-	NULL                    /* get_moods */
+	NULL,                   /* get_moods */
+	NULL,                   /* set_public_alias */
+	NULL                    /* get_public_alias */
 };
 
 /**
--- a/libpurple/protocols/novell/novell.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/novell/novell.c	Wed May 05 15:42:34 2010 +0900
@@ -3530,7 +3530,9 @@
 	NULL,						/* get_account_text_table */
 	NULL,						/* initiate_media */
 	NULL,						/* get_media_caps */
-	NULL						/* get_moods */
+	NULL,						/* get_moods */
+	NULL,						/* set_public_alias */
+	NULL						/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/protocols/null/nullprpl.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/null/nullprpl.c	Wed May 05 15:42:34 2010 +0900
@@ -1120,6 +1120,8 @@
   NULL,                                /* get_account_text_table */
   NULL,                                /* initiate_media */
   NULL,                                /* get_media_caps */
+  NULL,                                /* set_public_alias */
+  NULL,                                /* get_public_alias */
   NULL                                 /* get_moods */
 };
 
--- a/libpurple/protocols/oscar/libaim.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/oscar/libaim.c	Wed May 05 15:42:34 2010 +0900
@@ -97,7 +97,9 @@
 	NULL,					/* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* get_media_caps */
-	NULL					/* get_moods */
+	NULL,					/* get_moods */
+	NULL,					/* set_public_alias */
+	NULL					/* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/oscar/libicq.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/oscar/libicq.c	Wed May 05 15:42:34 2010 +0900
@@ -109,6 +109,8 @@
 	NULL,					/* initiate_media */
 	NULL,					/* can_do_media */
 	oscar_get_purple_moods, /* get_moods */
+	NULL,					/* set_public_alias */
+	NULL					/* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/oscar/oscar.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/oscar/oscar.c	Wed May 05 15:42:34 2010 +0900
@@ -3567,7 +3567,7 @@
 	PurpleConnection *gc = od->gc;
 	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleNotifyUserInfo *user_info;
-	gchar *tmp = NULL, *info_utf8 = NULL;
+	gchar *tmp = NULL, *info_utf8 = NULL, *base_profile_url = NULL;
 	va_list ap;
 	aim_userinfo_t *userinfo;
 
@@ -3620,8 +3620,9 @@
 	}
 
 	purple_notify_user_info_add_section_break(user_info);
-	tmp = g_strdup_printf("<a href=\"http://profiles.aim.com/%s\">%s</a>",
-			purple_normalize(account, userinfo->bn), _("View web profile"));
+	base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com";
+	tmp = g_strdup_printf("<a href=\"%s/%s\">%s</a>",
+			base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile"));
 	purple_notify_user_info_add_pair(user_info, NULL, tmp);
 	g_free(tmp);
 
--- a/libpurple/protocols/qq/qq.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/qq/qq.c	Wed May 05 15:42:34 2010 +0900
@@ -1041,7 +1041,9 @@
 	NULL,							/* get_account_text_table */
 	NULL,							/* initiate_media */
 	NULL,							/* get_media_caps */
-	NULL							/* get_moods */
+	NULL,							/* get_moods */
+	NULL,							/* set_public_alias */
+	NULL							/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/protocols/silc/silc.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/silc/silc.c	Wed May 05 15:42:34 2010 +0900
@@ -2117,7 +2117,9 @@
 	NULL,				        /* get_account_text_table */
 	NULL,				        /* initiate_media */
 	NULL,				        /* get_media_caps */
-	NULL				        /* get_moods */
+	NULL,				        /* get_moods */
+	NULL,				        /* set_public_alias */
+	NULL				        /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/silc10/silc.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/silc10/silc.c	Wed May 05 15:42:34 2010 +0900
@@ -1842,7 +1842,10 @@
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	NULL,                       /* get_account_text_table */
 	NULL,                       /* initiate_media */
-	NULL                       /* can_do_media */
+	NULL,                       /* get_media_caps */
+	NULL,                       /* get_moods */
+	NULL,                       /* set_public_alias */
+	NULL                        /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/simple/simple.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/simple/simple.c	Wed May 05 15:42:34 2010 +0900
@@ -2110,7 +2110,9 @@
 	NULL,					/* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* get_media_caps */
-	NULL					/* get_moods */
+	NULL,					/* get_moods */
+	NULL,					/* set_public_alias */
+	NULL					/* get_public_alias */
 };
 
 
--- a/libpurple/protocols/yahoo/libyahoo.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/yahoo/libyahoo.c	Wed May 05 15:42:34 2010 +0900
@@ -266,7 +266,9 @@
 	yahoo_get_account_text_table,    /* get_account_text_table */
 	NULL, /* initiate_media */
 	NULL,  /* get_media_caps */
-	NULL   /* get_moods */
+	NULL,  /* get_moods */
+	NULL,  /* set_public_alias */
+	NULL   /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/yahoo/libyahoojp.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/yahoo/libyahoojp.c	Wed May 05 15:42:34 2010 +0900
@@ -162,7 +162,9 @@
 	yahoojp_get_account_text_table,    /* get_account_text_table */
 	NULL, /* initiate_media */
 	NULL, /* get_media_caps */
-	NULL  /* get_moods */
+	NULL, /* get_moods */
+	NULL, /* set_public_alias */
+	NULL  /* get_public_alias */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/zephyr/zephyr.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/protocols/zephyr/zephyr.c	Wed May 05 15:42:34 2010 +0900
@@ -2909,7 +2909,9 @@
 	NULL,					/* get_account_text_table */
 	NULL,					/* initate_media */
 	NULL,					/* get_media_caps */
-	NULL					/* get_moods */
+	NULL,					/* get_moods */
+	NULL,					/* set_public_alias */
+	NULL					/* get_public_alias */
 };
 
 static PurplePluginInfo info = {
--- a/libpurple/prpl.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/prpl.h	Wed May 05 15:42:34 2010 +0900
@@ -52,6 +52,13 @@
 typedef struct _PurpleBuddyIconSpec PurpleBuddyIconSpec;
 
 /**
+ * A description of a file transfer thumbnail specification.
+ * This tells the UI if and what image formats the prpl support for file
+ * transfer thumbnails.
+ */
+typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec;
+
+/**
  * This \#define exists just to make it easier to fill out the buddy icon
  * field in the prpl info struct for protocols that couldn't care less.
  */
@@ -573,8 +580,48 @@
 	/**
 	 * Returns an array of "PurpleMood"s, with the last one having
 	 * "mood" set to @c NULL.
+	 * @since 2.7.0
 	 */
 	PurpleMood *(*get_moods)(PurpleAccount *account);
+
+	/**
+	 * Set the user's "friendly name" (or alias or nickname or
+	 * whatever term you want to call it) on the server.  The
+	 * protocol plugin should call success_cb or failure_cb
+	 * *asynchronously* (if it knows immediately that the set will fail,
+	 * call one of the callbacks from an idle/0-second timeout) depending
+	 * on if the nickname is set successfully.
+	 *
+	 * @param gc    The connection for which to set an alias
+	 * @param alias The new server-side alias/nickname for this account,
+	 *              or NULL to unset the alias/nickname (or return it to
+	 *              a protocol-specific "default").
+	 * @param success_cb Callback to be called if the public alias is set
+	 * @param failure_cb Callback to be called if setting the public alias
+	 *                   fails
+	 * @see purple_account_set_public_alias
+	 * @since 2.7.0
+	 */
+	void (*set_public_alias)(PurpleConnection *gc, const char *alias,
+	                         PurpleSetPublicAliasSuccessCallback success_cb,
+	                         PurpleSetPublicAliasFailureCallback failure_cb);
+	/**
+	 * Retrieve the user's "friendly name" as set on the server.
+	 * The protocol plugin should call success_cb or failure_cb
+	 * *asynchronously* (even if it knows immediately that the set will fail,
+	 * call one of the callbacks from an idle/0-second timeout) depending
+	 * on if the nickname is retrieved.
+	 *
+	 * @param gc    The connection for which to retireve the alias
+	 * @param success_cb Callback to be called with the retrieved alias
+	 * @param failure_cb Callback to be called if the prpl is unable to
+	 *                   retrieve the alias
+	 * @see purple_account_get_public_alias
+	 * @since 2.7.0
+	 */
+	void (*get_public_alias)(PurpleConnection *gc,
+	                         PurpleSetPublicAliasSuccessCallback success_cb,
+	                         PurpleSetPublicAliasFailureCallback failure_cb);
 };
 
 #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
--- a/libpurple/request.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/request.c	Wed May 05 15:42:34 2010 +0900
@@ -1317,6 +1317,29 @@
 }
 
 void *
+purple_request_action_with_icon(void *handle, const char *title, 
+					const char *primary,
+					const char *secondary, int default_action,
+					PurpleAccount *account, const char *who, 
+					PurpleConversation *conv, gconstpointer icon_data,
+					gsize icon_size, void *user_data, size_t action_count, ...)
+{
+	void *ui_handle;
+	va_list args;
+
+	g_return_val_if_fail(action_count > 0, NULL);
+
+	va_start(args, action_count);
+	ui_handle = purple_request_action_with_icon_varg(handle, title, primary, 
+		secondary, default_action, account, who, conv, icon_data, icon_size,
+		user_data, action_count, args);
+	va_end(args);
+
+	return ui_handle;
+}
+
+
+void *
 purple_request_action_varg(void *handle, const char *title,
 						 const char *primary, const char *secondary,
 						 int default_action,
@@ -1348,6 +1371,41 @@
 }
 
 void *
+purple_request_action_with_icon_varg(void *handle, const char *title,
+						 const char *primary, const char *secondary,
+						 int default_action,
+						 PurpleAccount *account, const char *who, 
+						 PurpleConversation *conv, gconstpointer icon_data,
+						 gsize icon_size,
+						 void *user_data, size_t action_count, va_list actions)
+{
+	PurpleRequestUiOps *ops;
+
+	g_return_val_if_fail(action_count > 0, NULL);
+
+	ops = purple_request_get_ui_ops();
+
+	if (ops != NULL && ops->request_action_with_icon != NULL) {
+		PurpleRequestInfo *info;
+
+		info            = g_new0(PurpleRequestInfo, 1);
+		info->type      = PURPLE_REQUEST_ACTION;
+		info->handle    = handle;
+		info->ui_handle = ops->request_action_with_icon(title, primary, secondary,
+											  default_action, account, who, conv,
+											  icon_data, icon_size,
+											  user_data, action_count, actions);
+
+		handles = g_list_append(handles, info);
+
+		return info->ui_handle;
+	}
+
+	return NULL;
+}
+
+
+void *
 purple_request_fields(void *handle, const char *title, const char *primary,
 					const char *secondary, PurpleRequestFields *fields,
 					const char *ok_text, GCallback ok_cb,
--- a/libpurple/request.h	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/request.h	Wed May 05 15:42:34 2010 +0900
@@ -237,10 +237,18 @@
 	                        PurpleAccount *account, const char *who,
 	                        PurpleConversation *conv, void *user_data);
 
+	/** @see purple_request_action_with_icon_varg(). */
+	void *(*request_action_with_icon)(const char *title, const char *primary,
+	                        const char *secondary, int default_action,
+	                        PurpleAccount *account, const char *who,
+	                        PurpleConversation *conv, 
+	                        gconstpointer icon_data, gsize icon_size,
+	                        void *user_data,
+	                        size_t action_count, va_list actions);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
 } PurpleRequestUiOps;
 
 typedef void (*PurpleRequestInputCb)(void *, const char *);
@@ -1393,6 +1401,29 @@
 	void *user_data, size_t action_count, va_list actions);
 
 /**
+ * Version of purple_request_action() supplying an image for the UI to 
+ * optionally display as an icon in the dialog; see its documentation
+ * @since 2.7.0
+ */
+void *purple_request_action_with_icon(void *handle, const char *title, 
+	const char *primary, const char *secondary, int default_action, 
+	PurpleAccount *account, const char *who, PurpleConversation *conv, 
+	gconstpointer icon_data, gsize icon_size, void *user_data, 
+	size_t action_count, ...);
+
+/**
+ * <tt>va_list</tt> version of purple_request_action_with_icon(); 
+ * see its documentation.
+ * @since 2.7.0
+ */
+void *purple_request_action_with_icon_varg(void *handle, const char *title,
+	const char *primary, const char *secondary, int default_action,
+	PurpleAccount *account, const char *who, PurpleConversation *conv,
+	gconstpointer icon_data, gsize icon_size,
+	void *user_data, size_t action_count, va_list actions);
+
+
+/**
  * Displays groups of fields for the user to fill in.
  *
  * @param handle      The plugin or connection handle.  For some things this
@@ -1477,6 +1508,19 @@
 						_("_Accept"), (accept_cb), _("_Cancel"), (cancel_cb))
 
 /**
+ * A wrapper for purple_request_action_with_icon() that uses Accept and Cancel 
+ * buttons.
+ */
+#define purple_request_accept_cancel_with_icon(handle, title, primary, secondary, \
+								   default_action, account, who, conv, \
+								   icon_data, icon_size, \
+								   user_data, accept_cb, cancel_cb) \
+	purple_request_action_with_icon((handle), (title), (primary), (secondary), \
+						(default_action), account, who, conv, icon_data, icon_size, \
+						(user_data), 2, \
+						_("_Accept"), (accept_cb), _("_Cancel"), (cancel_cb))
+
+/**
  * Displays a file selector request dialog.  Returns the selected filename to
  * the callback.  Can be used for either opening a file or saving a file.
  *
--- a/libpurple/tests/test_util.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/tests/test_util.c	Wed May 05 15:42:34 2010 +0900
@@ -121,6 +121,37 @@
 }
 END_TEST
 
+START_TEST(test_utf8_strip_unprintables)
+{
+	fail_unless(NULL == purple_utf8_strip_unprintables(NULL));
+	/* invalid UTF-8 */
+#if 0
+	/* disabled because make check fails on an assertion */
+	fail_unless(NULL == purple_utf8_strip_unprintables("abc\x80\x7f"));
+#endif
+	/* \t, \n, \r, space */
+	assert_string_equal_free("ab \tcd\nef\r   ", purple_utf8_strip_unprintables("ab \tcd\nef\r   "));
+	/* ASCII control characters (stripped) */
+	assert_string_equal_free(" aaaa ", purple_utf8_strip_unprintables(
+				"\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10 aaaa "
+				"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"));
+	/* Basic ASCII */
+	assert_string_equal_free("Foobar", purple_utf8_strip_unprintables("Foobar"));
+	/* 0xE000 - 0xFFFD (UTF-8 encoded) */
+	/* U+F1F7 */
+	assert_string_equal_free("aaaa\xef\x87\xb7", purple_utf8_strip_unprintables("aaaa\xef\x87\xb7"));
+#if 0
+	/* disabled because make check fails on an assertion */
+	/* U+DB80 (Private Use High Surrogate, First) -- should be stripped */
+	assert_string_equal_free("aaaa", purple_utf8_strip_unprintables("aaaa\xed\xa0\x80"));
+	/* U+FFFE (should be stripped) */
+	assert_string_equal_free("aaaa", purple_utf8_strip_unprintables("aaaa\xef\xbf\xbe"));
+#endif
+	/* U+FEFF (should not be stripped) */
+	assert_string_equal_free("aaaa\xef\xbb\xbf", purple_utf8_strip_unprintables("aaaa\xef\xbb\xbf"));
+}
+END_TEST
+
 START_TEST(test_mime_decode_field)
 {
 	gchar *result = purple_mime_decode_field("=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=");
@@ -168,6 +199,10 @@
 	tcase_add_test(tc, test_markup_html_to_xhtml);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("Stripping Unparseables");
+	tcase_add_test(tc, test_utf8_strip_unprintables);
+	suite_add_tcase(s, tc);
+
 	tc = tcase_create("MIME");
 	tcase_add_test(tc, test_mime_decode_field);
 	suite_add_tcase(s, tc);
--- a/libpurple/util.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/libpurple/util.c	Wed May 05 15:42:34 2010 +0900
@@ -4636,12 +4636,22 @@
 	}
 
 	workstr = iter = g_new(gchar, strlen(str) + 1);
-	for ( ; *str; ++str) {
-		guchar c = *str;
-		if (c >= 0x20 || c == '\t' || c == '\n' || c == '\r') {
-			*iter = c;
-			++iter;
+	while (*str) {
+		gunichar ch = g_utf8_get_char(str);
+		gchar *next = g_utf8_next_char(str);
+		/*
+		 * Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
+		 *          [#x10000-#x10FFFF]
+		 */
+		if ((ch == '\t' || ch == '\n' || ch == '\r') ||
+				(ch >= 0x20 && ch <= 0xD7FF) ||
+				(ch >= 0xE000 && ch <= 0xFFFD) ||
+				(ch >= 0x10000 && ch <= 0x10FFFF)) {
+			memcpy(iter, str, next - str);
+			iter += (next - str);
 		}
+
+		str = next;
 	}
 
 	/* nul-terminate the new string */
--- a/pidgin/gtkft.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/pidgin/gtkft.c	Wed May 05 15:42:34 2010 +0900
@@ -40,6 +40,9 @@
 #define PIDGINXFER(xfer) \
 	(PidginXferUiData *)(xfer)->ui_data
 
+/* the maximum size of files we will try to make a thumbnail for */
+#define PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL 10 * 1024 * 1024
+
 struct _PidginXferDialog
 {
 	gboolean keep_open;
@@ -1157,6 +1160,67 @@
 		pidgin_xfer_dialog_cancel_xfer(xfer_dialog, xfer);
 }
 
+static void
+pidgin_xfer_add_thumbnail(PurpleXfer *xfer, const gchar *formats)
+{	
+	purple_debug_info("ft", "creating thumbnail for transfer\n");
+
+	if (purple_xfer_get_size(xfer) <= PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL) {
+		GdkPixbuf *thumbnail = 
+			gdk_pixbuf_new_from_file_at_size(
+				purple_xfer_get_local_filename(xfer), 128, 128, NULL);
+
+		if (thumbnail) {
+			gchar **formats_split = g_strsplit(formats, ",", 0);
+			gchar *buffer = NULL;
+			gsize size;
+			char *option_keys[2] = {NULL, NULL};
+			char *option_values[2] = {NULL, NULL};
+			int i;
+			gchar *format = NULL;
+			
+			for (i = 0; formats_split[i]; i++) {
+				if (purple_strequal(formats_split[i], "jpeg")) {
+					purple_debug_info("ft", "creating JPEG thumbnail\n");
+					option_keys[0] = "quality";
+					option_values[0] = "90";
+					format = "jpeg";
+					break;
+				} else if (purple_strequal(formats_split[i], "png")) {
+					purple_debug_info("ft", "creating PNG thumbnail\n");
+					option_keys[0] = "compression";
+					option_values[0] = "9";
+					format = "png";
+					break;
+				}
+			}
+
+			/* Try the first format given by the PRPL without options */
+			if (format == NULL) {
+				purple_debug_info("ft",
+				    "creating thumbnail of format %s as demanded by PRPL\n",
+				    formats_split[0]);
+				format = formats_split[0];
+			}
+
+			gdk_pixbuf_save_to_bufferv(thumbnail, &buffer, &size, format, 
+				option_keys, option_values, NULL);
+
+			if (buffer) {
+				gchar *mimetype = g_strdup_printf("image/%s", format);				
+				purple_debug_info("ft",
+				                  "created thumbnail of %" G_GSIZE_FORMAT " bytes\n",
+					size);
+				purple_xfer_set_thumbnail(xfer, buffer, size, mimetype);
+				g_free(buffer);
+				g_free(mimetype);
+			}
+			g_object_unref(thumbnail);
+			g_strfreev(formats_split);
+		}
+	}
+}
+
 static PurpleXferUiOps ops =
 {
 	pidgin_xfer_new_xfer,
@@ -1168,7 +1232,7 @@
 	NULL,
 	NULL,
 	NULL,
-	NULL
+	pidgin_xfer_add_thumbnail
 };
 
 /**************************************************************************
--- a/pidgin/gtkrequest.c	Wed Apr 28 19:22:17 2010 +0900
+++ b/pidgin/gtkrequest.c	Wed May 05 15:42:34 2010 +0900
@@ -26,6 +26,7 @@
 #include "internal.h"
 #include "pidgin.h"
 
+#include "debug.h"
 #include "prefs.h"
 #include "util.h"
 
@@ -592,9 +593,11 @@
 }
 
 static void *
-pidgin_request_action(const char *title, const char *primary,
+pidgin_request_action_with_icon(const char *title, const char *primary,
 						const char *secondary, int default_action,
-					    PurpleAccount *account, const char *who, PurpleConversation *conv,
+					    PurpleAccount *account, const char *who, 
+						PurpleConversation *conv, gconstpointer icon_data,
+						gsize icon_size,
 						void *user_data, size_t action_count, va_list actions)
 {
 	PidginRequestData *data;
@@ -602,7 +605,7 @@
 	GtkWidget *vbox;
 	GtkWidget *hbox;
 	GtkWidget *label;
-	GtkWidget *img;
+	GtkWidget *img = NULL;
 	void **buttons;
 	char *label_text;
 	char *primary_esc, *secondary_esc;
@@ -659,8 +662,42 @@
 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
 
 	/* Dialog icon. */
-	img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION,
+	if (icon_data) {
+		GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+		GdkPixbuf *pixbuf = NULL;
+		if (gdk_pixbuf_loader_write(loader, icon_data, icon_size, NULL)) {
+			pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+			if (pixbuf) {
+				/* scale the image if it is too large */
+				int width = gdk_pixbuf_get_width(pixbuf);
+				int height = gdk_pixbuf_get_height(pixbuf);
+				if (width > 128 || height > 128) {
+					int scaled_width = width > height ? 128 : (128 * width) / height;
+					int scaled_height = height > width ? 128 : (128 * height) / width;
+					GdkPixbuf *scaled =
+							gdk_pixbuf_scale_simple(pixbuf, scaled_width, scaled_height,
+							    GDK_INTERP_BILINEAR);
+
+					purple_debug_info("pidgin",
+					    "dialog icon was too large, scale it down\n");
+					if (scaled) {
+						g_object_unref(pixbuf);
+						pixbuf = scaled;
+					}
+				}
+				img = gtk_image_new_from_pixbuf(pixbuf);
+			}
+		} else {
+			purple_debug_info("pidgin", "failed to parse dialog icon\n");
+		}
+		gdk_pixbuf_loader_close(loader, NULL);
+		g_object_unref(loader);
+	}
+	
+	if (!img) {
+		img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION,
 				       gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
+	}
 	gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
 	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
 
@@ -712,6 +749,17 @@
 	return data;
 }
 
+static void *
+pidgin_request_action(const char *title, const char *primary,
+						const char *secondary, int default_action,
+					    PurpleAccount *account, const char *who, PurpleConversation *conv,
+						void *user_data, size_t action_count, va_list actions)
+{
+	return pidgin_request_action_with_icon(title, primary, secondary,
+		default_action, account, who, conv, NULL, 0, user_data, action_count,
+		actions);
+}
+
 static void
 req_entry_field_changed_cb(GtkWidget *entry, PurpleRequestField *field)
 {
@@ -1699,7 +1747,7 @@
 	pidgin_request_file,
 	pidgin_close_request,
 	pidgin_request_folder,
-	NULL,
+	pidgin_request_action_with_icon,
 	NULL,
 	NULL,
 	NULL
--- a/po/ca.po	Wed Apr 28 19:22:17 2010 +0900
+++ b/po/ca.po	Wed May 05 15:42:34 2010 +0900
@@ -33,8 +33,8 @@
 msgstr ""
 "Project-Id-Version: Pidgin\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-04-26 18:32+0200\n"
-"PO-Revision-Date: 2010-04-26 19:11+0200\n"
+"POT-Creation-Date: 2010-05-04 22:47+0200\n"
+"PO-Revision-Date: 2010-05-04 23:17+0200\n"
 "Last-Translator: Josep Puigdemont i Casamajó <josep.puigdemont@gmail.com>\n"
 "Language-Team: Catalan <tradgnome@softcatala.net>\n"
 "MIME-Version: 1.0\n"
@@ -1681,6 +1681,12 @@
 msgid "Set User Info"
 msgstr "Estableix les dades d'usuari"
 
+msgid "This protocol does not support setting a public alias."
+msgstr "Aquest protocol no permet establir un àlies pulic."
+
+msgid "This protocol does not support fetching the public alias."
+msgstr "Aquest protocol no permet aconseguir l'àlies públic."
+
 msgid "Unknown"
 msgstr "Desconegut"
 
@@ -3827,15 +3833,6 @@
 msgid "execute"
 msgstr "executa"
 
-msgid "Server requires TLS/SSL, but no TLS/SSL support was found."
-msgstr ""
-"El servidor requereix TLS/SSL per entrar, però no s'ha trobat cap "
-"implementació de TLS/SSL."
-
-msgid "You require encryption, but no TLS/SSL support was found."
-msgstr ""
-"Heu requerit que es xifri, però no s'ha trobat cap implementació de TLS/SSL."
-
 msgid "Server requires plaintext authentication over an unencrypted stream"
 msgstr "El servidor requereix autenticació de text sobre un flux no xifrat"
 
@@ -3873,6 +3870,43 @@
 msgid "SASL error: %s"
 msgstr "Error SASL: %s"
 
+msgid "Invalid Encoding"
+msgstr "La condició no és vàlida"
+
+msgid "Unsupported Extension"
+msgstr "Aquesta extensió no està implementada"
+
+# MitM: Man-in-the-middle... segons wiki: intermediari
+msgid ""
+"Unexpected response from the server.  This may indicate a possible MITM "
+"attack"
+msgstr ""
+"S'ha rebut una resposta inesperada del servidor. Això podria indicar un "
+"possible atac informàtic \"man-in-the-middle\""
+
+msgid ""
+"The server does support channel binding, but did not appear to advertise "
+"it.  This indicates a likely MITM attack"
+msgstr ""
+"Aques servidor permet vincular canals, tot i que no ho havia anunciat. Això "
+"podria ser indicatiu d'un atac informàtic \"man-in-the-middle\""
+
+msgid "Server does not support channel binding"
+msgstr "El servidor no permet vincular canals"
+
+msgid "Unsupported channel binding method"
+msgstr "Aquest mètode de vinculació de canals no està implementat"
+
+msgid "User not found"
+msgstr "No s'ha trobat l'usuari"
+
+msgid "Invalid Username Encoding"
+msgstr "La codificació del nom d'usuari no és vàlida"
+
+# Mirar com es traduïa 'Constraint variables'
+msgid "Resource Constraint"
+msgstr "Restriccions del recurs"
+
 # FIXME: canonicalize -> normalitzar (josep)
 msgid "Unable to canonicalize username"
 msgstr "No s'ha pogut normalitzar el nom d'usuari"
@@ -4178,6 +4212,15 @@
 msgid "Roles:"
 msgstr "Rols:"
 
+msgid "Server requires TLS/SSL, but no TLS/SSL support was found."
+msgstr ""
+"El servidor requereix TLS/SSL per entrar, però no s'ha trobat cap "
+"implementació de TLS/SSL."
+
+msgid "You require encryption, but no TLS/SSL support was found."
+msgstr ""
+"Heu requerit que es xifri, però no s'ha trobat cap implementació de TLS/SSL."
+
 msgid "Ping timed out"
 msgstr "S'ha esgitat el temps d'espera (ping)"
 
@@ -4322,10 +4365,10 @@
 msgstr "Permet les botzines"
 
 msgid "Mood Name"
-msgstr ""
+msgstr "Nom de l'estat d'ànim"
 
 msgid "Mood Comment"
-msgstr ""
+msgstr "Comentari sobre l'estat d'ànim"
 
 #. primitive
 #. ID
@@ -4504,10 +4547,6 @@
 msgid "Remote Connection Failed"
 msgstr "Ha fallat la connexió remota"
 
-# Mirar com es traduïa 'Constraint variables'
-msgid "Resource Constraint"
-msgstr "Restriccions del recurs"
-
 msgid "Restricted XML"
 msgstr "XML restringit"
 
@@ -4871,9 +4910,8 @@
 msgid "Anxious"
 msgstr "Ansiós"
 
-#, fuzzy
 msgid "Aroused"
-msgstr "S'enviarà"
+msgstr ""
 
 msgid "Ashamed"
 msgstr "Avergonyit"
@@ -4899,17 +4937,14 @@
 msgid "Confused"
 msgstr "Confós"
 
-#, fuzzy
 msgid "Contemplative"
-msgstr "Contacte"
-
-#, fuzzy
+msgstr "Contemplatiu"
+
 msgid "Contented"
-msgstr "Connectat"
-
-#, fuzzy
+msgstr "Acontentat"
+
 msgid "Cranky"
-msgstr "Empresa"
+msgstr ""
 
 msgid "Crazy"
 msgstr "Boig"
@@ -4920,9 +4955,8 @@
 msgid "Curious"
 msgstr "Curiós"
 
-#, fuzzy
 msgid "Dejected"
-msgstr "Rebutjat"
+msgstr "Enfonsat"
 
 msgid "Depressed"
 msgstr "Deprimit"
@@ -4931,11 +4965,10 @@
 msgstr "Decebut"
 
 msgid "Disgusted"
-msgstr ""
-
-#, fuzzy
+msgstr "Repugnat"
+
 msgid "Dismayed"
-msgstr "Inhabilitat"
+msgstr "Descoratjat"
 
 msgid "Distracted"
 msgstr "Distret"
@@ -4950,9 +4983,8 @@
 msgid "Excited"
 msgstr "Excitat"
 
-#, fuzzy
 msgid "Flirtatious"
-msgstr "Gloriós"
+msgstr "Amb ganes de flirtar"
 
 msgid "Frustrated"
 msgstr "Frustrat"
@@ -4960,9 +4992,8 @@
 msgid "Grateful"
 msgstr "Agraït"
 
-#, fuzzy
 msgid "Grieving"
-msgstr "S'està recuperant..."
+msgstr "De dol"
 
 #. 3
 msgid "Grumpy"
@@ -4997,9 +5028,8 @@
 msgid "Impressed"
 msgstr "Impressionat"
 
-#, fuzzy
 msgid "In awe"
-msgstr "Enamorat"
+msgstr ""
 
 msgid "In love"
 msgstr "Enamorat"
@@ -6660,9 +6690,6 @@
 msgid "Incorrect password"
 msgstr "La contrasenya no és correcta"
 
-msgid "User not found"
-msgstr "No s'ha trobat l'usuari"
-
 msgid "Account has been disabled"
 msgstr "S'ha inhabilitat el compte"
 
@@ -6963,7 +6990,7 @@
 msgstr "A l'oficina"
 
 msgid "Taking a bath"
-msgstr ""
+msgstr "Prenent un bany"
 
 msgid "Watching TV"
 msgstr "Mirant la tele"
@@ -7871,9 +7898,8 @@
 msgid "Edit Buddy Comment"
 msgstr "Edita el comentari sobre l'amic"
 
-#, fuzzy
 msgid "Get X-Status Msg"
-msgstr "Aconsegueix el missatge d'estat"
+msgstr "Aconsegueix el missatge d'estat X"
 
 msgid "End Direct IM Session"
 msgstr "Finalitzar la sessió de MI directa"
@@ -10785,6 +10811,10 @@
 #. *
 #. * A wrapper for purple_request_action() that uses Accept and Cancel buttons.
 #.
+#. *
+#. * A wrapper for purple_request_action_with_icon() that uses Accept and Cancel
+#. * buttons.
+#.
 msgid "_Accept"
 msgstr "_Accepta"
 
@@ -11865,15 +11895,14 @@
 msgid "/Conversation/Se_nd File..."
 msgstr "/Conversa/Envia un _fitxer..."
 
-#, fuzzy
 msgid "/Conversation/Get _Attention"
-msgstr "/Conversa/Aconsegueix informació"
+msgstr "/Conversa/Aconseg_ueix atenció"
 
 msgid "/Conversation/Add Buddy _Pounce..."
-msgstr "/Conversa/Afegeix un a_vís per a l'amic..."
+msgstr "/Conversa/Afe_geix un avís per a l'amic..."
 
 msgid "/Conversation/_Get Info"
-msgstr "/Conversa/_Aconsegueix informació"
+msgstr "/Conversa/Aconsegueix inf_ormació"
 
 msgid "/Conversation/In_vite..."
 msgstr "/Conversa/Con_vida..."
@@ -11888,16 +11917,16 @@
 msgstr "/Conversa/_Bloca..."
 
 msgid "/Conversation/_Unblock..."
-msgstr "/Conversa/_Desbloca..."
+msgstr "/Conversa/Desb_loca..."
 
 msgid "/Conversation/_Add..."
 msgstr "/Conversa/_Afegeix..."
 
 msgid "/Conversation/_Remove..."
-msgstr "/Conversa/Sup_rimeix..."
+msgstr "/Conversa/_Suprimeix..."
 
 msgid "/Conversation/Insert Lin_k..."
-msgstr "/Conversa/Insereix un _enllaç..."
+msgstr "/Conversa/Insereix _un enllaç..."
 
 msgid "/Conversation/Insert Imag_e..."
 msgstr "/Conversa/Insereix una _imatge..."
@@ -11950,9 +11979,8 @@
 msgid "/Conversation/Send File..."
 msgstr "/Conversa/Envia un fitxer..."
 
-#, fuzzy
 msgid "/Conversation/Get Attention"
-msgstr "/Conversa/Aconsegueix informació"
+msgstr "/Conversa/Aconsegueix atenció"
 
 msgid "/Conversation/Add Buddy Pounce..."
 msgstr "/Conversa/Afegeix avís per a l'amic..."
@@ -12930,9 +12958,8 @@
 msgid "Insert Smiley"
 msgstr "Insereix una emoticona"
 
-#, fuzzy
 msgid "Send Attention"
-msgstr "Alerta!"
+msgstr "Envia atenció"
 
 msgid "<b>_Bold</b>"
 msgstr "<b>_Negreta</b>"
@@ -12980,9 +13007,8 @@
 msgid "_Smile!"
 msgstr "_Somrieu!"
 
-#, fuzzy
 msgid "_Attention!"
-msgstr "Alerta!"
+msgstr "_Atenció!"
 
 msgid "Log Deletion Failed"
 msgstr "No s'ha pogut suprimir el registre"
@@ -13936,9 +13962,8 @@
 msgid "Custom Smiley Manager"
 msgstr "Gestor d'emoticones personalitzades"
 
-#, fuzzy
 msgid "Attention received"
-msgstr "Cal activació"
+msgstr "S'ha rebut una alerta"
 
 msgid "Select Buddy Icon"
 msgstr "Seleccioneu una icona per a l'amic"
@@ -16911,9 +16936,6 @@
 #~ msgid "_Deny"
 #~ msgstr "_Denega"
 
-#~ msgid "Invalid Username"
-#~ msgstr "El nom d'usuari no és vàlid"
-
 #~ msgid "<b>Alias:</b> %s<br>"
 #~ msgstr "<b>Àlies:</b> %s<br>"
 
--- a/po/de.po	Wed Apr 28 19:22:17 2010 +0900
+++ b/po/de.po	Wed May 05 15:42:34 2010 +0900
@@ -11,9 +11,9 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-03-29 00:12-0700\n"
-"PO-Revision-Date: 2010-02-11 21:02+0100\n"
-"Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
+"POT-Creation-Date: 2010-05-04 19:40+0200\n"
+"PO-Revision-Date: 2010-05-04 19:40+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"
@@ -1360,8 +1360,6 @@
 msgid "Saved Statuses"
 msgstr "Gespeicherter Status"
 
-#. title
-#. optional information
 msgid "Title"
 msgstr "Titel"
 
@@ -1657,6 +1655,14 @@
 msgid "Set User Info"
 msgstr "Benutzer-Info setzen"
 
+msgid "This protocol does not support setting a public alias."
+msgstr ""
+"Dieses Protokoll unterstützt das Setzen eines öffentlichen Alias nicht."
+
+msgid "This protocol does not support fetching the public alias."
+msgstr ""
+"Dieses Protokoll unterstützt nicht das Abrufen von öffentlichen Aliasen."
+
 msgid "Unknown"
 msgstr "Unbekannt"
 
@@ -3811,15 +3817,6 @@
 msgid "execute"
 msgstr "Ausführen"
 
-msgid "Server requires TLS/SSL, but no TLS/SSL support was found."
-msgstr ""
-"Der Server benötigt TLS/SSL, es wurde aber kein TLS/SSL-Support gefunden."
-
-msgid "You require encryption, but no TLS/SSL support was found."
-msgstr ""
-"Sie fordern Verschlüsselung, aber es wurde keine TLS/SSL-Unterstützung "
-"gefunden."
-
 msgid "Server requires plaintext authentication over an unencrypted stream"
 msgstr ""
 "Der Server erfordert eine Klartext-Authentifizierung über einen "
@@ -3863,6 +3860,41 @@
 msgid "SASL error: %s"
 msgstr "SASL-Fehler: %s"
 
+msgid "Invalid Encoding"
+msgstr "Ungültige Kodierung"
+
+msgid "Unsupported Extension"
+msgstr "Nicht-unterstützte Erweiterung"
+
+msgid ""
+"Unexpected response from the server.  This may indicate a possible MITM "
+"attack"
+msgstr ""
+"Unerwartete Antwort vom Server.  Das kann auf eine mögliche MITM-Attacke "
+"hindeuten"
+
+msgid ""
+"The server does support channel binding, but did not appear to advertise "
+"it.  This indicates a likely MITM attack"
+msgstr ""
+"Der Server unterstützt Kanalbindung, aber er macht das nicht bekannt.  Das "
+"deuted auf eine wahrscheinliche MITM-Attacke hin"
+
+msgid "Server does not support channel binding"
+msgstr "Server unterstützt keine Kanalbindung"
+
+msgid "Unsupported channel binding method"
+msgstr "Nicht-unterstützte Kanalbindungsmethode"
+
+msgid "User not found"
+msgstr "Benutzer nicht gefunden"
+
+msgid "Invalid Username Encoding"
+msgstr "Ungültig Kodierung des Benutzernamens"
+
+msgid "Resource Constraint"
+msgstr "Ressourcen-Einschränkung"
+
 msgid "Unable to canonicalize username"
 msgstr "Benutzername konnte nicht in Normalform gebracht werden"
 
@@ -3940,6 +3972,11 @@
 msgid "Organization Unit"
 msgstr "Organisationseinheit"
 
+#. title
+#. optional information
+msgid "Job Title"
+msgstr "Beruf"
+
 msgid "Role"
 msgstr "Funktion"
 
@@ -4163,12 +4200,24 @@
 msgid "Roles:"
 msgstr "Rollen:"
 
+msgid "Server requires TLS/SSL, but no TLS/SSL support was found."
+msgstr ""
+"Der Server benötigt TLS/SSL, es wurde aber kein TLS/SSL-Support gefunden."
+
+msgid "You require encryption, but no TLS/SSL support was found."
+msgstr ""
+"Sie fordern Verschlüsselung, aber es wurde keine TLS/SSL-Unterstützung "
+"gefunden."
+
 msgid "Ping timed out"
 msgstr "Ping-Zeitüberschreitung"
 
 msgid "Invalid XMPP ID"
 msgstr "Ungültige XMPP-ID"
 
+msgid "Invalid XMPP ID. Username portion must be set."
+msgstr "Falsche XMPP-ID. Der Benutzername muss gesetzt werden."
+
 msgid "Invalid XMPP ID. Domain must be set."
 msgstr "Falsche XMPP-ID. Die Domain muss gesetzt werden."
 
@@ -4305,14 +4354,18 @@
 msgid "Allow Buzz"
 msgstr "Anklopfen erlauben"
 
-#, fuzzy
 msgid "Mood Name"
-msgstr "Zweiter Name"
-
-#, fuzzy
+msgstr "Name der Stimmung"
+
 msgid "Mood Comment"
-msgstr "Buddy-Kommentar"
-
+msgstr "Stimmungskommentar"
+
+#. primitive
+#. ID
+#. name - use default
+#. saveable
+#. should be user_settable some day
+#. independent
 msgid "Tune Artist"
 msgstr "Künstler anpassen"
 
@@ -4483,9 +4536,6 @@
 msgid "Remote Connection Failed"
 msgstr "Entfernte Verbindung fehlgeschlagen"
 
-msgid "Resource Constraint"
-msgstr "Eingeschränkte Ressourcen"
-
 msgid "Restricted XML"
 msgstr "Eingeschränktes XML"
 
@@ -4603,9 +4653,8 @@
 msgid "Initiate Media"
 msgstr "Initiiere Medien"
 
-#, fuzzy
 msgid "Account does not support PEP, can't set mood"
-msgstr "Dieses Protokoll unterstützt keine Chaträume."
+msgstr "Konto unterstützt kein PEP, kann die Stimmung nicht setzen"
 
 msgid "config:  Configure a chat room."
 msgstr "config:  Konfiguriere einen Chatraum."
@@ -4663,9 +4712,8 @@
 msgid "buzz: Buzz a user to get their attention"
 msgstr "buzz: Einen Kontakt anrufen, um seine Aufmerksamkeit zu erhalten"
 
-#, fuzzy
 msgid "mood: Set current user mood"
-msgstr "Wählen Sie den richtigen Benutzer"
+msgstr "mood: Setze die aktuelle Benutzerstimmung"
 
 msgid "Extended Away"
 msgstr "Abwesend (erweitert)"
@@ -4749,13 +4797,13 @@
 "werden."
 
 msgid "XMPP stream header missing"
-msgstr ""
+msgstr "Der XMPP-Datenstromkopf fehlt"
 
 msgid "XMPP Version Mismatch"
-msgstr ""
+msgstr "XMPP-Versionskonflikt"
 
 msgid "XMPP stream missing ID"
-msgstr ""
+msgstr "Fehlende ID im XMPP-Datenstrom"
 
 msgid "XML Parse error"
 msgstr "Fehler beim Einlesen von XML-Daten"
@@ -4834,32 +4882,27 @@
 msgstr ""
 "Bitte wählen Sie die Ressource von %s, an die Sie eine Datei schicken möchten"
 
-#, fuzzy
 msgid "Afraid"
-msgstr "Arabisch"
-
-#, fuzzy
+msgstr "Ängstlich"
+
 msgid "Amazed"
-msgstr "Beschämt"
-
-#, fuzzy
+msgstr "Verblüfft"
+
 msgid "Amorous"
-msgstr "Glorreich"
+msgstr "Sinnlich"
 
 #. 1
 msgid "Angry"
 msgstr "Verärgert"
 
-#, fuzzy
 msgid "Annoyed"
-msgstr "Verbannt"
+msgstr "Verärgert"
 
 msgid "Anxious"
 msgstr "Besorgt"
 
-#, fuzzy
 msgid "Aroused"
-msgstr "Sie senden"
+msgstr "Aufgerüttelt"
 
 msgid "Ashamed"
 msgstr "Beschämt"
@@ -4867,243 +4910,201 @@
 msgid "Bored"
 msgstr "Gelangweilt"
 
-#, fuzzy
 msgid "Brave"
-msgstr "Speichern"
-
-#, fuzzy
+msgstr "Tapfer"
+
 msgid "Calm"
-msgstr "Realm"
-
-#, fuzzy
+msgstr "Beruhigt"
+
 msgid "Cautious"
-msgstr "Chats"
-
-#, fuzzy
+msgstr "Zurückhaltend"
+
 msgid "Cold"
-msgstr "Fett"
-
-#, fuzzy
+msgstr "Unterkühlt"
+
 msgid "Confident"
-msgstr "Konflikt"
-
-#, fuzzy
+msgstr "Zuversichtlich"
+
 msgid "Confused"
-msgstr "Fortfahren"
-
-#, fuzzy
+msgstr "Verwirrt"
+
 msgid "Contemplative"
-msgstr "Kontakt"
-
-#, fuzzy
+msgstr "Nachdenklich"
+
 msgid "Contented"
-msgstr "Verbunden"
-
-#, fuzzy
+msgstr "Zufrieden"
+
 msgid "Cranky"
-msgstr "Firma"
+msgstr "Schrullig"
 
 msgid "Crazy"
-msgstr ""
-
-#, fuzzy
+msgstr "Verrückt"
+
 msgid "Creative"
-msgstr "Erzeugen"
-
-#, fuzzy
+msgstr "Kreativ"
+
 msgid "Curious"
-msgstr "Glorreich"
-
-#, fuzzy
+msgstr "Neugierig"
+
 msgid "Dejected"
-msgstr "Abgelehnt"
-
-#, fuzzy
+msgstr "Niedergeschlagen"
+
 msgid "Depressed"
-msgstr "Gelöscht"
-
-#, fuzzy
+msgstr "Deprimiert"
+
 msgid "Disappointed"
-msgstr "Verbindung unterbrochen."
+msgstr "Enttäuscht"
 
 msgid "Disgusted"
-msgstr ""
-
-#, fuzzy
+msgstr "Empört"
+
 msgid "Dismayed"
-msgstr "Deaktiviert"
-
-#, fuzzy
+msgstr "Bestürzt"
+
 msgid "Distracted"
-msgstr "Unbeteiligt"
+msgstr "Abgelenkt"
 
 msgid "Embarrassed"
-msgstr ""
-
-#, fuzzy
+msgstr "Verlegen"
+
 msgid "Envious"
-msgstr "Besorgt"
+msgstr "Neidisch"
 
 #. 2
 msgid "Excited"
 msgstr "Aufgeregt"
 
-#, fuzzy
 msgid "Flirtatious"
-msgstr "Glorreich"
+msgstr "Verführerisch"
 
 # old strings
-#, fuzzy
 msgid "Frustrated"
-msgstr "Vorname"
+msgstr "Frustriert"
 
 msgid "Grateful"
-msgstr ""
-
-#, fuzzy
+msgstr "Dankbar"
+
 msgid "Grieving"
-msgstr "Empfange..."
+msgstr "Trauernd"
 
 #. 3
 msgid "Grumpy"
-msgstr "Mürrisch"
-
-#, fuzzy
+msgstr "Brummig"
+
 msgid "Guilty"
-msgstr "Stadt"
+msgstr "Schuldig"
 
 #. 4
 msgid "Happy"
 msgstr "Glücklich"
 
 msgid "Hopeful"
-msgstr ""
+msgstr "Hoffnungsvoll"
 
 #. 8
 msgid "Hot"
 msgstr "Heiß"
 
 msgid "Humbled"
-msgstr ""
+msgstr "Gedemütigt"
 
 msgid "Humiliated"
-msgstr ""
-
-#, fuzzy
+msgstr "Erniedrigt"
+
 msgid "Hungry"
-msgstr "Verärgert"
-
-#, fuzzy
+msgstr "Hungrig"
+
 msgid "Hurt"
-msgstr "Humor"
+msgstr "Verletzt"
 
 msgid "Impressed"
-msgstr ""
-
-#, fuzzy
+msgstr "Beeindruckt"
+
 msgid "In awe"
-msgstr "Verliebt"
+msgstr "Ehrfurchtsvoll"
 
 msgid "In love"
 msgstr "Verliebt"
 
-#, fuzzy
 msgid "Indignant"
-msgstr "Indonesisch"
-
-#, fuzzy
+msgstr "Entrüstet"
+
 msgid "Interested"
-msgstr "Interessen"
-
-#, fuzzy
+msgstr "Interessiert"
+
 msgid "Intoxicated"
-msgstr "Eingeladen"
+msgstr "Betrunken"
 
 #. 6
 msgid "Invincible"
-msgstr "Unerschütterlich"
+msgstr "Unbesiegbar"
 
 msgid "Jealous"
 msgstr "Eifersüchtig"
 
-#, fuzzy
 msgid "Lonely"
-msgstr "Affe"
-
-#, fuzzy
+msgstr "Einsam"
+
 msgid "Lost"
-msgstr "Am lautesten"
+msgstr "Verloren"
 
 msgid "Lucky"
-msgstr ""
-
-#, fuzzy
+msgstr "Glücklich"
+
 msgid "Mean"
-msgstr "Deutsch"
-
-#, fuzzy
+msgstr "Gemein"
+
 msgid "Moody"
-msgstr "Stimmung"
+msgstr "Launisch"
 
 msgid "Nervous"
-msgstr ""
-
-#, fuzzy
+msgstr "Reizbar"
+
 msgid "Neutral"
-msgstr "Detail"
-
-#, fuzzy
+msgstr "Gleichgültig"
+
 msgid "Offended"
-msgstr "Offline"
+msgstr "Beleidigt"
 
 msgid "Outraged"
-msgstr ""
-
-#, fuzzy
+msgstr "Schockiert"
+
 msgid "Playful"
-msgstr "Abspielen"
-
-#, fuzzy
+msgstr "Verspielt"
+
 msgid "Proud"
-msgstr "Laut"
-
-#, fuzzy
+msgstr "Stolz"
+
 msgid "Relaxed"
-msgstr "Echter Name"
-
-#, fuzzy
+msgstr "Entspannt"
+
 msgid "Relieved"
-msgstr "Empfangen"
-
-#, fuzzy
+msgstr "Erleichtert"
+
 msgid "Remorseful"
-msgstr "Entfernen"
-
-#, fuzzy
+msgstr "Reumütig"
+
 msgid "Restless"
-msgstr "Registrieren"
+msgstr "Ruhelos"
 
 #. 7
 msgid "Sad"
 msgstr "Traurig"
 
-#, fuzzy
 msgid "Sarcastic"
-msgstr "Marathi"
+msgstr "Sarkastisch"
 
 msgid "Satisfied"
-msgstr ""
-
-#, fuzzy
+msgstr "Befriedigt"
+
 msgid "Serious"
-msgstr "Glorreich"
-
-#, fuzzy
+msgstr "Ernsthaft"
+
 msgid "Shocked"
-msgstr "Blockiert"
+msgstr "Schockiert"
 
 msgid "Shy"
-msgstr ""
+msgstr "Schüchtern"
 
 #. 9
 msgid "Sick"
@@ -5115,40 +5116,34 @@
 msgstr "Müde"
 
 msgid "Spontaneous"
-msgstr ""
-
-#, fuzzy
+msgstr "Spontan"
+
 msgid "Stressed"
-msgstr "Geschwindigkeit"
-
-#, fuzzy
+msgstr "Gestresst"
+
 msgid "Strong"
-msgstr "Lied"
+msgstr "Stark"
 
 msgid "Surprised"
-msgstr ""
+msgstr "Überrascht"
 
 msgid "Thankful"
-msgstr ""
+msgstr "Dankbar"
 
 msgid "Thirsty"
-msgstr ""
-
-#, fuzzy
+msgstr "Durstig"
+
 msgid "Tired"
-msgstr "Fire"
-
-#, fuzzy
+msgstr "Müde"
+
 msgid "Undefined"
-msgstr "Unterstrichen"
-
-#, fuzzy
+msgstr "Unbekannt"
+
 msgid "Weak"
-msgstr "Schlag"
-
-#, fuzzy
+msgstr "Schwach"
+
 msgid "Worried"
-msgstr "Gelangweilt"
+msgstr "Besorgt"
 
 msgid "Set User Nickname"
 msgstr "Setze Benutzer-Spitzname"
@@ -5516,18 +5511,6 @@
 msgid "Out to Lunch"
 msgstr "Zur Mittagspause"
 
-#. primitive
-#. ID
-#. name - use default
-#. saveable
-#. should be user_settable some day
-#. independent
-msgid "Artist"
-msgstr "Interpret"
-
-msgid "Album"
-msgstr "Album"
-
 msgid "Game Title"
 msgstr "Spieltitel"
 
@@ -5677,9 +5660,6 @@
 msgid "Work"
 msgstr "Geschäftlich"
 
-msgid "Job Title"
-msgstr "Beruf"
-
 msgid "Company"
 msgstr "Firma"
 
@@ -6719,9 +6699,6 @@
 msgid "Incorrect password"
 msgstr "Falsches Passwort"
 
-msgid "User not found"
-msgstr "Benutzer nicht gefunden"
-
 msgid "Account has been disabled"
 msgstr "Konto wurde deaktiviert"
 
@@ -6988,6 +6965,10 @@
 msgid "AOL does not allow your screen name to authenticate here"
 msgstr "AOL erlaubt Ihnen nicht, sich hier mit Ihrem Benutzernamen anzumelden"
 
+#, c-format
+msgid "Error requesting %s"
+msgstr "Fehler beim Anfordern von %s"
+
 msgid "Could not join chat room"
 msgstr "Konnte Chatraum nicht betreten"
 
@@ -6995,104 +6976,88 @@
 msgstr "Ungültiger Chatraumname"
 
 msgid "Thinking"
-msgstr ""
-
-#, fuzzy
+msgstr "Denkt nach"
+
 msgid "Shopping"
-msgstr "aufhört zu tippen"
-
-#, fuzzy
+msgstr "Kauft ein"
+
 msgid "Questioning"
-msgstr "Frage-Dialog"
-
-#, fuzzy
+msgstr "Fragt etwas"
+
 msgid "Eating"
-msgstr "Funkruf"
-
-#, fuzzy
+msgstr "Beim Essen"
+
 msgid "Watching a movie"
-msgstr "Spielt ein Spiel"
+msgstr "Schaut einen Film an"
 
 msgid "Typing"
 msgstr "Tippt gerade"
 
-#, fuzzy
 msgid "At the office"
-msgstr "Nicht im Büro"
+msgstr "Im Büro"
 
 msgid "Taking a bath"
-msgstr ""
+msgstr "Nimmt ein Bad"
 
 msgid "Watching TV"
-msgstr ""
-
-#, fuzzy
+msgstr "Schaut Fernsehen"
+
 msgid "Having fun"
-msgstr "Auflegen"
-
-#, fuzzy
+msgstr "Hat Spaß"
+
 msgid "Sleeping"
-msgstr "Müde"
+msgstr "Schläft"
 
 msgid "Using a PDA"
-msgstr ""
-
-#, fuzzy
+msgstr "Benutzt einen PDA"
+
 msgid "Meeting friends"
-msgstr "IM-Freunde"
-
-#, fuzzy
+msgstr "Freunde treffen"
+
 msgid "On the phone"
 msgstr "Am Telefon"
 
-#, fuzzy
 msgid "Surfing"
-msgstr "Wiederkehrend"
+msgstr "Surft (im Internet)"
 
 #. "I am mobile." / "John is mobile."
 msgid "Mobile"
-msgstr "Mobil"
+msgstr "Ist mobil"
 
 msgid "Searching the web"
-msgstr ""
+msgstr "Sucht etwas im Web"
 
 msgid "At a party"
-msgstr ""
+msgstr "Auf einer Party"
 
 msgid "Having Coffee"
-msgstr ""
+msgstr "Trinkt Kaffee"
 
 #. Playing video games
-#, fuzzy
 msgid "Gaming"
-msgstr "Zwillinge"
+msgstr "Spielt am PC"
 
 msgid "Browsing the web"
-msgstr ""
-
-#, fuzzy
+msgstr "Surft im Web"
+
 msgid "Smoking"
-msgstr "Lied"
-
-#, fuzzy
+msgstr "Raucht"
+
 msgid "Writing"
-msgstr "Arbeitet"
+msgstr "Schreibt"
 
 #. Drinking [Alcohol]
-#, fuzzy
 msgid "Drinking"
-msgstr "Arbeitet"
+msgstr "Trinkt"
 
 msgid "Listening to music"
 msgstr "Musik hören"
 
-#, fuzzy
 msgid "Studying"
-msgstr "Sende"
-
-#, fuzzy
+msgstr "Studiert"
+
 msgid "In the restroom"
-msgstr "Interessen"
+msgstr "Auf der Toilette"
 
 msgid "Received invalid data on connection with server"
 msgstr "Ungültige Daten in der Verbindung mit dem Server empfangen"
@@ -7311,7 +7276,7 @@
 msgstr "Spiele"
 
 msgid "ICQ Xtraz"
-msgstr ""
+msgstr "ICQ Xtraz"
 
 msgid "Add-Ins"
 msgstr "Zusätze"
@@ -7379,23 +7344,18 @@
 msgid "Invisible"
 msgstr "Unsichtbar"
 
-#, fuzzy
 msgid "Evil"
-msgstr "E-Mail"
-
-#, fuzzy
+msgstr "Böse"
+
 msgid "Depression"
-msgstr "Beruf"
-
-#, fuzzy
+msgstr "Depression"
+
 msgid "At home"
-msgstr "Über mich"
-
-#, fuzzy
+msgstr "Zu Hause"
+
 msgid "At work"
-msgstr "Netzwerk"
-
-#, fuzzy
+msgstr "Bei der Arbeit"
+
 msgid "At lunch"
 msgstr "Zur Mittagspause"
 
@@ -7936,9 +7896,8 @@
 msgid "iTunes Music Store Link"
 msgstr "iTunes Music Store Link"
 
-#, fuzzy
 msgid "Lunch"
-msgstr "Finch"
+msgstr "Mittagspause"
 
 #, c-format
 msgid "Buddy Comment for %s"
@@ -7971,9 +7930,8 @@
 msgid "Edit Buddy Comment"
 msgstr "Buddy-Kommentar bearbeiten"
 
-#, fuzzy
 msgid "Get X-Status Msg"
-msgstr "Abwesenheitsmitteilung abrufen"
+msgstr "X-Status-Nachricht abrufen"
 
 msgid "End Direct IM Session"
 msgstr "Direkt-IM-Sitzung beenden"
@@ -8384,6 +8342,10 @@
 msgid "Admin"
 msgstr "Admin"
 
+#. XXX: Should this be "Topic"?
+msgid "Room Title"
+msgstr "Raumtitel"
+
 msgid "Notice"
 msgstr "Bemerkung"
 
@@ -10311,9 +10273,6 @@
 msgid "Yahoo! Protocol Plugin"
 msgstr "Yahoo!-Protokoll-Plugin"
 
-msgid "Pager server"
-msgstr "Pager-Server"
-
 msgid "Pager port"
 msgstr "Pager-Port"
 
@@ -10335,12 +10294,6 @@
 msgid "Chat room list URL"
 msgstr "Chatraumliste (URL)"
 
-msgid "Yahoo Chat server"
-msgstr "Yahoo-Chat-Server"
-
-msgid "Yahoo Chat port"
-msgstr "Yahoo-Chat-Port"
-
 msgid "Yahoo JAPAN ID..."
 msgstr "Yahoo-JAPAN-ID..."
 
@@ -10409,6 +10362,15 @@
 "Konto gesperrt: Unbekannter Grund. Eventuell können Sie dies beheben, wenn "
 "Sie sich auf der Yahoo!-Webseite anmelden."
 
+#. indicates a lock due to logging in too frequently
+msgid ""
+"Account locked: You have been logging in too frequently.  Wait a few minutes "
+"before trying to connect again.  Logging into the Yahoo! website may help."
+msgstr ""
+"Konto gesperrt: Zu viele fehlgeschlagene Login-Versuche. Warten Sie einige "
+"Minuten bevor Sie erneut versuchen sich zu verbinden. Eventuell können Sie "
+"dies beheben, wenn Sie sich auf der Yahoo!-Webseite anmelden."
+
 #. username or password missing
 msgid "Username or password missing"
 msgstr "Benutzername oder Passwort fehlt"
@@ -10489,6 +10451,16 @@
 msgid "Unable to establish a connection with %s: %s"
 msgstr "Die Verbindung mit %s konnte nicht hergestellt werden: %s"
 
+msgid "Unable to connect: The server returned an empty response."
+msgstr "Verbindung fehlgeschlagen: Der Server lieferte eine leere Antwort."
+
+msgid ""
+"Unable to connect: The server's response did not contain the necessary "
+"information"
+msgstr ""
+"Verbindung fehlgeschlagen: Die Antwort des Servers enthielt die nötigen "
+"Informationen nicht"
+
 msgid "Not at Home"
 msgstr "Nicht zu Hause"
 
@@ -10879,6 +10851,10 @@
 #. *
 #. * A wrapper for purple_request_action() that uses Accept and Cancel buttons.
 #.
+#. *
+#. * A wrapper for purple_request_action_with_icon() that uses Accept and Cancel
+#. * buttons.
+#.
 msgid "_Accept"
 msgstr "_Akzeptieren"
 
@@ -10945,9 +10921,8 @@
 msgid "Extended away"
 msgstr "Länger abwesend"
 
-#, fuzzy
 msgid "Feeling"
-msgstr "Empfange"
+msgstr "Befinden"
 
 #, c-format
 msgid "%s (%s) changed status from %s to %s"
@@ -11120,12 +11095,6 @@
 msgid "Pidgin Internet Messenger"
 msgstr "Pidgin Internet-Sofortnachrichtendienst"
 
-msgid "Orientation"
-msgstr "Ausrichtung"
-
-msgid "The orientation of the tray."
-msgstr "Die Ausrichtung der Kontrollleiste."
-
 #. Build the login options frame.
 msgid "Login Options"
 msgstr "Anmeldeoptionen"
@@ -11499,13 +11468,11 @@
 msgid "Unknown node type"
 msgstr "Unbekannter Knotentyp"
 
-#, fuzzy
 msgid "Please select your mood from the list"
-msgstr "Bitte setzen Sie eine Stimmung aus der Liste."
-
-#, fuzzy
+msgstr "Bitte wählen Sie Ihre Stimmung aus der Liste"
+
 msgid "Message (optional)"
-msgstr "Alias (optional)"
+msgstr "Nachricht (optional)"
 
 msgid "Edit User Mood"
 msgstr "Benutzerstimmung ändern"
@@ -11588,9 +11555,8 @@
 msgid "/Tools/Pr_ivacy"
 msgstr "/Werkzeuge/Pri_vatsphäre"
 
-#, fuzzy
 msgid "/Tools/Set _Mood"
-msgstr "/Werkzeuge/_System-Mitschnitt"
+msgstr "/Werkzeuge/Setze _Stimmung"
 
 msgid "/Tools/_File Transfers"
 msgstr "/Werkzeuge/_Dateiübertragungen"
@@ -11611,20 +11577,17 @@
 msgid "/Help/Online _Help"
 msgstr "/Hilfe/Online-_Hilfe"
 
-#, fuzzy
 msgid "/Help/_Build Information"
-msgstr "Buddy-Information"
+msgstr "/Hilfe/_Build-Informationen"
 
 msgid "/Help/_Debug Window"
 msgstr "/Hilfe/_Debug-Fenster"
 
-#, fuzzy
 msgid "/Help/De_veloper Information"
-msgstr "Serverinformation"
-
-#, fuzzy
+msgstr "/Hilfe/_Entwickler-Informationen"
+
 msgid "/Help/_Translator Information"
-msgstr "Persönliche Informationen"
+msgstr "/Hilfe/Ü_bersetzer-Informationen"
 
 msgid "/Help/_About"
 msgstr "/Hilfe/Ü_ber"
@@ -11855,9 +11818,8 @@
 msgid "_Edit Account"
 msgstr "Konto _bearbeiten"
 
-#, fuzzy
 msgid "Set _Mood..."
-msgstr "Setze Stimmung..."
+msgstr "Setze _Stimmung..."
 
 msgid "No actions available"
 msgstr "Keine Aktionen verfügbar"
@@ -11979,9 +11941,8 @@
 msgid "/Conversation/Se_nd File..."
 msgstr "/Unterhaltung/Datei _senden..."
 
-#, fuzzy
 msgid "/Conversation/Get _Attention"
-msgstr "/Unterhaltung/Info abrufen"
+msgstr "/Unterhaltung/_Aufmerksamkeit erregen"
 
 msgid "/Conversation/Add Buddy _Pounce..."
 msgstr "/Unterhaltung/_Buddy-Alarm hinzufügen..."
@@ -12064,9 +12025,8 @@
 msgid "/Conversation/Send File..."
 msgstr "/Unterhaltung/Datei senden ..."
 
-#, fuzzy
 msgid "/Conversation/Get Attention"
-msgstr "/Unterhaltung/Info abrufen"
+msgstr "/Unterhaltung/Aufmerksamkeit erregen"
 
 msgid "/Conversation/Add Buddy Pounce..."
 msgstr "/Unterhaltung/Buddy-Alarm hinzufügen..."
@@ -12132,13 +12092,11 @@
 msgid "0 people in room"
 msgstr "0 Personen im Raum"
 
-#, fuzzy
 msgid "Close Find bar"
-msgstr "Diesen Reiter schließen"
-
-#, fuzzy
+msgstr "Suchleiste schließen"
+
 msgid "Find:"
-msgstr "Suchen"
+msgstr "Suchen:"
 
 #, c-format
 msgid "%d person in room"
@@ -12311,6 +12269,9 @@
 msgid "Bengali"
 msgstr "Bengalisch"
 
+msgid "Bengali-India"
+msgstr "Bengalisch"
+
 msgid "Bosnian"
 msgstr "Bosnisch"
 
@@ -12533,7 +12494,7 @@
 msgid "Lithuanian"
 msgstr "Litauisch"
 
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "%s is a messaging client based on libpurple which is capable of connecting "
 "to multiple messaging services at once.  %s is written in C using GTK+.  %s "
@@ -12542,15 +12503,14 @@
 "copyrighted by its contributors, a list of whom is also distributed with %"
 "s.  There is no warranty for %s.<BR><BR>"
 msgstr ""
-"%s ist ein grafischer modularer Nachrichtendienst, basierend auf libpurple, "
-"der AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC, SIP/SIMPLE, Novell GroupWise, "
-"Lotus Sametime, Bonjour, Zephyr, MySpaceIM, Gadu-Gadu und QQ gleichzeitig "
-"unterstützt.  Er wird mit GTK+ entwickelt.<BR><BR>Sie können das Programm "
-"nach den Bedingungen der GPL (Version 2 oder später) modifizieren und "
-"weitergeben.  Eine Kopie der GPL ist in der Datei 'COPYING' enthalten, die "
-"mit %s ausgeliefert wird.  %s wird von seinen Mitwirkenden urheberrechtlich "
-"geschützt.  Die Datei 'COPYRIGHT' enthält die komplette Liste der "
-"Mitwirkenden.  Wir übernehmen keine Haftung für dieses Programm.<BR><BR>"
+"%s ist ein Nachrichtendienst, basierend auf libpurple, der die Verbindung zu "
+"mehreren Nachrichtendiensten gleichzeitig unterstützt.  %s wird mit C und GTK"
+"+ entwickelt.  %s ist nach den Bedingungen der GPL (Version 2 oder später) "
+"freigegeben und darf gemäß dieser bearbeitet und weiter verbreitet werden.  "
+"Eine Kopie der GPL wird mit %s ausgeliefert.  %s wird von seinen "
+"Mitwirkenden urheberrechtlich geschützt.  Eine komplette Liste der "
+"Mitwirkenden wird mit %s ausgeliefert.  Wir übernehmen keine Haftung für %s."
+"<BR><BR>"
 
 #, c-format
 msgid ""
@@ -12559,8 +12519,12 @@
 "Channel: #pidgin on irc.freenode.net<BR>\tXMPP MUC: devel@conference.pidgin."
 "im<BR><BR>"
 msgstr ""
-
-#, fuzzy, c-format
+"<FONT SIZE=\"4\"><B>Hilfreiche Quellen</B></FONT><BR>\t<A HREF=\"%s"
+"\">Webseite</A><BR>\t<A HREF=\"%s\">Häufig gestellte Fragen (FAQ)</A><BR>"
+"\tIRC-Channel: #pidgin auf irc.freenode.net<BR>\tXMPP-MUC: devel@conference."
+"pidgin.im<BR><BR>"
+
+#, c-format
 msgid ""
 "<font size=\"4\"><b>Help from other Pidgin users</b></font> is available by "
 "e-mailing <a href=\"mailto:support@pidgin.im\">support@pidgin.im</a><br/"
@@ -12570,31 +12534,31 @@
 "welcome to post in another language, but the responses may be less helpful."
 "<br/>"
 msgstr ""
-"<font size=\"4\">Hilfe von anderen Pidgin-Benutzern:</font> <a href=\"mailto:"
-"support@pidgin.im\">support@pidgin.im</a><br/>Dies ist eine <b>öffentliche</"
-"b> Mailing-Liste! (<a href=\"http://pidgin.im/pipermail/support/\">Archiv</"
-"a>)<br/>Wir können nicht bei Problemen mit Drittanbieter-Protokollen oder "
-"Plugins helfen!<br/>Die Hauptsprache dieser Liste ist <b>Englisch</b>.  Sie "
-"können gern in einer anderen Sprache schreiben, aber die Antworten könnten "
-"weniger hilfreich sein.<br/>Deutschsprachige Benutzer können auch das Portal "
-"<a href=\"http://www.pidgin-im.de/\">Pidgin-IM.de</a> nutzen.  Dort finden "
-"Sie aktuelle Informationen zu Pidgin, können mit anderen Benutzern im <a "
-"href=\"http://forum.pidgin-im.de/\">Forum</a> diskutieren und Hilfe zu "
-"Problemen finden.  Beachten Sie, dass dieses Portal unabhängig vom "
-"offiziellen Pidgin-Projekt ist.<br/><br/>"
+"<font size=\"4\"><b>Hilfe von anderen Pidgin-Benutzern</b></font> erhält man "
+"per E-Mail an <a href=\"mailto:support@pidgin.im\">support@pidgin.im</a><br/"
+">Dies ist eine <b>öffentliche</b> Mailing-Liste! (<a href=\"http://pidgin.im/"
+"pipermail/support/\">Archiv</a>)<br/>Wir können nicht bei Problemen mit "
+"Drittanbieter-Protokollen oder Plugins helfen!<br/>Die Hauptsprache dieser "
+"Liste ist <b>Englisch</b>.  Sie können gern in einer anderen Sprache "
+"schreiben, aber die Antworten könnten weniger hilfreich sein.<br/"
+">Deutschsprachige Benutzer können auch das Portal <a href=\"http://www."
+"pidgin-im.de/\">Pidgin-IM.de</a> nutzen.  Dort finden Sie aktuelle "
+"Informationen zu Pidgin, können mit anderen Benutzern im <a href=\"http://"
+"forum.pidgin-im.de/\">Forum</a> diskutieren und Hilfe zu Problemen finden.  "
+"Beachten Sie, dass dieses Portal unabhängig vom offiziellen Pidgin-Projekt "
+"ist.<br/><br/>"
 
 #, c-format
 msgid "About %s"
 msgstr "Über %s"
 
-#, fuzzy
 msgid "Build Information"
-msgstr "Buddy-Information"
+msgstr "Build-Informationen"
 
 #. End of not to be translated section
-#, fuzzy, c-format
+#, c-format
 msgid "%s Build Information"
-msgstr "Buddy-Information"
+msgstr "%s-Build-Informationen"
 
 msgid "Current Developers"
 msgstr "Aktuelle Entwickler"
@@ -12608,9 +12572,9 @@
 msgid "Retired Crazy Patch Writers"
 msgstr "Zurückgetretene verrückte Patchschreiber"
 
-#, fuzzy, c-format
+#, c-format
 msgid "%s Developer Information"
-msgstr "Serverinformation"
+msgstr "%s-Entwickler-Informationen"
 
 msgid "Current Translators"
 msgstr "Aktuelle Übersetzer"
@@ -12618,9 +12582,9 @@
 msgid "Past Translators"
 msgstr "Frühere Übersetzer"
 
-#, fuzzy, c-format
+#, c-format
 msgid "%s Translator Information"
-msgstr "Mehr Informationen"
+msgstr "%s-Übersetzer-Informationen"
 
 msgid "_Name"
 msgstr "_Name"
@@ -12871,7 +12835,7 @@
 "Farbe, mit der der Name in einer empfangenen Nachricht dargestellt wird."
 
 msgid "\"Attention\" Name Color"
-msgstr "Farbe des Absendernamens für „Achtung“-Nachrichten"
+msgstr "Farbe des Absendernamens für „Aufmerksamkeits“-Nachrichten"
 
 msgid "Color to draw the name of a message you received containing your name."
 msgstr ""
@@ -13042,9 +13006,8 @@
 msgid "Insert Smiley"
 msgstr "Smiley einfügen"
 
-#, fuzzy
 msgid "Send Attention"
-msgstr "Senden-Knopf"
+msgstr "Aufmerksamkeitsgesuch senden"
 
 msgid "<b>_Bold</b>"
 msgstr "<b>_Fett</b>"
@@ -13092,7 +13055,7 @@
 msgstr "_Lächeln!"
 
 msgid "_Attention!"
-msgstr ""
+msgstr "_Aufmerksamkeit!"
 
 msgid "Log Deletion Failed"
 msgstr "Löschen des Mitschnitts fehlgeschlagen"
@@ -14040,9 +14003,8 @@
 msgid "Custom Smiley Manager"
 msgstr "Verwaltung für benutzerdefinierte Smileys"
 
-#, fuzzy
 msgid "Attention received"
-msgstr "Aktivierung erforderlich"
+msgstr "Aufmerksamkeitsgesuch erhalten"
 
 msgid "Select Buddy Icon"
 msgstr "Buddy-Icon auswählen"
@@ -15189,8 +15151,17 @@
 msgstr "Zeitstempelformat-Optionen"
 
 #, c-format
-msgid "_Force 24-hour time format"
-msgstr "_Erzwinge 24-Stunden Zeitformat"
+msgid "_Force timestamp format:"
+msgstr "_Erzwinge Zeitformat:"
+
+msgid "Use system default"
+msgstr "System-Vorgabe verwenden"
+
+msgid "12 hour time format"
+msgstr "12-Stunden-Zeitformat"
+
+msgid "24 hour time format"
+msgstr "24-Stunden-Zeitformat"
 
 msgid "Show dates in..."
 msgstr "Zeige Datumsangaben in..."
@@ -15391,11 +15362,31 @@
 msgstr "Sendet und empfängt RAW-XMPP-Blöcke."
 
 #. *  description
-#, fuzzy
 msgid "This plugin is useful for debugging XMPP servers or clients."
 msgstr ""
 "Dieses Plugin ist nützlich zur Fehlersuche in XMPP-Servern oder -Clients."
 
+#~ msgid "Artist"
+#~ msgstr "Interpret"
+
+#~ msgid "Album"
+#~ msgstr "Album"
+
+#~ msgid "Pager server"
+#~ msgstr "Pager-Server"
+
+#~ msgid "Yahoo Chat server"
+#~ msgstr "Yahoo-Chat-Server"
+
+#~ msgid "Yahoo Chat port"
+#~ msgstr "Yahoo-Chat-Port"
+
+#~ msgid "Orientation"
+#~ msgstr "Ausrichtung"
+
+#~ msgid "The orientation of the tray."
+#~ msgstr "Die Ausrichtung der Kontrollleiste."
+
 #~ msgid "Error creating conference."
 #~ msgstr "Fehler beim Erstellen der Konferenz."