changeset 27782:9cd7892b2c8b

propagate from branch 'im.pidgin.pidgin' (head dfdceb0b08475c3e5750b3e6430d154e9a747d67) to branch 'im.pidgin.pidgin.yaz' (head 7982395e45644f3f5d8b4a39018946e19ea9572f)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Tue, 04 Mar 2008 18:12:32 +0000
parents 11713f052640 (current diff) b77c8a87e15e (diff)
children b31b72cd273d
files libpurple/protocols/oscar/family_icbm.c libpurple/protocols/oscar/oscar.c pidgin/gtkimhtml.c pidgin/gtkmain.c
diffstat 18 files changed, 325 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue Mar 04 18:10:40 2008 +0000
+++ b/COPYRIGHT	Tue Mar 04 18:12:32 2008 +0000
@@ -327,6 +327,7 @@
 Peter Ruibal
 Sam S.
 Thanumalayan S.
+Tomasz Sałaciński <tsalacinski@gmail.com>
 Pradyumna Sampath
 Arvind Samptur
 Tom Samstag
--- a/ChangeLog	Tue Mar 04 18:10:40 2008 +0000
+++ b/ChangeLog	Tue Mar 04 18:12:32 2008 +0000
@@ -29,7 +29,7 @@
 
 	Pidgin:
 	* Added the ability to theme conversation name colors (red and blue)
-	  through your GTK+ theme, and exposed those theme settings to the 
+	  through your GTK+ theme, and exposed those theme settings to the
 	  Pidgin GTK+ Theme Control plugin (Dustin Howett)
 	* Fixed having multiple alias edit areas in the infopane (Elliott Sales
 	  de Andrade)
--- a/Makefile.am	Tue Mar 04 18:10:40 2008 +0000
+++ b/Makefile.am	Tue Mar 04 18:12:32 2008 +0000
@@ -35,9 +35,6 @@
 apps_in_files = pidgin.desktop.in
 apps_DATA = $(apps_in_files:.desktop.in=.desktop)
 @INTLTOOL_DESKTOP_RULE@
-endif
-
-if ENABLE_GTK
 GTK_DIR=pidgin
 endif
 
--- a/doc/pidgin.1.in	Tue Mar 04 18:10:40 2008 +0000
+++ b/doc/pidgin.1.in	Tue Mar 04 18:12:32 2008 +0000
@@ -57,9 +57,9 @@
 \fBOffline\fR.
 .TP
 .B \-l, \-\-login[=\fINAME\fR,\fINAME\fR,...]
-Sign in the comma-separated list of accounts provided, in addition to the
-accounts that would be logged in anyway.  If the user does not specify such a
-comma-separated list, the first account in accounts.xml will be signed in.
+Enable the comma-separated list of accounts provided, disabling all other
+accounts.  If the user does not specify such a comma-separated list, the
+first account in accounts.xml will be enabled.
 .TP
 .B \-v, \-\-version
 Print the current version and exit.
--- a/libpurple/buddyicon.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/buddyicon.c	Tue Mar 04 18:12:32 2008 +0000
@@ -701,6 +701,11 @@
 	}
 	unref_filename(old_icon);
 
+	if (img)
+		g_hash_table_insert(pointer_icon_cache, account, img);
+	else
+		g_hash_table_remove(pointer_icon_cache, account);
+	
 	if (purple_account_is_connected(account))
 	{
 		PurpleConnection *gc;
@@ -724,11 +729,6 @@
 	}
 	g_free(old_icon);
 
-	if (img)
-		g_hash_table_insert(pointer_icon_cache, account, img);
-	else
-		g_hash_table_remove(pointer_icon_cache, account);
-
 	return img;
 }
 
--- a/libpurple/plugin.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/plugin.c	Tue Mar 04 18:12:32 2008 +0000
@@ -924,7 +924,7 @@
 	g_return_val_if_fail(plugin, NULL);
 	g_return_val_if_fail(plugin->info, NULL);
 
-	return plugin->info->name;
+	return _(plugin->info->name);
 }
 
 const gchar *
@@ -940,7 +940,7 @@
 	g_return_val_if_fail(plugin, NULL);
 	g_return_val_if_fail(plugin->info, NULL);
 
-	return plugin->info->summary;
+	return _(plugin->info->summary);
 }
 
 const gchar *
@@ -948,7 +948,7 @@
 	g_return_val_if_fail(plugin, NULL);
 	g_return_val_if_fail(plugin->info, NULL);
 
-	return plugin->info->description;
+	return _(plugin->info->description);
 }
 
 const gchar *
@@ -956,7 +956,7 @@
 	g_return_val_if_fail(plugin, NULL);
 	g_return_val_if_fail(plugin->info, NULL);
 
-	return plugin->info->author;
+	return _(plugin->info->author);
 }
 
 const gchar *
