changeset 25696:6f1bd5f3aaa0

propagate from branch 'im.pidgin.pidgin' (head 3da4a61feea56ff40dc5fdba355a1057c675a32d) to branch 'im.pidgin.cpw.malu.xmpp.idle' (head fabd9ad23e9fb900097d73b3de731f9464c1211a)
author Marcus Lundblad <ml@update.uu.se>
date Fri, 06 Feb 2009 22:46:24 +0000
parents 8f5a63aebdb6 (diff) e3f2b16f75da (current diff)
children 8202f850ca9e
files libpurple/protocols/jabber/jabber.c
diffstat 28 files changed, 137 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Feb 06 22:45:52 2009 +0000
+++ b/ChangeLog	Fri Feb 06 22:46:24 2009 +0000
@@ -6,11 +6,16 @@
 	* Beta support for SSL connections for AIM and ICQ accounts.  To
 	  enable, check the "Use SSL" option from the Advanced tab when
 	  editing your AIM or ICQ account. (Paul Aurich)
-	* Fix retrieval of ICQ status messages from users of ICQ 6.x, Miranda,
-	  and other libpurple clients (fixes with libpurple users only on
-	  statuses other than Available). (Daniel Ljungborg)
 	* Fix a memory leak in SILC. (Luke Petre)
 
+	ICQ:
+	* Fix retrieval of status messages from users of ICQ 6.x, Miranda, and
+	  other libpurple clients. (Daniel Ljungborg)
+	* Change client ID to match ICQ Basic 14.34.3096.  This fixes publishing
+	  of buddy icons and available messages.
+	* Properly publish status messages for statuses other than Available.
+	  ICQ 6.x users can now see these status messages. (Daniel Ljungborg)
+
 	MSN:
 	* Fix transfer of buddy icons, custom smileys, and files from the
 	  latest Windows Live Messenger 9 official client. (Thomas
--- a/ChangeLog.API	Fri Feb 06 22:45:52 2009 +0000
+++ b/ChangeLog.API	Fri Feb 06 22:46:24 2009 +0000
@@ -6,6 +6,8 @@
 		* purple_status_type_new now defaults "saveable" to TRUE.
 		  This was necessary in order to maintain the current behavior
 		  while fixing non-saveable statuses not to be saved.
+		* xmlnode_get_prefix, xmlnode_to_str and xmlnode_to_formatted_str
+		  now all take a const xmlnode* instead of an xmlnode*
 
 version 2.5.4 (01/12/2009):
 	perl:
--- a/finch/finch.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/finch/finch.c	Fri Feb 06 22:46:24 2009 +0000
@@ -210,7 +210,7 @@
 		text = g_strdup_printf(_("%s\n"
 		       "Usage: %s [OPTION]...\n\n"
 		       "  -c, --config=DIR    use DIR for config files\n"
-		       "  -d, --debug         print debugging messages to stdout\n"
+		       "  -d, --debug         print debugging messages to stderr\n"
 		       "  -h, --help          display this help and exit\n"
 		       "  -n, --nologin       don't automatically login\n"
 		       "  -v, --version       display the current version and exit\n"), DISPLAY_VERSION, name);
--- a/finch/libgnt/gntkeys.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/finch/libgnt/gntkeys.c	Fri Feb 06 22:46:24 2009 +0000
@@ -163,7 +163,8 @@
 			(*(text + 2) >= 'A' && *(text + 2) <= 'D')) {
 		/* Apparently this is necessary for urxvt and screen and xterm */
 		if (strstr(term, "screen") == term || strcmp(term, "rxvt-unicode") == 0 ||
-				strstr(term, "xterm") == term)
+				strstr(term, "xterm") == term ||
+				strstr(term, "vt100") == term)
 			*(text + 1) = 'O';
 	} else if (*(unsigned char*)text == 195) {
 		if (*(text + 2) == 0 && strstr(term, "xterm") == term) {
--- a/libpurple/dbus-analyze-functions.py	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/dbus-analyze-functions.py	Fri Feb 06 22:46:24 2009 +0000
@@ -497,7 +497,7 @@
         # This is a total hack, but self.call is set up before the parameters
         #  are processed, so we can't tell it to pass a parameter by reference.
         self.call = "%s(%s)" % (self.function.name,
-                                ", ".join(param.name if param.name != "len" else "&len" for param in self.params))
+                                ", ".join([(param.name, "&len")[param.name == "len"] for param in self.params]))
 
         self.cdecls.append("\tgconstpointer %s;" % name)
         self.ccode.append("\t%s = %s;" % (name, self.call))
--- a/libpurple/protocols/jabber/data.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/data.c	Fri Feb 06 22:46:24 2009 +0000
@@ -200,11 +200,9 @@
 }
 
 void