--- a/libpurple/protocols/gg/gg.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/gg/gg.c	Tue Mar 04 18:12:32 2008 +0000
@@ -2088,7 +2088,7 @@
 	OPT_PROTO_REGISTER_NOSCREENNAME,
 	NULL,				/* user_splits */
 	NULL,				/* protocol_options */
-	NO_BUDDY_ICONS,			/* icon_spec */
+	{"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY},	/* icon_spec */
 	ggp_list_icon,			/* list_icon */
 	NULL,				/* list_emblem */
 	ggp_status_text,		/* status_text */
--- a/libpurple/protocols/jabber/Makefile.mingw	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/jabber/Makefile.mingw	Tue Mar 04 18:12:32 2008 +0000
@@ -84,7 +84,6 @@
 
 ifeq ($(CYRUS_SASL), 1)
 CYRUS_SASL_TOP := $(WIN32_DEV_TOP)/cyrus-sasl-2.1.22
-CFLAGS += -DHAVE_CYRUS_SASL
 INCLUDE_PATHS += -I$(CYRUS_SASL_TOP)/include
 LIB_PATHS += -L$(CYRUS_SASL_TOP)/lib
 LIBS += -llibsasl
--- a/libpurple/protocols/msnp9/nexus.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/msnp9/nexus.c	Tue Mar 04 18:12:32 2008 +0000
@@ -321,7 +321,7 @@
 {
 	MsnNexus *nexus;
 	MsnSession *session;
-	char *username, *password;
+	char *username, *password, *encpass;
 	char *request_str, *head, *tail;
 	char *buffer = NULL;
 	guint32 ctint;
@@ -337,8 +337,9 @@
 	username =
 		g_strdup(purple_url_encode(purple_account_get_username(session->account)));
 
-	password =
-		g_strdup(purple_url_encode(purple_connection_get_password(session->account->gc)));
+	password = g_strndup(purple_connection_get_password(session->account->gc), 16);
+	encpass = g_strdup(purple_url_encode(password));
+	g_free(password);
 
 	ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200;
 
@@ -368,7 +369,7 @@
 		nexus->login_host);
 
 	buffer = g_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail);
-	request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, password, tail);
+	request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, encpass, tail);
 
 	purple_debug_misc("msn", "Sending: {%s}\n", buffer);
 
@@ -376,7 +377,7 @@
 	g_free(head);
 	g_free(tail);
 	g_free(username);
-	g_free(password);
+	g_free(encpass);
 
 	nexus->write_buf = request_str;
 	nexus->written_len = 0;
--- a/libpurple/protocols/myspace/markup.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/myspace/markup.c	Tue Mar 04 18:12:32 2008 +0000
@@ -19,7 +19,7 @@
 
 #include "myspace.h"
 
-typedef void (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
+typedef int (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
 
 /* Internal functions */
 
@@ -28,8 +28,8 @@
 static guint msim_height_to_point(MsimSession *session, guint height);
 static guint msim_point_to_height(MsimSession *session, guint point);
 
-static void msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
-static void html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
+static int msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
+static int html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
 static gchar *msim_convert_xml(MsimSession *, const gchar *raw, MSIM_XMLNODE_CONVERT f);
 static gchar *msim_convert_smileys_to_markup(gchar *before);
 static double msim_round(double round);
@@ -396,11 +396,11 @@
 }
 
 /** Convert an individual msim markup tag to HTML. */
-static void 
+static int 
 msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin, 
 		gchar **end)
 {
-	g_return_if_fail(root != NULL);
+	g_return_val_if_fail(root != NULL, 0);
 
 	if (g_str_equal(root->name, "f")) {
 		msim_markup_f_to_html(session, root, begin, end);
@@ -421,13 +421,16 @@
 		*begin = g_strdup("");
 		*end = g_strdup("");
 	}
+	return 0;
 }
 
 /** Convert an individual HTML tag to msim markup. */
-static void 
+static int 
 html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin, 
 		gchar **end)
 {
+	int ret = 0;
+
 	if (!purple_utf8_strcasecmp(root->name, "root") ||
 	    !purple_utf8_strcasecmp(root->name, "html")) {
 		*begin = g_strdup("");
@@ -437,11 +440,39 @@
 	 * within another one, and only the inner-most formatting will be 
 	 * applied to the text. */
 	} else if (!purple_utf8_strcasecmp(root->name, "b")) {
-		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
-		*end = g_strdup("</f>");
+		if (root->child->type == XMLNODE_TYPE_DATA) {
+			*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
+			*end = g_strdup("</f>");
+		} else {
+			if (!purple_utf8_strcasecmp(root->child->name,"i")) {
+				ret++;
+				if (root->child->child->type == XMLNODE_TYPE_DATA) {
+					*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC));
+					*end = g_strdup("</f>");
+				} else {
+					if (!purple_utf8_strcasecmp(root->child->child->name,"u")) {
+						ret++;
+						*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
+						*end = g_strdup("</f>");
+					}
+				}
+			} else if (!purple_utf8_strcasecmp(root->child->name,"u")) {
+				ret++;
+				*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_UNDERLINE));
+				*end = g_strdup("</f>");
+			}
+		}
 	} else if (!purple_utf8_strcasecmp(root->name, "i")) {
-		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
-		*end = g_strdup("</f>");
+		if (root->child->type == XMLNODE_TYPE_DATA) {
+			*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
+			*end = g_strdup("</f>");
+		} else {
+			if (!purple_utf8_strcasecmp(root->child->name,"u")) {
+				ret++;
+				*begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
+				*end = g_strdup("</f>");
+			}
+		}
 	} else if (!purple_utf8_strcasecmp(root->name, "u")) {
 		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
 		*end = g_strdup("</f>");
@@ -524,6 +555,7 @@
 		msim_unrecognized(NULL, NULL, err);
 		g_free(err);
 	}
+	return ret;
 }
 
 /** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
@@ -533,11 +565,12 @@
  * @return An HTML string. Caller frees.
  */
 static gchar *
-msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f)
+msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f, int nodes_processed)
 {
 	xmlnode *node;
 	gchar *begin, *inner, *end;
 	GString *final;
+	int descended = nodes_processed;
 
 	if (!root || !root->name) {
 		return g_strdup("");
@@ -550,36 +583,37 @@
 
 	final = g_string_new("");
 
-	f(session, root, &begin, &end);
+	if (descended == 0) /* We've not formatted this yet.. :) */
+		descended = f(session, root, &begin, &end); /* Get the value that our format function has already descended for us */
 	
 	g_string_append(final, begin);
 
 	/* Loop over all child nodes. */
 	for (node = root->child; node != NULL; node = node->next) {
 		switch (node->type) {
-		case XMLNODE_TYPE_ATTRIB:
-			/* Attributes handled above. */
-			break;
-
-		case XMLNODE_TYPE_TAG:
-			/* A tag or tag with attributes. Recursively descend. */
-			inner = msim_convert_xmlnode(session, node, f);
-			g_return_val_if_fail(inner != NULL, NULL);
+			case XMLNODE_TYPE_ATTRIB:
+				/* Attributes handled above. */
+				break;
 
-			purple_debug_info("msim", " ** node name=%s\n", 
-					(node && node->name) ? node->name : "(NULL)");
-			break;
-	
-		case XMLNODE_TYPE_DATA:
-			/* Literal text. */
-			inner = g_strndup(node->data, node->data_sz);
-			purple_debug_info("msim", " ** node data=%s\n", 
-					inner ? inner : "(NULL)");
-			break;
-			
-		default:
-			purple_debug_info("msim",
-					"msim_convert_xmlnode: strange node\n");
+			case XMLNODE_TYPE_TAG:
+				/* A tag or tag with attributes. Recursively descend. */
+				inner = msim_convert_xmlnode(session, node, f, descended);
+				g_return_val_if_fail(inner != NULL, NULL);
+		
+				purple_debug_info("msim", " ** node name=%s\n", 
+						(node && node->name) ? node->name : "(NULL)");
+				break;
+		
+			case XMLNODE_TYPE_DATA:
+				/* Literal text. */
+				inner = g_strndup(node->data, node->data_sz);
+				purple_debug_info("msim", " ** node data=%s\n", 
+						inner ? inner : "(NULL)");
+				break;
+		
+			default:
+				purple_debug_info("msim",
+						"msim_convert_xmlnode: strange node\n");
 		}
 
 		if (inner) {
@@ -629,7 +663,7 @@
 
 	g_free(enclosed_raw);
 
-	str = msim_convert_xmlnode(session, root, f);
+	str = msim_convert_xmlnode(session, root, f, 0);
 	g_return_val_if_fail(str != NULL, NULL);
 	purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str);
 
--- a/libpurple/protocols/oscar/family_icbm.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Tue Mar 04 18:12:32 2008 +0000
@@ -2371,6 +2371,181 @@
 	return 0;
 }
 
+static void parse_status_note_text(OscarData *od, guchar *cookie, char *sn, ByteStream *bs)
+{
+	struct aim_icq_info *info;
+	struct aim_icq_info *prev_info;
+	char *response;
+	char *encoding;
+	char *stripped_encoding;
+	char *status_note_title;
+	char *status_note_text;
+	char *stripped_status_note_text;
+	char *status_note;
+	guint32 length;
+	guint16 version;
+	guint32 capability;
+	guint8 message_type;
+	guint16 status_code;
+	guint16 text_length;
+	guint32 request_length;
+	guint32 response_length;
+	guint32 encoding_length;
+	PurpleAccount *account;
+	PurpleBuddy *buddy;
+	PurplePresence *presence;
+	PurpleStatus *status;
+
+	for (prev_info = NULL, info = od->icq_info; info != NULL; prev_info = info, info = info->next)
+	{
+		if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
+		{
+			if (prev_info == NULL)
+				od->icq_info = info->next;
+			else
+				prev_info->next = info->next;
+
+			break;
+		}
+	}
+
+	if (info == NULL)
+		return;
+
+	status_note_title = info->status_note_title;
+	g_free(info);
+
+	length = byte_stream_getle16(bs);
+	if (length != 27) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect header "
+				"size; expected 27, received %u.\n", length);
+		g_free(status_note_title);
+		return;
+	}
+
+	version = byte_stream_getle16(bs);
+	if (version != 9) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect version; "
+				"expected 9, received %u.\n", version);
+		g_free(status_note_title);
+		return;
+	}
+
+	capability = aim_locate_getcaps(od, bs, 0x10);
+	if (capability != OSCAR_CAPABILITY_EMPTY) {
+		purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
+		g_free(status_note_title);
+		return;
+	}
+
+	byte_stream_advance(bs, 2); /* unknown */
+	byte_stream_advance(bs, 4); /* client capabilities flags */
+	byte_stream_advance(bs, 1); /* unknown */
+	byte_stream_advance(bs, 2); /* downcouner? */
+
+	length = byte_stream_getle16(bs);
+	if (length != 14) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect header "
+				"size; expected 14, received %u.\n", length);
+		g_free(status_note_title);
+		return;
+	}
+
+	byte_stream_advance(bs, 2); /* downcounter? */
+	byte_stream_advance(bs, 12); /* unknown */
+
+	message_type = byte_stream_get8(bs);
+	if (message_type != 0x1a) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect message "
+				"type; expected 0x1a, received 0x%x.\n", message_type);
+		g_free(status_note_title);
+		return;
+	}
+
+	byte_stream_advance(bs, 1); /* message flags */
+
+	status_code = byte_stream_getle16(bs);
+	if (status_code != 0) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect status "
+				"code; expected 0, received %u.\n", status_code);
+		g_free(status_note_title);
+		return;
+	}
+
+	byte_stream_advance(bs, 2); /* priority code */
+
+	text_length = byte_stream_getle16(bs);
+	byte_stream_advance(bs, text_length); /* text */
+
+	length = byte_stream_getle16(bs);
+	byte_stream_advance(bs, 18); /* unknown */
+
+	request_length = byte_stream_getle32(bs);
+	if (length != 18 + 4 + request_length + 17) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect block; "
+				"expected length is %u, got %u.\n",
+				18 + 4 + request_length + 17, length);
+		g_free(status_note_title);
+		return;
+	}
+
+	byte_stream_advance(bs, request_length); /* x request */
+	byte_stream_advance(bs, 17); /* unknown */
+
+	length = byte_stream_getle32(bs);
+	response_length = byte_stream_getle32(bs);
+	response = byte_stream_getstr(bs, response_length);
+	encoding_length = byte_stream_getle32(bs);
+	if (length != 4 + response_length + 4 + encoding_length) {
+		purple_debug_misc("oscar", "clientautoresp: incorrect block; "
+				"expected length is %u, got %u.\n",
+				4 + response_length + 4 + encoding_length, length);
+		g_free(status_note_title);
+		g_free(response);
+		return;
+	}
+
+	encoding = byte_stream_getstr(bs, encoding_length);
+
+	account = purple_connection_get_account(od->gc);
+
+	stripped_encoding = oscar_encoding_extract(encoding);
+	status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
+	stripped_status_note_text = purple_markup_strip_html(status_note_text);
+
+	if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
+		status_note = g_strdup_printf("%s: %s", status_note_title, stripped_status_note_text);
+	else
+		status_note = g_strdup(status_note_title);
+
+	g_free(status_note_title);
+	g_free(response);
+	g_free(encoding);
+	g_free(stripped_encoding);
+	g_free(status_note_text);
+	g_free(stripped_status_note_text);
+
+	buddy = purple_find_buddy(account, sn);
+	if (buddy == NULL)
+	{
+		purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
+		g_free(status_note);
+		return;
+	}
+
+	purple_debug_misc("oscar", "clientautoresp: setting status "
+			"message to \"%s\".\n", status_note);
+
+	presence = purple_buddy_get_presence(buddy);
+	status = purple_presence_get_active_status(presence);
+
+	purple_prpl_got_user_status(account, sn,
+			purple_status_get_id(status),
+			"message", status_note, NULL);
+
+	g_free(status_note);
+}
+
 /*
  * Subtype 0x000b - Receive the response from an ICQ status message
  * request (in which case this contains the ICQ status message) or
@@ -2393,158 +2568,9 @@
 
 	if (channel == 0x0002)
 	{
-		/* parse status note text */
-
-		struct aim_icq_info *info = NULL;
-		struct aim_icq_info *prev_info = NULL;
-		char *response = NULL;
-		char *encoding = NULL;
-		char *stripped_encoding = NULL;
-		char *status_note_text = NULL;
-		char *stripped_status_note_text = NULL;
-		char *status_note = NULL;
-
-		/*
-		 * TODO: Using a while statement here is kind of an ugly hack
-		 *       to be able to use 'break'.  We might as well be using
-		 *       'goto'.  Should probably get rid of this.
-		 */
-		while (reason == 0x0003) /* channel-specific */
-		{
-			guint32 length;
-			guint16 version;
-			guint32 capability;
-			guint8 message_type;
-			guint16 status_code;
-			guint16 text_length;
-			guint32 request_length;
-			guint32 response_length;
-			guint32 encoding_length;
-			PurpleAccount *account;
-			PurpleBuddy *buddy;
-			PurplePresence *presence;
-			PurpleStatus *status;
-
-			for (info = od->icq_info; info != NULL; info = info->next)
-			{
-				if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
-				{
-					if (prev_info == NULL)
-						od->icq_info = info->next;
-					else
-						prev_info->next = info->next;
-
-					break;
-				}
-
-				prev_info = info;
-			}
-
-			if (info == NULL)
-				break;
-
-			if ((length = byte_stream_getle16(bs)) != 27)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 27, received %u.\n", length);
-				break;
-			}
-			if ((version = byte_stream_getle16(bs)) != 9)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect version; expected 9, received %u.\n", version);
-				break;
-			}
-			capability = aim_locate_getcaps(od, bs, 0x10);
-			if (capability != OSCAR_CAPABILITY_EMPTY)
-			{
-				purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
-				break;
-			}
-			byte_stream_advance(bs, 2); /* unknown */
-			byte_stream_advance(bs, 4); /* client capabilities flags */
-			byte_stream_advance(bs, 1); /* unknown */
-			byte_stream_advance(bs, 2); /* downcouner? */
-
-			if ((length = byte_stream_getle16(bs)) != 14)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 14, received %u.\n", length);
-				break;
-			}
-			byte_stream_advance(bs, 2); /* downcounter? */
-			byte_stream_advance(bs, 12); /* unknown */
-
-			if ((message_type = byte_stream_get8(bs)) != 0x1a)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect message type; expected 0x1a, received 0x%x.\n", message_type);
-				break;
-			}
-			byte_stream_advance(bs, 1); /* message flags */
-			if ((status_code = byte_stream_getle16(bs)) != 0)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect status code; expected 0, received %u.\n", status_code);
-				break;
-			}
-			byte_stream_advance(bs, 2); /* priority code */
-
-			text_length = byte_stream_getle16(bs);
-			byte_stream_advance(bs, text_length); /* text */
-
-			length = byte_stream_getle16(bs);
-			byte_stream_advance(bs, 18); /* unknown */
-			if (length != 18 + 4 + (request_length = byte_stream_getle32(bs)) + 17)
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 18 + 4 + request_length + 17, length);
-				break;
-			}
-			byte_stream_advance(bs, request_length); /* x request */
-			byte_stream_advance(bs, 17); /* unknown */
-
-			length = byte_stream_getle32(bs);
-			response_length = byte_stream_getle32(bs);
-			response = byte_stream_getstr(bs, response_length);
-			if (length != 4 + response_length + 4 + (encoding_length = byte_stream_getle32(bs)))
-			{
-				purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 4 + response_length + 4 + encoding_length, length);
-				break;
-			}
-			encoding = byte_stream_getstr(bs, encoding_length);
-
-			account = purple_connection_get_account(od->gc);
-			stripped_encoding = oscar_encoding_extract(encoding);
-			status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
-			stripped_status_note_text = purple_markup_strip_html(status_note_text);
-
-			if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
-				status_note = g_strdup_printf("%s: %s", info->status_note_title, stripped_status_note_text);
-			else
-				status_note = g_strdup(info->status_note_title);
-
-			buddy = purple_find_buddy(account, sn);
-			if (buddy == NULL)
-			{
-				purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
-				break;
-			}
-
-			purple_debug_misc("oscar", "clientautoresp: setting status message to \"%s\".\n", status_note);
-
-			presence = purple_buddy_get_presence(buddy);
-			status = purple_presence_get_active_status(presence);
-
-			purple_prpl_got_user_status(account, sn,
-					purple_status_get_id(status),
-					"message", status_note, NULL);
-
-			break;
-		}
-
-		g_free(status_note);
-		g_free(stripped_status_note_text);
-		g_free(status_note_text);
-		g_free(stripped_encoding);
-		g_free(encoding);
-		g_free(response);
-		g_free(info->status_note_title);
-		g_free(info);
+		if (reason == 0x0003) /* channel-specific */
+			/* parse status note text */
+			parse_status_note_text(od, cookie, sn, bs);
 
 		byte_stream_get16(bs); /* Unknown */
 		byte_stream_get16(bs); /* Unknown */