-jabber_data_parse(JabberStream *js, xmlnode *packet)
+jabber_data_parse(JabberStream *js, xmlnode *data_node, const char *who, const char *id)
 {
 	JabberIq *result = NULL;
-	const char *who = xmlnode_get_attrib(packet, "from");
-	xmlnode *data_node = xmlnode_get_child(packet, "data");
 	const JabberData *data =
 		jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid"));
 
@@ -213,12 +211,12 @@
 
 		result = jabber_iq_new(js, JABBER_IQ_ERROR);
 		xmlnode_set_attrib(result->node, "to", who);
-		xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
+		xmlnode_set_attrib(result->node, "id", id);
 		xmlnode_insert_child(result->node, item_not_found);
 	} else {
 		result = jabber_iq_new(js, JABBER_IQ_RESULT);
 		xmlnode_set_attrib(result->node, "to", who);
-		xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
+		xmlnode_set_attrib(result->node, "id", id);
 		xmlnode_insert_child(result->node,
 							 jabber_data_get_xml_definition(data));
 	}
--- a/libpurple/protocols/jabber/data.h	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/data.h	Fri Feb 06 22:46:24 2009 +0000
@@ -65,7 +65,8 @@
 void jabber_data_associate_remote(JabberData *data);
 
 /* handles iq requests */
-void jabber_data_parse(JabberStream *js, xmlnode *packet);
+void jabber_data_parse(JabberStream *js, xmlnode *data_node,
+                       const char *who, const char *id);
 
 void jabber_data_init(void);
 void jabber_data_uninit(void);
--- a/libpurple/protocols/jabber/google.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/google.c	Fri Feb 06 22:46:24 2009 +0000
@@ -144,9 +144,8 @@
 }
 
 void
-jabber_gmail_poke(JabberStream *js, xmlnode *packet)
+jabber_gmail_poke(JabberStream *js, const char *type)
 {
-	const char *type;
 	xmlnode *query;
 	JabberIq *iq;
 
@@ -154,11 +153,8 @@
 	if (!purple_account_get_check_mail(js->gc->account))
 		return;
 
-	type = xmlnode_get_attrib(packet, "type");
-
-
 	/* Is this an initial incoming mail notification? If so, send a request for more info */
-	if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail"))
+	if (strcmp(type, "set"))
 		return;
 
 	purple_debug(PURPLE_DEBUG_MISC, "jabber",
--- a/libpurple/protocols/jabber/google.h	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/google.h	Fri Feb 06 22:46:24 2009 +0000
@@ -27,7 +27,7 @@
 #include "jabber.h"
 
 void jabber_gmail_init(JabberStream *js);
-void jabber_gmail_poke(JabberStream *js, xmlnode *node);
+void jabber_gmail_poke(JabberStream *js, const char *type);
 
 void jabber_google_roster_init(JabberStream *js);
 void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item);
--- a/libpurple/protocols/jabber/iq.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/iq.c	Fri Feb 06 22:46:24 2009 +0000
@@ -309,7 +309,7 @@
 void jabber_iq_parse(JabberStream *js, xmlnode *packet)
 {
 	JabberCallbackData *jcd;
-	xmlnode *query, *error, *x;
+	xmlnode *child, *query, *error, *x;
 	const char *xmlns;
 	const char *type, *id, *from;
 	JabberIqHandler *jih;
@@ -371,25 +371,25 @@
 		}
 	}
 