--- a/libpurple/protocols/oscar/oscar.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue Mar 04 18:12:32 2008 +0000
@@ -202,7 +202,7 @@
 void oscar_set_info(PurpleConnection *gc, const char *info);
 static void oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, PurpleStatus *status);
 static void oscar_set_extendedstatus(PurpleConnection *gc);
-static void oscar_format_screenname(PurpleConnection *gc, const char *nick); 
+static void oscar_format_screenname(PurpleConnection *gc, const char *nick);
 static gboolean purple_ssi_rerequestdata(gpointer data);
 
 static void oscar_free_name_data(struct name_data *data) {
@@ -1061,8 +1061,8 @@
 	if (conn->type == SNAC_FAMILY_AUTH)
 	{
 		aim_request_login(od, conn, purple_account_get_username(account));
-		purple_debug_info("oscar", "Screen name sent, waiting for response\n");
-		purple_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS);
+		purple_debug_info("oscar", "Username sent, waiting for response\n");
+		purple_connection_update_progress(gc, _("Username sent"), 1, OSCAR_CONNECT_STEPS);
 		ck[1] = 0x65;
 	}
 	else if (conn->type == SNAC_FAMILY_LOCATE)
@@ -1324,7 +1324,7 @@
 
 	if (!aim_snvalid(purple_account_get_username(account))) {
 		gchar *buf;
-		buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid.  Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
+		buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the username is invalid.  Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
 		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf);
 		g_free(buf);
 		return;
@@ -1403,14 +1403,14 @@
 	va_end(ap);
 
 	purple_debug_info("oscar",
-			   "inside auth_resp (Screen name: %s)\n", info->sn);
+			   "inside auth_resp (Username: %s)\n", info->sn);
 
 	if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) {
 		char buf[256];
 		switch (info->errorcode) {
 		case 0x01:
 			/* Unregistered screen name */
-			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Invalid screen name."));
+			purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Invalid username."));
 			break;
 		case 0x05:
 			/* Incorrect password */
@@ -2979,7 +2979,7 @@
 	va_end(ap);
 
 	user_info = purple_notify_user_info_new();
-	purple_notify_user_info_add_pair(user_info, _("Screen Name"), userinfo->sn);
+	purple_notify_user_info_add_pair(user_info, _("Username"), userinfo->sn);
 
 	tmp = g_strdup_printf("%d", (int)((userinfo->warnlevel/10.0) + 0.5));
 	purple_notify_user_info_add_pair(user_info, _("Warning Level"), tmp);
@@ -3967,12 +3967,12 @@
 	gchar *secondary;
 	int i, num;
 	va_list ap;
-	char *email, *SNs;
+	char *email, *usernames;
 
 	va_start(ap, fr);
 	email = va_arg(ap, char *);
 	num = va_arg(ap, int);
-	SNs = va_arg(ap, char *);
+	usernames = va_arg(ap, char *);
 	va_end(ap);
 
 	results = purple_notify_searchresults_new();
@@ -3987,17 +3987,17 @@
 	}
 
 	secondary = g_strdup_printf(
-					dngettext(PACKAGE, "The following screen name is associated with %s",
-						 "The following screen names are associated with %s",
+					dngettext(PACKAGE, "The following username is associated with %s",
+						 "The following usernames are associated with %s",
 						 num),
 					email);
 
-	column = purple_notify_searchresults_column_new(_("Screen name"));
+	column = purple_notify_searchresults_column_new(_("Username"));
 	purple_notify_searchresults_column_add(results, column);
 
 	for (i = 0; i < num; i++) {
-		GList *row = NULL;
-		row = g_list_append(row, g_strdup(&SNs[i * (MAXSNLEN + 1)]));
+		GList *row;
+		row = g_list_append(NULL, g_strdup(&usernames[i * (MAXSNLEN + 1)]));
 		purple_notify_searchresults_row_add(results, row);
 	}
 	purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD,
@@ -4072,32 +4072,23 @@
 
 	if ((err > 0) && (url != NULL)) {
 		char *dialog_msg;
-		char *dialog_top = g_strdup_printf(_("Error Changing Account Info"));
-		switch (err) {
-			case 0x0001: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name differs from the original."), err);
-			} break;
-			case 0x0006: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because it is invalid."), err);
-			} break;
-			case 0x000b: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name is too long."), err);
-			} break;
-			case 0x001d: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because there is already a request pending for this screen name."), err);
-			} break;
-			case 0x0021: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because the given address has too many screen names associated with it."), err);
-			} break;
-			case 0x0023: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because the given address is invalid."), err);
-			} break;
-			default: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unknown error."), err);
-			} break;
-		}
-		purple_notify_error(gc, NULL, dialog_top, dialog_msg);
-		g_free(dialog_top);
+
+		if (err == 0x0001)
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because the requested name differs from the original."), err);
+		else if (err == 0x0006)
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because it is invalid."), err);
+		else if (err == 0x00b)
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because the requested name is too long."), err);
+		else if (err == 0x001d)
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because there is already a request pending for this username."), err);
+		else if (err == 0x0021)
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because the given address has too many usernames associated with it."), err);
+		else if (err == 0x0023)
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because the given address is invalid."), err);
+		else
+			dialog_msg = g_strdup_printf(_("Error 0x%04x: Unknown error."), err);
+		purple_notify_error(gc, NULL,
+				_("Error Changing Account Info"), dialog_msg);
 		g_free(dialog_msg);
 		return 1;
 	}