-	if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) {
-		jabber_si_parse(js, packet);
+	if ((child = xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si"))) {
+		jabber_si_parse(js, child, from, id);
 		return;
 	}
 
-	if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) {
-		jabber_gmail_poke(js, packet);
+	if (xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) {
+		jabber_gmail_poke(js, type);
 		return;
 	}
 
 	purple_debug_info("jabber", "jabber_iq_parse\n");
 
-	if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) {
-		jabber_ping_parse(js, packet);
+	if (xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) {
+		jabber_ping_parse(js, from, id);
 		return;
 	}
 
-	if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) {
-		jabber_data_parse(js, packet);
+	if ((child = xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE))) {
+		jabber_data_parse(js, child, from, id);
 		return;
 	}
 
--- a/libpurple/protocols/jabber/jabber.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Fri Feb 06 22:46:24 2009 +0000
@@ -1909,7 +1909,7 @@
 
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE,
 			jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE),
-			NULL, FALSE, TRUE, FALSE,
+			NULL, TRUE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
 	types = g_list_append(types, type);
--- a/libpurple/protocols/jabber/ping.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/ping.c	Fri Feb 06 22:46:24 2009 +0000
@@ -30,7 +30,7 @@
 #include "iq.h"
 
 void
-jabber_ping_parse(JabberStream *js, xmlnode *packet)
+jabber_ping_parse(JabberStream *js, const char *from, const char *id)
 {
 	JabberIq *iq;
 
@@ -38,9 +38,9 @@
 
 	iq = jabber_iq_new(js, JABBER_IQ_RESULT);
 
-	xmlnode_set_attrib(iq->node, "to", xmlnode_get_attrib(packet, "from") );
+	xmlnode_set_attrib(iq->node, "to", from);
 
-	jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id"));
+	jabber_iq_set_id(iq, id);
 
 	jabber_iq_send(iq);
 }
--- a/libpurple/protocols/jabber/ping.h	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/ping.h	Fri Feb 06 22:46:24 2009 +0000
@@ -26,7 +26,8 @@
 #include "conversation.h"
 
 void jabber_ping_parse(JabberStream *js,
-						xmlnode *packet);
+                       const char *from,
+                       const char *id);
 
 
 gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid);
--- a/libpurple/protocols/jabber/si.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/si.c	Fri Feb 06 22:46:24 2009 +0000
@@ -1182,17 +1182,14 @@
 		purple_xfer_request(xfer);
 }
 