@@ -4541,7 +4532,6 @@
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
 	OscarData *od = gc->proto_data;
-	PurplePresence *presence;
 	PurpleStatusType *status_type;
 	PurpleStatusPrimitive primitive;
 
@@ -4557,7 +4547,6 @@
 
 	status_type = purple_status_get_type(status);
 	primitive = purple_status_type_get_primitive(status_type);
-	presence = purple_account_get_presence(account);
 
 	if (!setinfo)
 	{
@@ -4707,7 +4696,7 @@
 
 	if (!aim_snvalid(buddy->name)) {
 		gchar *buf;
-		buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid.  Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name);
+		buf = g_strdup_printf(_("Could not add the buddy %s because the username is invalid.  Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name);
 		if (!purple_conv_present_error(buddy->name, account, buf))
 			purple_notify_error(gc, NULL, _("Unable To Add"), buf);
 		g_free(buf);
@@ -6259,7 +6248,7 @@
 		}
 	} else {
 		purple_notify_error(gc, NULL, _("The new formatting is invalid."),
-						  _("Screen name formatting can change only capitalization and whitespace."));
+						  _("Username formatting can change only capitalization and whitespace."));
 	}
 }
 
@@ -6658,7 +6647,7 @@
 	g_return_val_if_fail(str != NULL, NULL);
 
 	/* copy str to buf and skip all blanks */
-	for (i=0, j=0; str[j] && i < BUF_LEN; i++, j++)
+	for (i=0, j=0; str[j] && i < BUF_LEN - 1; i++, j++)
 	{
 		while (str[j] == ' ')
 			j++;
@@ -6678,18 +6667,7 @@
 gboolean
 oscar_offline_message(const PurpleBuddy *buddy)
 {
-	OscarData *od = NULL;
-	PurpleAccount *account;
-	PurpleConnection *gc = NULL;
-
-	account = purple_buddy_get_account(buddy);
-	if (account != NULL) {
-		gc = purple_account_get_connection(account);
-		if (gc != NULL)
-			od = (OscarData *)gc->proto_data;
-	}
-
-	return (od != NULL && od->icq && aim_snvalid_icq(purple_account_get_username(account)));
+	return TRUE;
 }
 
 /* TODO: Find somewhere to put this instead of including it in a bunch of places.
--- a/libpurple/protocols/zephyr/zephyr.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Tue Mar 04 18:12:32 2008 +0000
@@ -2235,6 +2235,9 @@
 	char *tmp;
 
 	gc = purple_account_get_connection(account);
+	if (gc == NULL)
+		return NULL;
+
 	tmp = local_zephyr_normalize(gc->proto_data, who);
 
 	if (strlen(tmp) >= sizeof(buf)) {
--- a/libpurple/win32/global.mak	Tue Mar 04 18:10:40 2008 +0000
+++ b/libpurple/win32/global.mak	Tue Mar 04 18:12:32 2008 +0000
@@ -79,6 +79,10 @@
 
 CYRUS_SASL ?= 1
 
+ifeq ($(CYRUS_SASL), 1)
+DEFINES += -DHAVE_CYRUS_SASL
+endif
+
 DEFINES += -DHAVE_CONFIG_H
 
 # Use -g flag when building debug version of Pidgin (including plugins).
--- a/pidgin/gtkmain.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/pidgin/gtkmain.c	Tue Mar 04 18:12:32 2008 +0000
@@ -408,8 +408,9 @@
 		       "  -h, --help          display this help and exit\n"
 		       "  -m, --multiple      do not ensure single instance\n"
 		       "  -n, --nologin       don't automatically login\n"
-		       "  -l, --login[=NAME]  automatically login (optional argument NAME specifies\n"
-		       "                      account(s) to use, separated by commas)\n"
+		       "  -l, --login[=NAME]  enable specified account(s) (optional argument NAME\n"
+		       "                      specifies account(s) to use, separated by commas.\n"
+		       "                      Without this only the first account will be enabled).\n"
 		       "  --display=DISPLAY   X display to use\n"
 		       "  -v, --version       display the current version and exit\n"), PIDGIN_NAME, DISPLAY_VERSION, name);
 #else
@@ -420,8 +421,9 @@
 		       "  -h, --help          display this help and exit\n"
 		       "  -m, --multiple      do not ensure single instance\n"
 		       "  -n, --nologin       don't automatically login\n"
-		       "  -l, --login[=NAME]  automatically login (optional argument NAME specifies\n"
-		       "                      account(s) to use, separated by commas)\n"
+		       "  -l, --login[=NAME]  enable specified account(s) (optional argument NAME\n"
+		       "                      specifies account(s) to use, separated by commas.\n"
+		       "                      Without this only the first account will be enabled).\n"
 		       "  -v, --version       display the current version and exit\n"), PIDGIN_NAME, DISPLAY_VERSION, name);
 #endif
 	}
@@ -478,6 +480,7 @@
 	gboolean opt_help = FALSE;
 	gboolean opt_login = FALSE;
 	gboolean opt_nologin = FALSE;
+	gboolean opt_nocrash = FALSE;
 	gboolean opt_version = FALSE;
 	gboolean opt_si = TRUE;     /* Check for single instance? */
 	char *opt_config_dir_arg = NULL;
@@ -508,6 +511,7 @@
 		{"login",    optional_argument, NULL, 'l'},
 		{"multiple", no_argument,       NULL, 'm'},
 		{"nologin",  no_argument,       NULL, 'n'},
+		{"nocrash",  no_argument,       NULL, 'x'},
 		{"session",  required_argument, NULL, 's'},
 		{"version",  no_argument,       NULL, 'v'},
 		{"display",  required_argument, NULL, 'D'},
@@ -657,6 +661,9 @@
 		case 'm':   /* do not ensure single instance. */
 			opt_si = FALSE;
 			break;
+		case 'x':   /* --nocrash */
+			opt_nocrash = TRUE;
+			break;
 		case 'D':   /* --display */
 		case 'S':   /* --sync */
 			/* handled by gtk_init_check below */
--- a/pidgin/gtkplugin.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/pidgin/gtkplugin.c	Tue Mar 04 18:12:32 2008 +0000
@@ -559,10 +559,10 @@
 
 	gtk_tree_model_get(model, &iter, 2, &plugin, -1);
 
-	markup = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>\n<b>Description:</b> %s\n<b>Author:</b> %s",
+	markup = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>\n<b>%s:</b> %s\n<b>%s:</b> %s",
 			name = g_markup_escape_text(purple_plugin_get_name(plugin), -1),
-			desc = g_markup_escape_text(purple_plugin_get_description(plugin), -1),
-			author = g_markup_escape_text(purple_plugin_get_author(plugin), -1));
+			_("Description"), desc = g_markup_escape_text(purple_plugin_get_description(plugin), -1),
+			_("Author"), author = g_markup_escape_text(purple_plugin_get_author(plugin), -1));
 
 	layout = gtk_widget_create_pango_layout(tipwindow, NULL);
 	pango_layout_set_markup(layout, markup, -1);
--- a/pidgin/plugins/notify.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/pidgin/plugins/notify.c	Tue Mar 04 18:12:32 2008 +0000
@@ -842,8 +842,6 @@
 	                    PURPLE_CALLBACK(chat_sent_im), NULL);
 	purple_signal_connect(conv_handle, "conversation-created", plugin,
 	                    PURPLE_CALLBACK(conv_created), NULL);
-	purple_signal_connect(conv_handle, "chat-joined", plugin,
-	                    PURPLE_CALLBACK(conv_created), NULL);
 	purple_signal_connect(conv_handle, "deleting-conversation", plugin,
 	                    PURPLE_CALLBACK(deleting_conv), NULL);
 #if 0
--- a/pidgin/win32/winpidgin.c	Tue Mar 04 18:10:40 2008 +0000
+++ b/pidgin/win32/winpidgin.c	Tue Mar 04 18:12:32 2008 +0000
@@ -456,7 +456,7 @@
 
 				printf("An instance of Pidgin is already running.\n");
 
-				if((msg_win = FindWindowEx(HWND_MESSAGE, NULL, TEXT("WinpidginMsgWinCls"), NULL)))
+				if((msg_win = FindWindowEx(NULL, NULL, TEXT("WinpidginMsgWinCls"), NULL)))
 					if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL))
 						return FALSE;