-void jabber_si_parse(JabberStream *js, xmlnode *packet)
+void jabber_si_parse(JabberStream *js, xmlnode *si, const char *from, const char *id)
 {
 	JabberSIXfer *jsx;
 	PurpleXfer *xfer;
-	xmlnode *si, *file, *feature, *x, *field, *option, *value;
-	const char *stream_id, *filename, *filesize_c, *profile, *from;
+	xmlnode *file, *feature, *x, *field, *option, *value;
+	const char *stream_id, *filename, *filesize_c, *profile;
 	size_t filesize = 0;
 
-	if(!(si = xmlnode_get_child(packet, "si")))
-		return;
-
 	if(!(profile = xmlnode_get_attrib(si, "profile")) ||
 			strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer"))
 		return;
@@ -1215,7 +1212,7 @@
 	if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data")))
 		return;
 
-	if(!(from = xmlnode_get_attrib(packet, "from")))
+	if(!from)
 		return;
 
 	/* if they've already sent us this file transfer with the same damn id
@@ -1256,7 +1253,7 @@
 
 	jsx->js = js;
 	jsx->stream_id = g_strdup(stream_id);
-	jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id"));
+	jsx->iq_id = g_strdup(id);
 
 	xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from);
 	if (xfer)
--- a/libpurple/protocols/jabber/si.h	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/jabber/si.h	Fri Feb 06 22:46:24 2009 +0000
@@ -27,7 +27,7 @@
 #include "jabber.h"
 
 void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet);
-void jabber_si_parse(JabberStream *js, xmlnode *packet);
+void jabber_si_parse(JabberStream *js, xmlnode *si, const char *from, const char *id);
 PurpleXfer *jabber_si_new_xfer(PurpleConnection *gc, const char *who);
 void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file);
 
--- a/libpurple/protocols/msn/msg.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/msn/msg.c	Fri Feb 06 22:46:24 2009 +0000
@@ -80,7 +80,7 @@
 	msg->ref_count++;
 
 #ifdef MSN_DEBUG_MSG
-	purple_debug_info("msn", "message ref (%p)[%d]\n", msg, msg->ref_count);
+	purple_debug_info("msn", "message ref (%p)[%" G_GSIZE_FORMAT "]\n", msg, msg->ref_count);
 #endif
 
 	return msg;
@@ -95,7 +95,7 @@
 	msg->ref_count--;
 
 #ifdef MSN_DEBUG_MSG
-	purple_debug_info("msn", "message unref (%p)[%d]\n", msg, msg->ref_count);
+	purple_debug_info("msn", "message unref (%p)[%" G_GSIZE_FORMAT "]\n", msg, msg->ref_count);
 #endif
 
 	if (msg->ref_count == 0)
--- a/libpurple/protocols/msn/msn.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/msn/msn.c	Fri Feb 06 22:46:24 2009 +0000
@@ -853,11 +853,11 @@
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
-			NULL, NULL, FALSE, TRUE, FALSE);
+			NULL, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-			NULL, NULL, FALSE, TRUE, FALSE);
+			NULL, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
@@ -1176,6 +1176,7 @@
 	MsnMessage *msg;
 	char *msgformat;
 	char *msgtext;
+	size_t msglen;
 	const char *username;
 
 	purple_debug_info("msn", "send IM {%s} to %s\n", message, who);
@@ -1203,13 +1204,23 @@
 	}
 
 	msn_import_html(message, &msgformat, &msgtext);
+	msglen = strlen(msgtext);
+	if (msglen == 0) {
+		/* Stuff like <hr> will be ignored. Don't send an empty message
+		   if that's all there is. */
+		g_free(msgtext);
+		g_free(msgformat);
+
+		return 0;
+	}
+
 	if (msn_user_is_online(account, who) ||
 		msn_user_is_yahoo(account, who) ||
 		swboard != NULL) {
 		/*User online or have a swboard open because it's invisible
 		 * and sent us a message,then send Online Instant Message*/
  
-		if (strlen(msgtext) + strlen(msgformat) + strlen(VERSION) > 1564)
+		if (msglen + strlen(msgformat) + strlen(VERSION) > 1564)
 		{
 			g_free(msgformat);
 			g_free(msgtext);
--- a/libpurple/protocols/msn/user.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/msn/user.c	Fri Feb 06 22:46:24 2009 +0000
@@ -180,7 +180,7 @@
 gboolean
 msn_user_set_friendly_name(MsnUser *user, const char *name)
 {
-	g_return_if_fail(user != NULL);
+	g_return_val_if_fail(user != NULL, FALSE);
 
 	if (user->friendly_name && name && !strcmp(user->friendly_name, name))
 		return FALSE;
--- a/libpurple/protocols/myspace/myspace.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Fri Feb 06 22:46:24 2009 +0000
@@ -1146,7 +1146,11 @@
 			break;
 
 		case MSIM_CONTACT_LIST_INITIAL_FRIENDS:
-			/* Nothing */
+			/* The session is now set up, ready to be connected. This emits the
+			 * signedOn signal, so clients can now do anything with msimprpl, and
+			 * we're ready for it (session key, userid, username all setup). */
+			purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
+			purple_connection_set_state(session->gc, PURPLE_CONNECTED);
 			break;
 	}
 
@@ -1185,12 +1189,6 @@
 	/* Set display name to username (otherwise will show email address) */
 	purple_connection_set_display_name(session->gc, session->username);
 
-	/* The session is now set up, ready to be connected. This emits the
-	 * signedOn signal, so clients can now do anything with msimprpl, and
-	 * we're ready for it (session key, userid, username all setup). */
-	purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
-	purple_connection_set_state(session->gc, PURPLE_CONNECTED);
-
 	body = msim_msg_new(
 			"UserID", MSIM_TYPE_INTEGER, session->userid,
 			NULL);
--- a/libpurple/protocols/novell/novell.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/novell/novell.c	Fri Feb 06 22:46:24 2009 +0000
@@ -2976,7 +2976,7 @@
 										   NULL, TRUE, TRUE, FALSE);
 	status_types = g_list_append(status_types, type);
 
-	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE);
 	status_types = g_list_append(status_types, type);
 
 	return status_types;
--- a/libpurple/protocols/oscar/oscar.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Feb 06 22:46:24 2009 +0000
@@ -4782,7 +4782,7 @@
 		if (status_html != NULL)
 		{
 			status_text = purple_markup_strip_html(status_html);
-			/* If the status_text is longer than 60 character then truncate it */
+			/* If the status_text is longer than 251 characters then truncate it */
 			if (strlen(status_text) > MAXAVAILMSGLEN)
 			{
 				char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]);
@@ -4799,9 +4799,28 @@
 	}
 	else
 	{
+		char *status_text = NULL;
+		
 		htmlaway = purple_status_get_attr_string(status, "message");
 		if ((htmlaway == NULL) || (*htmlaway == '\0'))
 			htmlaway = purple_status_type_get_name(status_type);
+		
+		/* ICQ 6.x seems to use an available message for all statuses so set one */
+		if (od->icq) 
+		{
+			status_text = purple_markup_strip_html(htmlaway);
+			/* If the status_text is longer than 251 characters then truncate it */
+			if (strlen(status_text) > MAXAVAILMSGLEN)
+			{
+				char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]);
+				strcpy(tmp, "...");
+			}
+			aim_srv_setextrainfo(od, FALSE, 0, TRUE, status_text, NULL);
+		}
+		g_free(status_text);
+
+		/* Set a proper away message for icq too so that they work for old third party clients */
+		
 		away = purple_prpl_oscar_convert_to_infotext(htmlaway, &awaylen, &away_encoding);
 
 		if (awaylen > od->rights.maxawaymsglen)
--- a/libpurple/protocols/qq/qq.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/qq/qq.c	Fri Feb 06 22:46:24 2009 +0000
@@ -406,15 +406,15 @@
 	GList *types = NULL;
 
 	status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE,
-			"available", _("Available"), FALSE, TRUE, FALSE);
+			"available", _("Available"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_AWAY,
-			"away", _("Away"), FALSE, TRUE, FALSE);
+			"away", _("Away"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
-			"invisible", _("Invisible"), FALSE, TRUE, FALSE);
+			"invisible", _("Invisible"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE,
@@ -422,7 +422,7 @@
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-			"offline", _("Offline"), FALSE, TRUE, FALSE);
+			"offline", _("Offline"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
--- a/libpurple/protocols/silc/silc.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/silc/silc.c	Fri Feb 06 22:46:24 2009 +0000
@@ -48,19 +48,19 @@
 	PurpleStatusType *type;
 	GList *types = NULL;
 
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
 
 	return types;
--- a/libpurple/protocols/silc10/silc.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/protocols/silc10/silc.c	Fri Feb 06 22:46:24 2009 +0000
@@ -39,19 +39,19 @@
 	PurpleStatusType *type;
 	GList *types = NULL;
 
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, FALSE, TRUE, FALSE);
+	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE);
 	types = g_list_append(types, type);
 
 	return types;
--- a/libpurple/xmlnode.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/xmlnode.c	Fri Feb 06 22:46:24 2009 +0000
@@ -303,7 +303,7 @@
 	node->prefix = g_strdup(prefix);
 }
 
-const char *xmlnode_get_prefix(xmlnode *node)
+const char *xmlnode_get_prefix(const xmlnode *node)
 {
 	g_return_val_if_fail(node != NULL, NULL);
 	return node->prefix;
@@ -443,11 +443,11 @@
 }
 
 static char *
-xmlnode_to_str_helper(xmlnode *node, int *len, gboolean formatting, int depth)
+xmlnode_to_str_helper(const xmlnode *node, int *len, gboolean formatting, int depth)
 {
 	GString *text = g_string_new("");
 	const char *prefix;
-	xmlnode *c;
+	const xmlnode *c;
 	char *node_name, *esc, *esc2, *tab = NULL;
 	gboolean need_end = FALSE, pretty = formatting;
 
@@ -537,13 +537,13 @@
 }
 
 char *
-xmlnode_to_str(xmlnode *node, int *len)
+xmlnode_to_str(const xmlnode *node, int *len)
 {
 	return xmlnode_to_str_helper(node, len, FALSE, 0);
 }
 
 char *
-xmlnode_to_formatted_str(xmlnode *node, int *len)
+xmlnode_to_formatted_str(const xmlnode *node, int *len)
 {
 	char *xml, *xml_with_declaration;
 
--- a/libpurple/xmlnode.h	Fri Feb 06 22:45:52 2009 +0000
+++ b/libpurple/xmlnode.h	Fri Feb 06 22:46:24 2009 +0000
@@ -243,7 +243,7 @@
  * @param node The node to get the prefix from
  * @return The prefix of this node
  */
-const char *xmlnode_get_prefix(xmlnode *node);
+const char *xmlnode_get_prefix(const xmlnode *node);
 
 /**
  * Returns the node in a string of xml.
@@ -254,7 +254,7 @@
  * @return The node represented as a string.  You must
  *         g_free this string when finished using it.
  */
-char *xmlnode_to_str(xmlnode *node, int *len);
+char *xmlnode_to_str(const xmlnode *node, int *len);
 
 /**
  * Returns the node in a string of human readable xml.
@@ -266,7 +266,7 @@
  *         tab and new line characters.  You must
  *         g_free this string when finished using it.
  */
-char *xmlnode_to_formatted_str(xmlnode *node, int *len);
+char *xmlnode_to_formatted_str(const xmlnode *node, int *len);
 
 /**
  * Creates a node from a string of XML.  Calling this on the
--- a/pidgin/gtkdialogs.c	Fri Feb 06 22:45:52 2009 +0000
+++ b/pidgin/gtkdialogs.c	Fri Feb 06 22:46:24 2009 +0000
@@ -198,7 +198,7 @@
 	{N_("Macedonian"),          "mk", "Arangel Angov ", "arangel@linux.net.mk"},
 	{N_("Macedonian"),          "mk", "Ivana Kirkovska", "ivana.kirkovska@gmail.com"},
 	{N_("Macedonian"),          "mk", "Jovan Naumovski", "jovan@lugola.net"},
-	{"Mongolian",               "mn", "gooyo", NULL},
+	{N_("Mongolian"),           "mn", "gooyo", NULL},
 	{N_("Bokmål Norwegian"),    "nb", "Hans Fredrik Nordhaug", "hans@nordhaug.priv.no"},
 	{N_("Nepali"),              "ne", "Shyam Krishna Bal", "shyamkrishna_bal@yahoo.com"},
 	{N_("Dutch, Flemish"),      "nl", "Vincent van Adrighem", "V.vanAdrighem@dirck.mine.nu"},
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Fri Feb 06 22:45:52 2009 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Fri Feb 06 22:46:24 2009 +0000
@@ -1247,6 +1247,9 @@
   Push $R0
   Push $R1
   Push $R2
+  Push $R3 ; This is only used for the Parameters throughout the function
+
+  ${GetParameters} $R3
 
   IntOp $R1 0 + 0
   retry_runcheck:
@@ -1258,7 +1261,14 @@
   IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume
     MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(INSTALLER_IS_RUNNING) /SD IDCANCEL IDRETRY retry_runcheck
     Abort
+
+  ; Allow installer to run even if pidgin is running via "/NOPIDGINRUNCHECK=1"
+  ; This is useful for testing
+  ClearErrors
+  ${GetOptions} "$R3" "/NOPIDGINRUNCHECK=" $R1
+  IfErrors 0 +2
   Call RunCheck
+
   StrCpy $name "Pidgin ${PIDGIN_VERSION}"
   StrCpy $SPELLCHECK_SEL ""
 
@@ -1312,16 +1322,13 @@
   SetShellVarContext "current"
 
   StrCpy $ISSILENT "/S"
-
-  ; GTK installer has two silent states.. one with Message boxes, one without
+  ; GTK installer has two silent states - one with Message boxes, one without
   ; If pidgin installer was run silently, we want to supress gtk installer msg boxes.
-  IfSilent 0 set_gtk_normal
-      StrCpy $ISSILENT "/NOUI"
-  set_gtk_normal:
+  IfSilent 0 +2
+    StrCpy $ISSILENT "/NOUI"
 
-  ${GetParameters} $R0
   ClearErrors
-  ${GetOptions} "$R0" "/L=" $R1
+  ${GetOptions} "$R3" "/L=" $R1
   IfErrors +3
   StrCpy $LANGUAGE $R1
   Goto skip_lang
@@ -1332,7 +1339,7 @@
     skip_lang:
 
   ClearErrors
-  ${GetOptions} "$R0" "/DS=" $R1
+  ${GetOptions} "$R3" "/DS=" $R1
   IfErrors +8
   SectionGetFlags ${SecDesktopShortcut} $R2
   StrCmp "1" $R1 0 +2
@@ -1343,7 +1350,7 @@
   SectionSetFlags ${SecDesktopShortcut} $R2
 
   ClearErrors
-  ${GetOptions} "$R0" "/SMS=" $R1
+  ${GetOptions} "$R3" "/SMS=" $R1
   IfErrors +8
   SectionGetFlags ${SecStartMenuShortcut} $R2
   StrCmp "1" $R1 0 +2
@@ -1380,6 +1387,7 @@
 
   instdir_done:
 ;LogSet on
+  Pop $R3
   Pop $R2
   Pop $R1
   Pop $R0
@@ -1694,6 +1702,7 @@
   Push $R1
   Push $R2
   Push $R3
+  Push $R4
 
   check:
   ClearErrors
@@ -1714,7 +1723,12 @@
   StrCmp $R3 "success" +3
     StrCpy $R0 $R3
     Goto done
+  ; Use a specific temporary $OUTDIR for each dictionary because the installer doesn't clean up after itself
+  StrCpy $R4 "$OUTDIR"
+  SetOutPath "$TEMP\aspell_dict-$R0"
   ExecWait '"$R1"'
+  SetOutPath "$R4"
+  RMDir /r "$TEMP\aspell_dict-$R0"
   Delete $R1
   Goto check ; Check that it is now installed correctly
 
@@ -1723,6 +1737,7 @@
     StrCpy $R0 ''
 
   done:
+  Pop $R4
   Pop $R3
   Pop $R2
   Pop $R1