changeset 29376:4c4ddafbc089

merged with im.pidgin.pidgin
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Sat, 06 Feb 2010 15:45:51 +0900
parents e3031e5785a3 (current diff) 8e007ad2421d (diff)
children 421ef79a30ca
files libpurple/buddyicon.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/message.c pidgin/gtkconv.c pidgin/gtkimhtml.c
diffstat 59 files changed, 712 insertions(+), 712 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Feb 03 16:00:49 2010 +0900
+++ b/ChangeLog	Sat Feb 06 15:45:51 2010 +0900
@@ -5,6 +5,8 @@
 	* Fix 'make check' on OS X. (David Fang)
 	* Fix a quirk in purple_markup_html_to_xhtml that caused some messages
 	  to be improperly converted to XHTML.
+	* Set "controlling-mode" correctly when initializing a media session.
+	  Fixes receiving voice calls from Psi.
 
 	General:
 	* Correctly disable all missing dependencies when using the
@@ -14,6 +16,10 @@
 	* Fix display of avatars after a server-side change. (Krzysztof
 	  Klinikowski)
 
+	AIM:
+	* Allow setting and displaying icons between 1x1 and 100x100 pixels.
+	  Previously only icons between 48x48 and 50x50 were allowed.
+
 	MSN:
 	* File transfer requests will no longer cause a crash if you delete the
 	  file before the other side accepts.
@@ -33,6 +39,9 @@
 	  with some clients.
 	* Don't do an SRV lookup for a STUN server associated with the account
 	  if one is already set globally in prefs.
+	* Don't send custom smileys larger than the recommended maximum object size
+	  specified in the BoB XEP.   This prevents a client from being
+	  disconnected by servers that dislike overly-large stanzas.
 
 	Yahoo:
 	* Don't send <span> and </span> tags.  (Fartash Faghri)
@@ -44,6 +53,12 @@
 	  request form.  (Thanks to Florian Zeitz for finding this problem)
 	* Search friends by email-addresses in the buddy list. (Luoh Ren-Shan)
 
+	Finch:
+	* Rebindable 'move-first' and 'move-last' actions for tree widgets. So
+	  it is possible to jump to the first or last entry in the buddy list
+	  (and other such lists) by pressing home or end key (defaults)
+	  respectively.
+
 version 2.6.5 (01/08/2010):
 	libpurple:
 	* TLS certificates are actually stored to the local cache once again
--- a/doc/finch.1.in	Wed Feb 03 16:00:49 2010 +0900
+++ b/doc/finch.1.in	Sat Feb 06 15:45:51 2010 +0900
@@ -366,6 +366,10 @@
 .br
 backspace = move-parent
 .br
+home = move-first
+.br
+end = move-last
+.br
 # Following is the default binding for the context-menu
 .br
 menu = context-menu
--- a/finch/libgnt/gnttree.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/finch/libgnt/gnttree.c	Sat Feb 06 15:45:51 2010 +0900
@@ -957,6 +957,45 @@
 	return TRUE;
 }
 
+static gboolean
+move_first_action(GntBindable *bind, GList *null)
+{
+	GntTree *tree = GNT_TREE(bind);
+	GntTreeRow *row = tree->root;
+	GntTreeRow *old = tree->current;
+	if (row && !row_matches_search(row))
+		row = get_next(row);
+	if (row) {
+		tree->current = row;
+		redraw_tree(tree);
+		if (old != tree->current)
+			tree_selection_changed(tree, old, tree->current);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+move_last_action(GntBindable *bind, GList *null)
+{
+	GntTree *tree = GNT_TREE(bind);
+	GntTreeRow *old = tree->current;
+	GntTreeRow *row = tree->bottom;
+	GntTreeRow *next;
+
+	while ((next = get_next(row)))
+		row = next;
+
+	if (row) {
+		tree->current = row;
+		redraw_tree(tree);
+		if (old != tree->current)
+			tree_selection_changed(tree, old, tree->current);
+	}
+
+	return TRUE;
+}
+
 static void
 gnt_tree_set_property(GObject *obj, guint prop_id, const GValue *value,
 		GParamSpec *spec)
@@ -1076,6 +1115,10 @@
 				"/", NULL);
 	gnt_bindable_class_register_action(bindable, "end-search", end_search_action,
 				"\033", NULL);
+	gnt_bindable_class_register_action(bindable, "move-first", move_first_action,
+			GNT_KEY_HOME, NULL);
+	gnt_bindable_class_register_action(bindable, "move-last", move_last_action,
+			GNT_KEY_END, NULL);
 
 	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable);
 	GNTDEBUG;
--- a/libpurple/buddyicon.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/buddyicon.c	Sat Feb 06 15:45:51 2010 +0900
@@ -1300,6 +1300,9 @@
 	g_hash_table_destroy(pointer_icon_cache);
 	g_free(old_icons_dir);
 	g_free(cache_dir);
+
+	cache_dir = NULL;
+	old_icons_dir = NULL;
 }
 
 void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int *height)
--- a/libpurple/media.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/media.c	Sat Feb 06 15:45:51 2010 +0900
@@ -2754,15 +2754,21 @@
 		FsStream *fsstream = NULL;
 		const gchar *stun_ip = purple_network_get_stun_ip();
 		const gchar *turn_ip = purple_network_get_turn_ip();
-
-		if (stun_ip || turn_ip) {
-			guint new_num_params = 
+		guint new_num_params =
+					!stun_ip && !turn_ip ? num_params + 1 :
 					(stun_ip && is_nice) && turn_ip ?
-					num_params + 2 : num_params + 1;
-			guint next_param_index = num_params;
-			GParameter *param = g_new0(GParameter, new_num_params);
-			memcpy(param, params, sizeof(GParameter) * num_params);
-
+					num_params + 3 : num_params + 2;
+		guint next_param_index = num_params;
+		GParameter *param = g_new0(GParameter, new_num_params);
+		memcpy(param, params, sizeof(GParameter) * num_params);
+
+		/* set controlling mode according to direction */
+		param[next_param_index].name = "controlling-mode";
+		g_value_init(&param[next_param_index].value, G_TYPE_BOOLEAN);
+		g_value_set_boolean(&param[next_param_index].value, initiator);
+		next_param_index++;
+		
+		if (stun_ip || turn_ip) {
 			if (stun_ip) {
 				purple_debug_info("media", 
 					"setting property stun-ip on new stream: %s\n", stun_ip);
@@ -2813,20 +2819,14 @@
 					return FALSE;
 				}
 			}
-
-			fsstream = fs_session_new_stream(session->session,
+		}
+
+		fsstream = fs_session_new_stream(session->session,
 					participant, initiator == TRUE ?
 					type_direction : (type_direction &
 					FS_DIRECTION_RECV), transmitter,
 					new_num_params, param, &err);
-			g_free(param);
-		} else {
-			fsstream = fs_session_new_stream(session->session,
-					participant, initiator == TRUE ?
-					type_direction : (type_direction &
-					FS_DIRECTION_RECV), transmitter,
-					num_params, params, &err);
-		}
+		g_free(param);
 
 		if (fsstream == NULL) {
 			purple_debug_error("media",
--- a/libpurple/prefs.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/prefs.h	Sat Feb 06 15:45:51 2010 +0900
@@ -185,7 +185,16 @@
  *
  * @param name  The name of the pref
  * @param value The value to set
+ *
+ * @deprecated We're not really sure what purpose this function serves, so it
+ *             will be removed in 3.0.0.  Preferences values set using this
+ *             function aren't serialized to prefs.xml, which could be
+ *             misleading.  There is also no purple_prefs_get_generic, which
+ *             means that if you can't really get the value (other in a
+ *             connected callback).  If you think you have a use for this then
+ *             please let us know.
  */
+/* TODO: When this is removed, also remove struct purple_pref->value.generic */
 void purple_prefs_set_generic(const char *name, gpointer value);
 
 /**
--- a/libpurple/protocols/irc/msgs.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/irc/msgs.c	Sat Feb 06 15:45:51 2010 +0900
@@ -1069,7 +1069,7 @@
 
 	nick = irc_mask_nick(from);
 	if (!purple_utf8_strcasecmp(nick, purple_connection_get_display_name(gc))) {
-		char *escaped = g_markup_escape_text(args[1], -1);
+		char *escaped = args[1] ? g_markup_escape_text(args[1], -1) : NULL;
 		msg = g_strdup_printf(_("You have parted the channel%s%s"),
 		                      (args[1] && *args[1]) ? ": " : "",
 		                      (escaped && *escaped) ? escaped : "");
--- a/libpurple/protocols/jabber/data.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/jabber/data.h	Sat Feb 06 15:45:51 2010 +0900
@@ -26,6 +26,8 @@
 
 #include <glib.h>
 
+#define JABBER_DATA_MAX_SIZE 8192
+
 typedef struct {
 	char *cid;
 	char *type;
--- a/libpurple/protocols/jabber/jabber.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/jabber/jabber.c	Sat Feb 06 15:45:51 2010 +0900
@@ -356,11 +356,20 @@
 	}
 
 	if (ret < 0 && errno != EAGAIN) {
-		gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
-				g_strerror(errno));
-		purple_connection_error_reason(js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
+		PurpleAccount *account = purple_connection_get_account(js->gc);
+		/*
+		 * The server may have closed the socket (on a stream error), so if
+		 * we're disconnecting, don't generate (possibly another) error that
+		 * (for some UIs) would mask the first.
+		 */
+		if (!account->disconnecting) {
+			gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
+					g_strerror(errno));
+			purple_connection_error_reason(js->gc,
+				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+			g_free(tmp);
+		}
+
 		success = FALSE;
 	} else if (ret < len) {
 		if (ret < 0)
@@ -418,13 +427,12 @@
 		g_free(text);
 	}
 
-	/* If we've got a security layer, we need to encode the data,
-	 * splitting it on the maximum buffer length negotiated */
-
 	purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-sending-text", js->gc, &data);
 	if (data == NULL)
 		return;
 
+	/* 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
 	if (js->sasl_maxbuf>0) {
 		int pos = 0;
@@ -1437,30 +1445,21 @@
  */
 void jabber_close(PurpleConnection *gc)
 {
-	JabberStream *js = gc->proto_data;
+	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	/* Close all of the open Jingle sessions on this stream */
 	jingle_terminate_sessions(js);
 
-	/* Don't perform any actions on the ssl connection
-	 * if we were forcibly disconnected because it will crash
-	 * on some SSL backends.
-	 */
-	if (!gc->disconnect_timeout) {
-		if (js->bosh)
-			jabber_bosh_connection_close(js->bosh);
-		else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0)
-			jabber_send_raw(js, "</stream:stream>", -1);
-	}
+	if (js->bosh)
+		jabber_bosh_connection_close(js->bosh);
+	else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0)
+		jabber_send_raw(js, "</stream:stream>", -1);
 
 	if (js->srv_query_data)
 		purple_srv_cancel(js->srv_query_data);
 
 	if(js->gsc) {
-#ifdef HAVE_OPENSSL
-		if (!gc->disconnect_timeout)
-#endif
-			purple_ssl_close(js->gsc);
+		purple_ssl_close(js->gsc);
 	} else if (js->fd > 0) {
 		if(js->gc->inpa)
 			purple_input_remove(js->gc->inpa);
--- a/libpurple/protocols/jabber/libxmpp.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/jabber/libxmpp.c	Sat Feb 06 15:45:51 2010 +0900
@@ -431,7 +431,7 @@
 	jabber_data_init();
 	jabber_bosh_init();
 
-	#warning implement adding and retrieving own features via IPC API
+	/* TODO: Implement adding and retrieving own features via IPC API */
 
 	jabber_ibb_init();
 	jabber_si_init();
--- a/libpurple/protocols/jabber/message.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/jabber/message.c	Sat Feb 06 15:45:51 2010 +0900
@@ -868,6 +868,7 @@
 
 	for (; smileys ; smileys = g_list_delete_link(smileys, smileys)) {
 		PurpleSmiley *smiley = (PurpleSmiley *) smileys->data;
+
 		const gchar *shortcut = purple_smiley_get_shortcut(smiley);
 		const gssize len = strlen(shortcut);
 
@@ -989,36 +990,52 @@
 		if (found_smileys) {
 			gchar *smileyfied_xhtml = NULL;
 			const GList *iterator;
-
+			GList *valid_smileys = NULL;
+			gboolean has_too_large_smiley = FALSE;
+			
 			for (iterator = found_smileys; iterator ;
 				iterator = g_list_next(iterator)) {
-				const PurpleSmiley *smiley =
-						(PurpleSmiley *) iterator->data;
+				PurpleSmiley *smiley = (PurpleSmiley *) iterator->data;
 				const gchar *shortcut = purple_smiley_get_shortcut(smiley);
 				const JabberData *data =
 					jabber_data_find_local_by_alt(shortcut);
+				PurpleStoredImage *image = purple_smiley_get_stored_image(smiley);
 
-				/* the object has not been sent before */
-				if (!data) {
-					PurpleStoredImage *image =
-							purple_smiley_get_stored_image(smiley);
-					const gchar *ext = purple_imgstore_get_extension(image);
-					JabberStream *js = jm->js;
+				if (purple_imgstore_get_size(image) <= JABBER_DATA_MAX_SIZE) {
+					/* the object has not been sent before */
+					if (!data) {
+						const gchar *ext = purple_imgstore_get_extension(image);
+						JabberStream *js = jm->js;
 
-					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);
-					purple_debug_info("jabber",
-						"cache local smiley alt = %s, cid = %s\n",
-						shortcut, jabber_data_get_cid(new_data));
-					jabber_data_associate_local(new_data, shortcut);
-				}
+						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);
+						purple_debug_info("jabber",
+							"cache local smiley alt = %s, cid = %s\n",
+							shortcut, jabber_data_get_cid(new_data));
+						jabber_data_associate_local(new_data, shortcut);
+					}
+					valid_smileys = g_list_append(valid_smileys, smiley);
+				} else {
+					has_too_large_smiley = TRUE;
+					purple_debug_warning("jabber", "Refusing to send smiley %s "
+							"(too large, max is %d)\n",
+							purple_smiley_get_shortcut(smiley),
+							JABBER_DATA_MAX_SIZE);
+				}				
+			}
+
+			if (has_too_large_smiley) {
+				purple_conversation_write(conv, NULL,
+				    _("A custom smiley in the message is too large to send."),
+					PURPLE_MESSAGE_ERROR, time(NULL));
 			}
 
 			smileyfied_xhtml =
-				jabber_message_get_smileyfied_xhtml(xhtml, found_smileys);
+				jabber_message_get_smileyfied_xhtml(xhtml, valid_smileys);
 			g_list_free(found_smileys);
+			g_list_free(valid_smileys);
 
 			return smileyfied_xhtml;
 		}
--- a/libpurple/protocols/msn/cmdproc.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/cmdproc.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,17 +21,17 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_CMDPROC_H_
-#define _MSN_CMDPROC_H_
+#ifndef MSN_CMDPROC_H
+#define MSN_CMDPROC_H
 
 typedef struct _MsnCmdProc MsnCmdProc;
 
-#include "session.h"
-#include "servconn.h"
+#include "command.h"
 #include "error.h"
-#include "command.h"
+#include "history.h"
+#include "servconn.h"
+#include "session.h"
 #include "table.h"
-#include "history.h"
 
 struct _MsnCmdProc
 {
@@ -71,4 +71,4 @@
 void msn_cmdproc_process_payload(MsnCmdProc *cmdproc,
 								 char *payload, int payload_len);
 
-#endif /* _MSN_CMDPROC_H_ */
+#endif /* MSN_CMDPROC_H */
--- a/libpurple/protocols/msn/command.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/command.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_COMMAND_H
-#define _MSN_COMMAND_H
+#ifndef MSN_COMMAND_H
+#define MSN_COMMAND_H
 
 typedef struct _MsnCommand MsnCommand;
 
@@ -59,4 +59,4 @@
 MsnCommand *msn_command_ref(MsnCommand *cmd);
 MsnCommand *msn_command_unref(MsnCommand *cmd);
 
-#endif /* _MSN_COMMAND_H */
+#endif /* MSN_COMMAND_H */
--- a/libpurple/protocols/msn/contact.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/contact.c	Sat Feb 06 15:45:51 2010 +0900
@@ -406,8 +406,8 @@
 	msn_user_set_network(user, nid);
 	msn_user_set_invite_message(user, invite);
 
-	if (member_id) {
-		user->membership_id[list] = atoi(member_id);
+	if (list == MSN_LIST_PL && member_id) {
+		user->member_id_on_pending_list = atoi(member_id);
 	}
 
 	msn_got_lst_user(session, user, 1 << list, NULL);
@@ -1567,11 +1567,11 @@
 		if (user && user->networkid != MSN_NETWORK_PASSPORT)
 			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
 			                         "EmailMember", "Email",
-			                         user->membership_id[MSN_LIST_PL]);
+			                         user->member_id_on_pending_list);
 		else
 			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
 			                         "PassportMember", "Passport",
-			                         user->membership_id[MSN_LIST_PL]);
+			                         user->member_id_on_pending_list);
 	} else {
 		/* list == MSN_LIST_AL || list == MSN_LIST_BL */
 		partner_scenario = MSN_PS_BLOCK_UNBLOCK;
--- a/libpurple/protocols/msn/contact.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/contact.h	Sat Feb 06 15:45:51 2010 +0900
@@ -22,8 +22,38 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
  */
-#ifndef _MSN_CONTACT_H_
-#define _MSN_CONTACT_H_
+#ifndef MSN_CONTACT_H
+#define MSN_CONTACT_H
+
+typedef struct _MsnCallbackState MsnCallbackState;
+
+typedef enum
+{
+	MSN_ADD_BUDDY       = 0x01,
+	MSN_MOVE_BUDDY      = 0x02,
+	MSN_ACCEPTED_BUDDY  = 0x04,
+	MSN_DENIED_BUDDY    = 0x08,
+	MSN_ADD_GROUP       = 0x10,
+	MSN_DEL_GROUP       = 0x20,
+	MSN_RENAME_GROUP    = 0x40,
+	MSN_UPDATE_INFO     = 0x80
+} MsnCallbackAction;
+
+typedef enum
+{
+	MSN_UPDATE_DISPLAY,	/* Real display name */
+	MSN_UPDATE_ALIAS,	/* Aliased display name */
+	MSN_UPDATE_COMMENT
+} MsnContactUpdateType;
+
+typedef enum
+{
+	MSN_PS_INITIAL,
+	MSN_PS_SAVE_CONTACT,
+	MSN_PS_PENDING_LIST,
+	MSN_PS_CONTACT_API,
+	MSN_PS_BLOCK_UNBLOCK
+} MsnSoapPartnerScenario;
 
 #include "session.h"
 #include "soap.h"
@@ -609,29 +639,6 @@
 	"</soap:Body>"\
 "</soap:Envelope>"
 
-typedef enum
-{
-	MSN_ADD_BUDDY       = 0x01,
-	MSN_MOVE_BUDDY      = 0x02,
-	MSN_ACCEPTED_BUDDY  = 0x04,
-	MSN_DENIED_BUDDY    = 0x08,
-	MSN_ADD_GROUP       = 0x10,
-	MSN_DEL_GROUP       = 0x20,
-	MSN_RENAME_GROUP    = 0x40,
-	MSN_UPDATE_INFO     = 0x80
-} MsnCallbackAction;
-
-typedef enum
-{
-	MSN_PS_INITIAL,
-	MSN_PS_SAVE_CONTACT,
-	MSN_PS_PENDING_LIST,
-	MSN_PS_CONTACT_API,
-	MSN_PS_BLOCK_UNBLOCK
-} MsnSoapPartnerScenario;
-
-typedef struct _MsnCallbackState MsnCallbackState;
-
 struct _MsnCallbackState
 {
 	gchar * who;
@@ -651,13 +658,6 @@
 	MsnSoapPartnerScenario partner_scenario;
 };
 
-typedef enum
-{
-	MSN_UPDATE_DISPLAY,	/* Real display name */
-	MSN_UPDATE_ALIAS,	/* Aliased display name */
-	MSN_UPDATE_COMMENT
-} MsnContactUpdateType;
-
 /************************************************
  * function prototype
  ************************************************/
@@ -707,5 +707,4 @@
 void msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
 			       const gchar *passport, const MsnListId list);
 
-#endif /* _MSN_CONTACT_H_ */
-
+#endif /* MSN_CONTACT_H */
--- a/libpurple/protocols/msn/dialog.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/dialog.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,10 +21,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_DIALOG_H_
-#define _MSN_DIALOG_H_
+#ifndef MSN_DIALOG_H
+#define MSN_DIALOG_H
 
 void msn_show_sync_issue(MsnSession *session, const char *passport,
 						 const char *group_name);
 
-#endif /* _MSN_DIALOG_H_ */
+#endif /* MSN_DIALOG_H */
--- a/libpurple/protocols/msn/directconn.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/directconn.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,14 +21,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_DIRECTCONN_H_
-#define _MSN_DIRECTCONN_H_
+#ifndef MSN_DIRECTCONN_H
+#define MSN_DIRECTCONN_H
 
 typedef struct _MsnDirectConn MsnDirectConn;
 
-#include "slplink.h"
+#include "msg.h"
 #include "slp.h"
-#include "msg.h"
+#include "slplink.h"
 
 struct _MsnDirectConn
 {
@@ -58,4 +58,4 @@
 void msn_directconn_destroy(MsnDirectConn *directconn);
 void msn_directconn_send_handshake(MsnDirectConn *directconn);
 
-#endif /* _MSN_DIRECTCONN_H_ */
+#endif /* MSN_DIRECTCONN_H */
--- a/libpurple/protocols/msn/error.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/error.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_ERROR_H_
-#define _MSN_ERROR_H_
+#ifndef MSN_ERROR_H
+#define MSN_ERROR_H
 
 #include "session.h"
 
@@ -44,4 +44,4 @@
  */
 void msn_error_handle(MsnSession *session, unsigned int type);
 
-#endif /* _MSN_ERROR_H_ */
+#endif /* MSN_ERROR_H */
--- a/libpurple/protocols/msn/group.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/group.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_GROUP_H_
-#define _MSN_GROUP_H_
+#ifndef MSN_GROUP_H
+#define MSN_GROUP_H
 
 typedef struct _MsnGroup  MsnGroup;
 
@@ -106,5 +106,4 @@
  */
 const char *msn_group_get_name(const MsnGroup *group);
 
-#endif /* _MSN_GROUP_H_ */
-
+#endif /* MSN_GROUP_H */
--- a/libpurple/protocols/msn/history.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/history.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,16 +21,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_HISTORY_H
-#define _MSN_HISTORY_H
-
-#define MSN_NS_HIST_ELEMS 0x300
-#define MSN_SB_HIST_ELEMS 0x30
+#ifndef MSN_HISTORY_H
+#define MSN_HISTORY_H
 
 typedef struct _MsnHistory MsnHistory;
 
 #include "transaction.h"
 
+#define MSN_NS_HIST_ELEMS 0x300
+#define MSN_SB_HIST_ELEMS 0x30
+
 /**
  * The history.
  */
@@ -45,4 +45,4 @@
 MsnTransaction *msn_history_find(MsnHistory *history, unsigned int triId);
 void msn_history_add(MsnHistory *history, MsnTransaction *trans);
 
-#endif /* _MSN_HISTORY_H */
+#endif /* MSN_HISTORY_H */
--- a/libpurple/protocols/msn/httpconn.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/httpconn.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_HTTPCONN_H_
-#define _MSN_HTTPCONN_H_
+#ifndef MSN_HTTPCONN_H
+#define MSN_HTTPCONN_H
 
 typedef struct _MsnHttpConn MsnHttpConn;
 
@@ -108,4 +108,4 @@
  */
 void msn_httpconn_disconnect(MsnHttpConn *httpconn);
 
-#endif /* _MSN_HTTPCONN_H_ */
+#endif /* MSN_HTTPCONN_H */
--- a/libpurple/protocols/msn/msg.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/msg.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,32 +21,17 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_MSG_H_
-#define _MSN_MSG_H_
+#ifndef MSN_MSG_H
+#define MSN_MSG_H
 
 typedef struct _MsnMessage MsnMessage;
 
-#include "session.h"
-#include "user.h"
-
-#include "command.h"
-#include "transaction.h"
-
-typedef void (*MsnMsgCb)(MsnMessage *, void *data);
-
-#define MSG_BODY_DEM	"\r\n\r\n"
-#define MSG_LINE_DEM	"\r\n"
-
-#define MSG_OIM_BODY_DEM	"\n\n"
-#define MSG_OIM_LINE_DEM	"\n"
-
 /*
 typedef enum
 {
 	MSN_MSG_NORMAL,
 	MSN_MSG_SLP_SB,
 	MSN_MSG_SLP_DC
-
 } MsnMsgType;
 */
 
@@ -58,7 +43,6 @@
 	MSN_MSG_CAPS,
 	MSN_MSG_SLP,
 	MSN_MSG_NUDGE
-
 } MsnMsgType;
 
 typedef enum
@@ -68,8 +52,20 @@
 	MSN_MSG_ERROR_NAK, /**< The message could not be sent. */
 	MSN_MSG_ERROR_SB, /**< The error comes from the switchboard. */
 	MSN_MSG_ERROR_UNKNOWN /**< An unknown error occurred. */
+} MsnMsgErrorType;
 
-} MsnMsgErrorType;
+#include "command.h"
+#include "session.h"
+#include "transaction.h"
+#include "user.h"
+
+typedef void (*MsnMsgCb)(MsnMessage *, void *data);
+
+#define MSG_BODY_DEM	"\r\n\r\n"
+#define MSG_LINE_DEM	"\r\n"
+
+#define MSG_OIM_BODY_DEM	"\n\n"
+#define MSG_OIM_LINE_DEM	"\n"
 
 typedef struct
 {
@@ -82,13 +78,11 @@
 	guint32 ack_id;
 	guint32 ack_sub_id;
 	guint64 ack_size;
-
 } MsnSlpHeader;
 
 typedef struct
 {
 	guint32 value;
-
 } MsnSlpFooter;
 
 /**
@@ -347,4 +341,4 @@
 
 void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
 
-#endif /* _MSN_MSG_H_ */
+#endif /* MSN_MSG_H */
--- a/libpurple/protocols/msn/msn.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/msn.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,65 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_H_
-#define _MSN_H_
+#ifndef MSN_H
+#define MSN_H
+
+typedef enum
+{
+	MSN_LIST_FL_OP = 0x01,
+	MSN_LIST_AL_OP = 0x02,
+	MSN_LIST_BL_OP = 0x04,
+	MSN_LIST_RL_OP = 0x08,
+	MSN_LIST_PL_OP = 0x10
+} MsnListOp;
+#define MSN_LIST_OP_MASK	0x07
+
+typedef enum
+{
+	MSN_CLIENT_CAP_WIN_MOBILE = 0x0000001,
+	MSN_CLIENT_CAP_INK_GIF    = 0x0000004,
+	MSN_CLIENT_CAP_INK_ISF    = 0x0000008,
+	MSN_CLIENT_CAP_VIDEO_CHAT = 0x0000010,
+	MSN_CLIENT_CAP_PACKET     = 0x0000020,
+	MSN_CLIENT_CAP_MSNMOBILE  = 0x0000040,
+	MSN_CLIENT_CAP_MSNDIRECT  = 0x0000080,
+	MSN_CLIENT_CAP_WEBMSGR    = 0x0000200,
+	MSN_CLIENT_CAP_TGW        = 0x0000800,
+	MSN_CLIENT_CAP_SPACE      = 0x0001000,
+	MSN_CLIENT_CAP_MCE        = 0x0002000,
+	MSN_CLIENT_CAP_DIRECTIM   = 0x0004000,
+	MSN_CLIENT_CAP_WINKS      = 0x0008000,
+	MSN_CLIENT_CAP_SEARCH     = 0x0010000,
+	MSN_CLIENT_CAP_BOT        = 0x0020000,
+	MSN_CLIENT_CAP_VOICEIM    = 0x0040000,
+	MSN_CLIENT_CAP_SCHANNEL   = 0x0080000,
+	MSN_CLIENT_CAP_SIP_INVITE = 0x0100000,
+	MSN_CLIENT_CAP_SDRIVE     = 0x0400000,
+	MSN_CLIENT_CAP_ONECARE    = 0x1000000,
+	MSN_CLIENT_CAP_P2P_TURN   = 0x2000000,
+	MSN_CLIENT_CAP_P2P_BOOTSTRAP_VIA_UUN = 0x4000000,
+} MsnClientCaps;
+
+typedef enum
+{
+	MSN_CLIENT_EXT_CAP_RTC_VIDEO = 0x10,
+	MSN_CLIENT_EXT_CAP_P2PV2     = 0x20
+} MsnClientExtCaps;
+
+typedef enum
+{
+	MSN_CLIENT_VER_5_0  = 0x00,
+	MSN_CLIENT_VER_6_0  = 0x10,	/* MSNC1 */
+	MSN_CLIENT_VER_6_1  = 0x20,	/* MSNC2 */
+	MSN_CLIENT_VER_6_2  = 0x30,	/* MSNC3 */
+	MSN_CLIENT_VER_7_0  = 0x40,	/* MSNC4 */
+	MSN_CLIENT_VER_7_5  = 0x50,	/* MSNC5 */
+	MSN_CLIENT_VER_8_0  = 0x60,	/* MSNC6 */
+	MSN_CLIENT_VER_8_1  = 0x70,	/* MSNC7 */
+	MSN_CLIENT_VER_8_5  = 0x80,	/* MSNC8 */
+	MSN_CLIENT_VER_9_0  = 0x90,	/* MSNC9 */
+	MSN_CLIENT_VER_14_0 = 0xA0	/* MSNC10 */
+} MsnClientVerId;
 
 #include "internal.h"
 
@@ -77,66 +134,6 @@
 /* Index into attention_types */
 #define MSN_NUDGE 0
 
-typedef enum
-{
-	MSN_LIST_FL_OP = 0x01,
-	MSN_LIST_AL_OP = 0x02,
-	MSN_LIST_BL_OP = 0x04,
-	MSN_LIST_RL_OP = 0x08,
-	MSN_LIST_PL_OP = 0x10
-
-} MsnListOp;
-#define MSN_LIST_OP_MASK	0x07
-
-typedef enum
-{
-	MSN_CLIENT_CAP_WIN_MOBILE = 0x0000001,
-	MSN_CLIENT_CAP_INK_GIF    = 0x0000004,
-	MSN_CLIENT_CAP_INK_ISF    = 0x0000008,
-	MSN_CLIENT_CAP_VIDEO_CHAT = 0x0000010,
-	MSN_CLIENT_CAP_PACKET     = 0x0000020,
-	MSN_CLIENT_CAP_MSNMOBILE  = 0x0000040,
-	MSN_CLIENT_CAP_MSNDIRECT  = 0x0000080,
-	MSN_CLIENT_CAP_WEBMSGR    = 0x0000200,
-	MSN_CLIENT_CAP_TGW        = 0x0000800,
-	MSN_CLIENT_CAP_SPACE      = 0x0001000,
-	MSN_CLIENT_CAP_MCE        = 0x0002000,
-	MSN_CLIENT_CAP_DIRECTIM   = 0x0004000,
-	MSN_CLIENT_CAP_WINKS      = 0x0008000,
-	MSN_CLIENT_CAP_SEARCH     = 0x0010000,
-	MSN_CLIENT_CAP_BOT        = 0x0020000,
-	MSN_CLIENT_CAP_VOICEIM    = 0x0040000,
-	MSN_CLIENT_CAP_SCHANNEL   = 0x0080000,
-	MSN_CLIENT_CAP_SIP_INVITE = 0x0100000,
-	MSN_CLIENT_CAP_SDRIVE     = 0x0400000,
-	MSN_CLIENT_CAP_ONECARE    = 0x1000000,
-	MSN_CLIENT_CAP_P2P_TURN   = 0x2000000,
-	MSN_CLIENT_CAP_P2P_BOOTSTRAP_VIA_UUN = 0x4000000,
-
-} MsnClientCaps;
-
-typedef enum
-{
-	MSN_CLIENT_EXT_CAP_RTC_VIDEO = 0x10,
-	MSN_CLIENT_EXT_CAP_P2PV2     = 0x20
-} MsnClientExtCaps;
-
-typedef enum
-{
-	MSN_CLIENT_VER_5_0  = 0x00,
-	MSN_CLIENT_VER_6_0  = 0x10,	/* MSNC1 */
-	MSN_CLIENT_VER_6_1  = 0x20,	/* MSNC2 */
-	MSN_CLIENT_VER_6_2  = 0x30,	/* MSNC3 */
-	MSN_CLIENT_VER_7_0  = 0x40,	/* MSNC4 */
-	MSN_CLIENT_VER_7_5  = 0x50,	/* MSNC5 */
-	MSN_CLIENT_VER_8_0  = 0x60,	/* MSNC6 */
-	MSN_CLIENT_VER_8_1  = 0x70,	/* MSNC7 */
-	MSN_CLIENT_VER_8_5  = 0x80,	/* MSNC8 */
-	MSN_CLIENT_VER_9_0  = 0x90,	/* MSNC9 */
-	MSN_CLIENT_VER_14_0 = 0xA0	/* MSNC10 */
-
-} MsnClientVerId;
-
 #define MSN_CLIENT_ID_VERSION      MSN_CLIENT_VER_7_0
 #define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF|MSN_CLIENT_CAP_VOICEIM)
 
@@ -151,4 +148,4 @@
 void msn_send_privacy(PurpleConnection *gc);
 void msn_send_im_message(MsnSession *session, MsnMessage *msg);
 
-#endif /* _MSN_H_ */
+#endif /* MSN_H */
--- a/libpurple/protocols/msn/msnutils.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/msnutils.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,16 +21,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_UTILS_H_
-#define _MSN_UTILS_H_
+#ifndef MSN_UTILS_H
+#define MSN_UTILS_H
 
 /*encode the str to RFC2047 style*/
-char * msn_encode_mime(const char *str);
+char *msn_encode_mime(const char *str);
 
 /**
  * Generate the Random GUID
  */
-char * rand_guid(void);
+char *rand_guid(void);
 
 /**
  * Parses the MSN message formatting into a format compatible with Purple.
@@ -57,4 +57,4 @@
 void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
 void msn_handle_chl(char *input, char *output);
 
-#endif /* _MSN_UTILS_H_ */
+#endif /* MSN_UTILS_H */
--- a/libpurple/protocols/msn/nexus.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/nexus.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_NEXUS_H_
-#define _MSN_NEXUS_H_
+#ifndef MSN_NEXUS_H
+#define MSN_NEXUS_H
+
+typedef struct _MsnNexus MsnNexus;
+typedef struct _MsnTicketToken MsnTicketToken;
+typedef struct _MsnUsrKey MsnUsrKey;
 
 /* Index into ticket_tokens in nexus.c Keep updated! */
 typedef enum
@@ -183,7 +187,6 @@
 	"</Body>"\
 "</Envelope>"
 
-typedef struct _MsnUsrKey MsnUsrKey;
 struct _MsnUsrKey
 {
 	int size; /* 28. Does not count data */
@@ -199,7 +202,6 @@
 	char cipher[72];
 };
 
-typedef struct _MsnTicketToken MsnTicketToken;
 struct _MsnTicketToken {
 	GHashTable *token;
 	char *secret;
@@ -207,8 +209,6 @@
 	GSList *updates;
 };
 
-typedef struct _MsnNexus MsnNexus;
-
 struct _MsnNexus
 {
 	MsnSession *session;
@@ -230,5 +230,5 @@
 GHashTable *msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id);
 const char *msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id);
 void msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data);
-#endif /* _MSN_NEXUS_H_ */
 
+#endif /* MSN_NEXUS_H */
--- a/libpurple/protocols/msn/notification.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/notification.c	Sat Feb 06 15:45:51 2010 +0900
@@ -1144,7 +1144,7 @@
 
 	msn_user_set_object(user, msnobj);
 
-	user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->phone.mobile && user->phone.mobile[0] == '+');
+	user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
 	msn_user_set_clientid(user, clientid);
 	msn_user_set_network(user, networkid);
 
@@ -1316,7 +1316,7 @@
 	}
 
 	clientid = strtoul(cmd->params[4], NULL, 10);
-	user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->phone.mobile && user->phone.mobile[0] == '+');
+	user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
 
 	msn_user_set_clientid(user, clientid);
 	msn_user_set_network(user, networkid);
@@ -1599,6 +1599,63 @@
 	/*get the payload content*/
 }
 
+static void parse_currentmedia(MsnUser *user, const char *cmedia)
+{
+	char **cmedia_array;
+	int strings = 0;
+
+	if (!cmedia || cmedia[0] == '\0') {
+		purple_debug_info("msn", "No currentmedia string\n");
+		return;
+	}
+
+	purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia);
+
+	cmedia_array = g_strsplit(cmedia, "\\0", 0);
+
+	/*
+	 * 0: Application
+	 * 1: 'Music'/'Games'/'Office'
+	 * 2: '1' if enabled, '0' if not
+	 * 3: Format (eg. {0} by {1})
+	 * 4: Title
+	 * If 'Music':
+	 *  5: Artist
+	 *  6: Album
+	 *  7: ?
+	 */
+#if GLIB_CHECK_VERSION(2,6,0)
+	strings  = g_strv_length(cmedia_array);
+#else
+	while (cmedia_array[++strings] != NULL);
+#endif
+
+	if (strings >= 4 && !strcmp(cmedia_array[2], "1")) {
+		if (user->extinfo == NULL)
+			user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+		else {
+			g_free(user->extinfo->media_album);
+			g_free(user->extinfo->media_artist);
+			g_free(user->extinfo->media_title);
+		}
+
+		if (!strcmp(cmedia_array[1], "Music"))
+			user->extinfo->media_type = CURRENT_MEDIA_MUSIC;
+		else if (!strcmp(cmedia_array[1], "Games"))
+			user->extinfo->media_type = CURRENT_MEDIA_GAMES;
+		else if (!strcmp(cmedia_array[1], "Office"))
+			user->extinfo->media_type = CURRENT_MEDIA_OFFICE;
+		else
+			user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
+
+		user->extinfo->media_title = g_strdup(cmedia_array[strings == 4 ? 3 : 4]);
+		user->extinfo->media_artist = strings > 5 ? g_strdup(cmedia_array[5]) : NULL;
+		user->extinfo->media_album = strings > 6 ? g_strdup(cmedia_array[6]) : NULL;
+	}
+
+	g_strfreev(cmedia_array);
+}
+
 /*
  * Get the UBX's PSM info
  * Post it to the User status
@@ -1613,7 +1670,6 @@
 	MsnUser *user;
 	const char *passport;
 	char *psm_str, *str;
-	CurrentMedia media = {CURRENT_MEDIA_UNKNOWN, NULL, NULL, NULL};
 
 	session = cmdproc->session;
 	account = session->account;
@@ -1628,24 +1684,26 @@
 		return;
 	}
 
+	/* Free any existing media info for this user */
+	if (user->extinfo) {
+		g_free(user->extinfo->media_album);
+		g_free(user->extinfo->media_artist);
+		g_free(user->extinfo->media_title);
+		user->extinfo->media_album = NULL;
+		user->extinfo->media_artist = NULL;
+		user->extinfo->media_title = NULL;
+	}
+
 	if (len != 0) {
 		psm_str = msn_get_psm(cmd->payload,len);
 		msn_user_set_statusline(user, psm_str);
 		g_free(psm_str);
 
 		str = msn_get_currentmedia(cmd->payload, len);
-		if (msn_parse_currentmedia(str, &media))
-			msn_user_set_currentmedia(user, &media);
-		else
-			msn_user_set_currentmedia(user, NULL);
-		g_free(media.title);
-		g_free(media.album);
-		g_free(media.artist);
+		parse_currentmedia(user, str);
 		g_free(str);
-
 	} else {
 		msn_user_set_statusline(user, NULL);
-		msn_user_set_currentmedia(user, NULL);
 	}
 
 	msn_user_update(user);
--- a/libpurple/protocols/msn/notification.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/notification.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,27 +21,29 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_NOTIFICATION_H_
-#define _MSN_NOTIFICATION_H_
+#ifndef MSN_NOTIFICATION_H
+#define MSN_NOTIFICATION_H
 
-/*MSN protocol challenge info*/
+typedef struct _MsnNotification MsnNotification;
 
-/*MSNP15 challenge: WLM 8.5.1288.816*/
+/* MSN protocol challenge info */
+
+/* MSNP15 challenge: WLM 8.5.1288.816 */
 #define MSNP15_WLM_PRODUCT_KEY "ILTXC!4IXB5FB*PX"
 #define MSNP15_WLM_PRODUCT_ID "PROD0119GSJUC$18"
 
-/*MSNP13 challenge*/
+/* MSNP13 challenge */
 #define MSNP13_WLM_PRODUCT_KEY	"O4BG@C7BWLYQX?5G"
 #define MSNP13_WLM_PRODUCT_ID	"PROD01065C%ZFN6F"
 
 #define MSNP10_PRODUCT_KEY		"VT6PX?UQTM4WM%YR"
 #define MSNP10_PRODUCT_ID		"PROD0038W!61ZTF9"
 
-typedef struct _MsnNotification MsnNotification;
-
+#include "cmdproc.h"
+#include "msg.h"
 #include "session.h"
 #include "servconn.h"
-#include "cmdproc.h"
+#include "state.h"
 #include "user.h"
 
 struct _MsnNotification
@@ -60,8 +62,7 @@
 
 typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network, gpointer data);
 
-#include "state.h"
-void uum_send_msg(MsnSession *session,MsnMessage *msg);
+void uum_send_msg(MsnSession *session, MsnMessage *msg);
 
 void msn_notification_end(void);
 void msn_notification_init(void);
@@ -93,4 +94,4 @@
 
 void msn_got_login_params(MsnSession *session, const char *ticket, const char *response);
 
-#endif /* _MSN_NOTIFICATION_H_ */
+#endif /* MSN_NOTIFICATION_H */
--- a/libpurple/protocols/msn/object.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/object.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,12 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_OBJECT_H_
-#define _MSN_OBJECT_H_
-
-#include "imgstore.h"
-
-#include "internal.h"
+#ifndef MSN_OBJECT_H
+#define MSN_OBJECT_H
 
 typedef enum
 {
@@ -36,8 +32,11 @@
 	MSN_OBJECT_USERTILE   =  3, /**< UserTile (buddy icon) */
 	MSN_OBJECT_RESERVED2  =  4, /**< Reserved              */
 	MSN_OBJECT_BACKGROUND =  5  /**< Background            */
+} MsnObjectType;
 
-} MsnObjectType;
+#include "internal.h"
+
+#include "imgstore.h"
 
 typedef struct
 {
@@ -51,7 +50,6 @@
 	char *friendly;
 	char *sha1d;
 	char *sha1c;
-
 } MsnObject;
 
 /**
@@ -239,4 +237,4 @@
 
 void msn_object_set_local(MsnObject *obj);
 
-#endif /* _MSN_OBJECT_H_ */
+#endif /* MSN_OBJECT_H */
--- a/libpurple/protocols/msn/oim.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/oim.h	Sat Feb 06 15:45:51 2010 +0900
@@ -22,8 +22,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
  */
-#ifndef _MSN_OIM_H_
-#define _MSN_OIM_H_
+#ifndef MSN_OIM_H
+#define MSN_OIM_H
+
+typedef struct _MsnOim MsnOim;
 
 /* OIM Retrieval Info */
 #define MSN_OIM_RETRIEVE_HOST	"rsi.hotmail.com"
@@ -131,8 +133,6 @@
 	"</soap:Body>"\
 "</soap:Envelope>"
 
-typedef struct _MsnOim MsnOim;
-
 struct _MsnOim
 {
 	MsnSession *session;
@@ -160,4 +160,4 @@
 
 void msn_oim_send_msg(MsnOim *oim);
 
-#endif/* _MSN_OIM_H_*/
+#endif/* MSN_OIM_H*/
--- a/libpurple/protocols/msn/page.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/page.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_PAGE_H_
-#define _MSN_PAGE_H_
+#ifndef MSN_PAGE_H
+#define MSN_PAGE_H
 
 typedef struct _MsnPage MsnPage;
 
@@ -78,4 +78,4 @@
  */
 const char *msn_page_get_body(const MsnPage *page);
 
-#endif /* _MSN_PAGE_H_ */
+#endif /* MSN_PAGE_H */
--- a/libpurple/protocols/msn/servconn.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/servconn.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,17 +21,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SERVCONN_H_
-#define _MSN_SERVCONN_H_
+#ifndef MSN_SERVCONN_H
+#define MSN_SERVCONN_H
 
 typedef struct _MsnServConn MsnServConn;
 
-#include "session.h"
-#include "cmdproc.h"
-
-#include "proxy.h"
-#include "httpconn.h"
-
 /**
  * Connection error types.
  */
@@ -41,7 +35,6 @@
 	MSN_SERVCONN_ERROR_CONNECT,
 	MSN_SERVCONN_ERROR_WRITE,
 	MSN_SERVCONN_ERROR_READ
-
 } MsnServConnError;
 
 /**
@@ -51,8 +44,13 @@
 {
 	MSN_SERVCONN_NS,
 	MSN_SERVCONN_SB
+} MsnServConnType;
 
-} MsnServConnType;
+#include "proxy.h"
+
+#include "cmdproc.h"
+#include "httpconn.h"
+#include "session.h"
 
 /**
  * A Connection.
@@ -191,4 +189,4 @@
  */
 void msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds);
 
-#endif /* _MSN_SERVCONN_H_ */
+#endif /* MSN_SERVCONN_H */
--- a/libpurple/protocols/msn/session.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/session.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,27 +21,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SESSION_H_
-#define _MSN_SESSION_H_
+#ifndef MSN_SESSION_H
+#define MSN_SESSION_H
 
 typedef struct _MsnSession MsnSession;
 
-#include "sslconn.h"
-
-#include "user.h"
-#include "slpcall.h"
-
-#include "notification.h"
-#include "switchboard.h"
-#include "group.h"
-
-#include "nexus.h"
-#include "httpconn.h"
-#include "oim.h"
-
-#include "userlist.h"
-#include "sync.h"
-
 /**
  * Types of errors.
  */
@@ -55,7 +39,6 @@
 	MSN_ERROR_SIGN_OTHER,
 	MSN_ERROR_SERV_DOWN,
 	MSN_ERROR_SERV_UNAVAILABLE
-
 } MsnErrorType;
 
 /**
@@ -68,16 +51,26 @@
 	MSN_LOGIN_STEP_TRANSFER,
 	MSN_LOGIN_STEP_HANDSHAKE2,
 	MSN_LOGIN_STEP_AUTH_START,
-	MSN_LOGIN_STEP_AUTH,
 	MSN_LOGIN_STEP_GET_COOKIE,
 	MSN_LOGIN_STEP_AUTH_END,
 	MSN_LOGIN_STEP_SYN,
 	MSN_LOGIN_STEP_END
-
 } MsnLoginStep;
 
 #define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END
 
+#include "group.h"
+#include "httpconn.h"
+#include "nexus.h"
+#include "notification.h"
+#include "oim.h"
+#include "slpcall.h"
+#include "sslconn.h"
+#include "switchboard.h"
+#include "sync.h"
+#include "user.h"
+#include "userlist.h"
+
 struct _MsnSession
 {
 	PurpleAccount *account;
@@ -238,4 +231,4 @@
 void msn_session_report_user(MsnSession *session,const char *passport,
 							const char *msg,PurpleMessageFlags flags);
 
-#endif /* _MSN_SESSION_H_ */
+#endif /* MSN_SESSION_H */
--- a/libpurple/protocols/msn/slp.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/slp.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,13 +21,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SLP_H_
-#define _MSN_SLP_H_
+#ifndef MSN_SLP_H
+#define MSN_SLP_H
 
+#include "internal.h"
+
+#include "ft.h"
+#include "session.h"
 #include "slpcall.h"
-#include "session.h"
-#include "internal.h"
-#include "ft.h"
 
 MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink,
 							  const char *body);
@@ -45,4 +46,4 @@
 
 void msn_queue_buddy_icon_request(MsnUser *user);
 
-#endif /* _MSN_SLP_H_ */
+#endif /* MSN_SLP_H */
--- a/libpurple/protocols/msn/slpcall.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/slpcall.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,26 +21,26 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SLPCALL_H_
-#define _MSN_SLPCALL_H_
+#ifndef MSN_SLPCALL_H
+#define MSN_SLPCALL_H
+
+typedef struct _MsnSlpCall MsnSlpCall;
+
+typedef enum
+{
+	MSN_SLPCALL_ANY,
+	MSN_SLPCALL_DC
+} MsnSlpCallType;
 
 #include "internal.h"
+
 #include "ft.h"
 
-typedef struct _MsnSlpCall MsnSlpCall;
-
 #include "slplink.h"
 
 /* The official client seems to timeout slp calls after 5 minutes */
 #define MSN_SLPCALL_TIMEOUT 300
 
-typedef enum
-{
-	MSN_SLPCALL_ANY,
-	MSN_SLPCALL_DC
-
-} MsnSlpCallType;
-
 struct _MsnSlpCall
 {
 	/* Our parent slplink */
@@ -95,4 +95,4 @@
 						 int app_id, const char *context);
 void msn_slpcall_close(MsnSlpCall *slpcall);
 
-#endif /* _MSN_SLPCALL_H_ */
+#endif /* MSN_SLPCALL_H */
--- a/libpurple/protocols/msn/slplink.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/slplink.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,21 +21,19 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SLPLINK_H_
-#define _MSN_SLPLINK_H_
+#ifndef MSN_SLPLINK_H
+#define MSN_SLPLINK_H
 
 typedef struct _MsnSlpLink MsnSlpLink;
 
+#include "ft.h"
+
 #include "directconn.h"
+#include "session.h"
 #include "slpcall.h"
 #include "slpmsg.h"
-
 #include "switchboard.h"
 
-#include "ft.h"
-
-#include "session.h"
-
 typedef void (*MsnSlpCb)(MsnSlpCall *slpcall,
 						 const guchar *data, gsize size);
 typedef void (*MsnSlpEndCb)(MsnSlpCall *slpcall, MsnSession *session);
@@ -95,4 +93,4 @@
 
 MsnSlpCall *msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
 
-#endif /* _MSN_SLPLINK_H_ */
+#endif /* MSN_SLPLINK_H */
--- a/libpurple/protocols/msn/soap.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/soap.h	Sat Feb 06 15:45:51 2010 +0900
@@ -22,17 +22,18 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
  */
+#ifndef MSN_SOAP_H
+#define MSN_SOAP_H
 
-#ifndef _MSN_SOAP_H
-#define _MSN_SOAP_H
+typedef struct _MsnSoapMessage MsnSoapMessage;
+
+#include <glib.h>
+
+#include "xmlnode.h"
 
 #include "session.h"
 #include "sslconn.h"
-#include "xmlnode.h"
 
-#include <glib.h>
-
-typedef struct _MsnSoapMessage MsnSoapMessage;
 typedef void (*MsnSoapCallback)(MsnSoapMessage *request,
 	MsnSoapMessage *response, gpointer cb_data);
 
@@ -48,4 +49,4 @@
 	const char *host, const char *path, gboolean secure,
 	MsnSoapCallback cb, gpointer cb_data);
 
-#endif
+#endif /* MSN_SOAP_H */
--- a/libpurple/protocols/msn/state.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/state.c	Sat Feb 06 15:45:51 2010 +0900
@@ -23,6 +23,7 @@
  */
 
 #include "internal.h"
+
 #include "core.h"
 
 #include "msn.h"
@@ -86,78 +87,6 @@
 	return result;
 }
 
-/* parse CurrentMedia string */
-gboolean
-msn_parse_currentmedia(const char *cmedia, CurrentMedia *media)
-{
-	char **cmedia_array;
-	int strings = 0;
-	gboolean parsed = FALSE;
-
-	if ((cmedia == NULL) || (*cmedia == '\0')) {
-		purple_debug_info("msn", "No currentmedia string\n");
-		return FALSE;
-	}
-
-	purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia);
-
-	cmedia_array = g_strsplit(cmedia, "\\0", 0);
-
-	/*
-	 * 0: Application
-	 * 1: 'Music'/'Games'/'Office'
-	 * 2: '1' if enabled, '0' if not
-	 * 3: Format (eg. {0} by {1})
-	 * 4: Title
-	 * If 'Music':
-	 *  5: Artist
-	 *  6: Album
-	 *  7: ?
-	 */
-#if GLIB_CHECK_VERSION(2,6,0)
-	strings  = g_strv_length(cmedia_array);
-#else
-	while (cmedia_array[++strings] != NULL);
-#endif
-
-	if (strings >= 4 && !strcmp(cmedia_array[2], "1")) {
-		parsed = TRUE;
-
-		if (!strcmp(cmedia_array[1], "Music"))
-			media->type = CURRENT_MEDIA_MUSIC;
-		else if (!strcmp(cmedia_array[1], "Games"))
-			media->type = CURRENT_MEDIA_GAMES;
-		else if (!strcmp(cmedia_array[1], "Office"))
-			media->type = CURRENT_MEDIA_OFFICE;
-		else
-			media->type = CURRENT_MEDIA_UNKNOWN;
-
-		g_free(media->title);
-		if (strings == 4) {
-			media->title = g_strdup(cmedia_array[3]);
-		} else {
-			media->title = g_strdup(cmedia_array[4]);
-		}
-
-		g_free(media->artist);
-		if (strings > 5)
-			media->artist = g_strdup(cmedia_array[5]);
-		else
-			media->artist = NULL;
-
-		g_free(media->album);
-		if (strings > 6)
-			media->album = g_strdup(cmedia_array[6]);
-		else
-			media->album = NULL;
-
-	}
-
-	g_strfreev(cmedia_array);
-
-	return parsed;
-}
-
 /* get the CurrentMedia info from the XML string */
 char *
 msn_get_currentmedia(char *xml_str, gsize len)
--- a/libpurple/protocols/msn/state.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/state.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_STATE_H_
-#define _MSN_STATE_H_
+#ifndef MSN_STATE_H
+#define MSN_STATE_H
 
 /**
  * Away types.
@@ -38,7 +38,6 @@
 	MSN_LUNCH   = 7,
 	MSN_OFFLINE = 8,
 	MSN_HIDDEN  = 9
-
 } MsnAwayType;
 
 /**
@@ -61,15 +60,12 @@
 
 void msn_set_psm(MsnSession *session);
 
-/* Parse CurrentMedia string */
-gboolean msn_parse_currentmedia(const char *cmedia, CurrentMedia *media);
-
 /* Get the CurrentMedia info from the XML string */
-char * msn_get_currentmedia(char *xml_str,gsize len);
+char *msn_get_currentmedia(char *xml_str, gsize len);
 
 /*get the PSM info from the XML string*/
-char * msn_get_psm(char *xml_str,gsize len);
+char *msn_get_psm(char *xml_str, gsize len);
 
 MsnAwayType msn_state_from_account(PurpleAccount *account);
 
-#endif /* _MSN_STATE_H_ */
+#endif /* MSN_STATE_H */
--- a/libpurple/protocols/msn/switchboard.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/switchboard.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,20 +21,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SWITCHBOARD_H_
-#define _MSN_SWITCHBOARD_H_
+#ifndef MSN_SWITCHBOARD_H
+#define MSN_SWITCHBOARD_H
 
 typedef struct _MsnSwitchBoard MsnSwitchBoard;
 
-#include "conversation.h"
-
-#include "msg.h"
-#include "user.h"
-
-#include "servconn.h"
-
-#include "slplink.h"
-
 /**
  * A switchboard error.
  */
@@ -48,7 +39,6 @@
 	MSN_SB_ERROR_TOO_FAST, /**< We are sending too fast */
 	MSN_SB_ERROR_AUTHFAILED, /**< Authentication failed joining the switchboard session */
 	MSN_SB_ERROR_UNKNOWN /**< An unknown error occurred. */
-
 } MsnSBErrorType;
 
 /**
@@ -58,8 +48,14 @@
 {
 	MSN_SB_FLAG_IM = 0x01, /**< This switchboard is being used for a conversation. */
 	MSN_SB_FLAG_FT = 0x02  /**< This switchboard is being used for file transfer. */
+} MsnSBFlag;
 
-} MsnSBFlag;
+#include "conversation.h"
+
+#include "msg.h"
+#include "servconn.h"
+#include "slplink.h"
+#include "user.h"
 
 /**
  * A switchboard.
@@ -290,4 +286,4 @@
 void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
                               const char *data);
 
-#endif /* _MSN_SWITCHBOARD_H_ */
+#endif /* MSN_SWITCHBOARD_H */
--- a/libpurple/protocols/msn/sync.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/sync.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_SYNC_H_
-#define _MSN_SYNC_H_
+#ifndef MSN_SYNC_H
+#define MSN_SYNC_H
 
 typedef struct _MsnSync MsnSync;
 
@@ -51,7 +51,7 @@
 void msn_sync_init(void);
 void msn_sync_end(void);
 
-MsnSync * msn_sync_new(MsnSession *session);
+MsnSync *msn_sync_new(MsnSession *session);
 void msn_sync_destroy(MsnSync *sync);
 
-#endif /* _MSN_SYNC_H_ */
+#endif /* MSN_SYNC_H */
--- a/libpurple/protocols/msn/table.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/table.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,8 +21,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_TABLE_H_
-#define _MSN_TABLE_H_
+#ifndef MSN_TABLE_H
+#define MSN_TABLE_H
 
 typedef struct _MsnTable MsnTable;
 
@@ -50,4 +50,4 @@
 void msn_table_add_error(MsnTable *table, char *answer, MsnErrorCb cb);
 void msn_table_add_msg_type(MsnTable *table, char *type, MsnMsgTypeCb cb);
 
-#endif /* _MSN_TABLE_H_ */
+#endif /* MSN_TABLE_H */
--- a/libpurple/protocols/msn/transaction.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/transaction.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,13 +21,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_TRANSACTION_H
-#define _MSN_TRANSACTION_H
+#ifndef MSN_TRANSACTION_H
+#define MSN_TRANSACTION_H
 
 typedef struct _MsnTransaction MsnTransaction;
 
+#include "cmdproc.h"
 #include "command.h"
-#include "cmdproc.h"
 
 typedef void (*MsnTransCb)(MsnCmdProc *cmdproc, MsnCommand *cmd);
 typedef void (*MsnTimeoutCb)(MsnCmdProc *cmdproc, MsnTransaction *trans);
@@ -79,4 +79,4 @@
 void msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb);
 void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb);
 
-#endif /* _MSN_TRANSACTION_H */
+#endif /* MSN_TRANSACTION_H */
--- a/libpurple/protocols/msn/user.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/user.c	Sat Feb 06 15:45:51 2010 +0900
@@ -67,12 +67,15 @@
 	g_free(user->passport);
 	g_free(user->friendly_name);
 	g_free(user->uid);
-	g_free(user->phone.home);
-	g_free(user->phone.work);
-	g_free(user->phone.mobile);
-	g_free(user->media.artist);
-	g_free(user->media.title);
-	g_free(user->media.album);
+	if (user->extinfo) {
+		g_free(user->extinfo->media_album);
+		g_free(user->extinfo->media_artist);
+		g_free(user->extinfo->media_title);
+		g_free(user->extinfo->phone_home);
+		g_free(user->extinfo->phone_mobile);
+		g_free(user->extinfo->phone_work);
+		g_free(user->extinfo);
+	}
 	g_free(user->statusline);
 	g_free(user->invite_message);
 
@@ -107,24 +110,24 @@
 		purple_prpl_got_user_status_deactive(account, user->passport, "mobile");
 	}
 
-	if (!offline && user->media.type != CURRENT_MEDIA_UNKNOWN) {
-		if (user->media.type == CURRENT_MEDIA_MUSIC) {
+	if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) {
+		if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) {
 			purple_prpl_got_user_status(account, user->passport, "tune",
-			                            PURPLE_TUNE_ARTIST, user->media.artist,
-			                            PURPLE_TUNE_ALBUM, user->media.album,
-			                            PURPLE_TUNE_TITLE, user->media.title,
+			                            PURPLE_TUNE_ARTIST, user->extinfo->media_artist,
+			                            PURPLE_TUNE_ALBUM, user->extinfo->media_album,
+			                            PURPLE_TUNE_TITLE, user->extinfo->media_title,
 			                            NULL);
-		} else if (user->media.type == CURRENT_MEDIA_GAMES) {
+		} else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) {
 			purple_prpl_got_user_status(account, user->passport, "tune",
-			                            "game", user->media.title,
+			                            "game", user->extinfo->media_title,
 			                            NULL);
-		} else if (user->media.type == CURRENT_MEDIA_OFFICE) {
+		} else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) {
 			purple_prpl_got_user_status(account, user->passport, "tune",
-			                            "office", user->media.title,
+			                            "office", user->extinfo->media_title,
 			                            NULL);
 		} else {
 			purple_debug_warning("msn", "Got CurrentMedia with unknown type %d.\n",
-			                     user->media.type);
+			                     user->extinfo->media_type);
 		}
 	} else {
 		purple_prpl_got_user_status_deactive(account, user->passport, "tune");
@@ -205,21 +208,6 @@
 }
 
 void
-msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *media)
-{
-	g_return_if_fail(user != NULL);
-
-	g_free(user->media.title);
-	g_free(user->media.album);
-	g_free(user->media.artist);
-
-	user->media.type   = media ? media->type : CURRENT_MEDIA_UNKNOWN;
-	user->media.title  = media ? g_strdup(media->title) : NULL;
-	user->media.artist = media ? g_strdup(media->artist) : NULL;
-	user->media.album  = media ? g_strdup(media->album) : NULL;
-}
-
-void
 msn_user_set_uid(MsnUser *user, const char *uid)
 {
 	g_return_if_fail(user != NULL);
@@ -229,7 +217,7 @@
 }
 
 void
-msn_user_set_op(MsnUser *user, int list_op)
+msn_user_set_op(MsnUser *user, MsnListOp list_op)
 {
 	g_return_if_fail(user != NULL);
 
@@ -237,7 +225,7 @@
 }
 
 void
-msn_user_unset_op(MsnUser *user, int list_op)
+msn_user_unset_op(MsnUser *user, MsnListOp list_op)
 {
 	g_return_if_fail(user != NULL);
 
@@ -366,8 +354,15 @@
 {
 	g_return_if_fail(user != NULL);
 
-	g_free(user->phone.home);
-	user->phone.home = g_strdup(number);
+	if (!number && !user->extinfo)
+		return;
+
+	if (user->extinfo)
+		g_free(user->extinfo->phone_home);
+	else
+		user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+
+	user->extinfo->phone_home = g_strdup(number);
 }
 
 void
@@ -375,8 +370,15 @@
 {
 	g_return_if_fail(user != NULL);
 
-	g_free(user->phone.work);
-	user->phone.work = g_strdup(number);
+	if (!number && !user->extinfo)
+		return;
+
+	if (user->extinfo)
+		g_free(user->extinfo->phone_work);
+	else
+		user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+
+	user->extinfo->phone_work = g_strdup(number);
 }
 
 void
@@ -384,8 +386,15 @@
 {
 	g_return_if_fail(user != NULL);
 
-	g_free(user->phone.mobile);
-	user->phone.mobile = g_strdup(number);
+	if (!number && !user->extinfo)
+		return;
+
+	if (user->extinfo)
+		g_free(user->extinfo->phone_mobile);
+	else
+		user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+
+	user->extinfo->phone_mobile = g_strdup(number);
 }
 
 void
@@ -460,7 +469,7 @@
 {
 	g_return_val_if_fail(user != NULL, NULL);
 
-	return user->phone.home;
+	return user->extinfo ? user->extinfo->phone_home : NULL;
 }
 
 const char *
@@ -468,7 +477,7 @@
 {
 	g_return_val_if_fail(user != NULL, NULL);
 
-	return user->phone.work;
+	return user->extinfo ? user->extinfo->phone_work : NULL;
 }
 
 const char *
@@ -476,7 +485,7 @@
 {
 	g_return_val_if_fail(user != NULL, NULL);
 
-	return user->phone.mobile;
+	return user->extinfo ? user->extinfo->phone_mobile : NULL;
 }
 
 guint
--- a/libpurple/protocols/msn/user.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/user.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,16 +21,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_USER_H_
-#define _MSN_USER_H_
+#ifndef MSN_USER_H
+#define MSN_USER_H
 
 typedef struct _MsnUser  MsnUser;
 
-#include "session.h"
-#include "object.h"
-
-#include "userlist.h"
-
 typedef enum
 {
 	MSN_NETWORK_UNKNOWN      = 0x00,
@@ -53,13 +48,29 @@
 	CURRENT_MEDIA_OFFICE
 } CurrentMediaType;
 
-typedef struct _CurrentMedia
+#include "object.h"
+#include "session.h"
+#include "userlist.h"
+
+/**
+ * Contains optional info about a user that is fairly uncommon.  We
+ * put this info in in a separate struct to save memory because we
+ * allocate an MsnUser struct for each buddy, but we generally only
+ * need this information for a small percentage of our buddies
+ * (usually less than 1%).  Putting it in a separate struct saves
+ * makes MsnUser smaller by the size of a few pointers.
+ */
+typedef struct _MsnUserExtendedInfo
 {
-	CurrentMediaType type;     /**< Type.   */
-	char *title;    /**< Title.  */
-	char *artist;   /**< Artist. */
-	char *album;    /**< Album.  */
-} CurrentMedia;
+	CurrentMediaType media_type; /**< Type of the user's current media.   */
+	char *media_title;  /**< Title of the user's current media.  */
+	char *media_artist; /**< Artist of the user's current media. */
+	char *media_album;  /**< Album of the user's current media.  */
+
+	char *phone_home;   /**< E.T. uses this.                     */
+	char *phone_work;   /**< Work phone number.                  */
+	char *phone_mobile; /**< Mobile phone number.                */
+} MsnUserExtendedInfo;
 
 /**
  * A user.
@@ -71,21 +82,14 @@
 	char *passport;         /**< The passport account.          */
 	char *friendly_name;    /**< The friendly name.             */
 
-	char * uid;				/*< User Id							*/
+	char *uid;              /*< User ID                         */
 
 	const char *status;     /**< The state of the user.         */
 	char *statusline;       /**< The state of the user.         */
-	CurrentMedia media;     /**< Current media of the user.     */
 
 	gboolean idle;          /**< The idle state of the user.    */
 
-	struct
-	{
-		char *home;         /**< Home phone number.             */
-		char *work;         /**< Work phone number.             */
-		char *mobile;       /**< Mobile phone number.           */
-
-	} phone;
+	MsnUserExtendedInfo *extinfo; /**< Extended info for the user. */
 
 	gboolean authorized;    /**< Authorized to add this user.   */
 	gboolean mobile;        /**< Signed up with MSN Mobile.     */
@@ -101,10 +105,13 @@
 
 	MsnNetwork networkid;   /**< The user's network             */
 
-	int list_op;            /**< Which lists the user is in     */
+	MsnListOp list_op;      /**< Which lists the user is in     */
 
-	guint membership_id[5];	/**< The membershipId sent by the contacts server,
-				     indexed by the list it belongs to		*/
+	/**
+	 * The membershipId for this buddy on our pending list.  Sent by
+	 * the contact's server
+	 */
+	guint member_id_on_pending_list;
 
 	char *invite_message;   /**< Invite message of user request */
 };
@@ -151,14 +158,6 @@
   */
 void msn_user_set_statusline(MsnUser *user, const char *statusline);
 
- /**
-  *  Sets the current media of user.
-  *
-  *  @param user   The user.
-  *  @param cmedia Current media.
-  */
-void msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *cmedia);
-
 /**
  * Sets the new state of user.
  *
@@ -394,19 +393,16 @@
 /**
  * check to see if user is online
  */
-gboolean
-msn_user_is_online(PurpleAccount *account, const char *name);
+gboolean msn_user_is_online(PurpleAccount *account, const char *name);
 
 /**
  * check to see if user is Yahoo User
  */
-gboolean
-msn_user_is_yahoo(PurpleAccount *account ,const char *name);
+gboolean msn_user_is_yahoo(PurpleAccount *account ,const char *name);
 
-void msn_user_set_op(MsnUser *user, int list_op);
-void msn_user_unset_op(MsnUser *user, int list_op);
+void msn_user_set_op(MsnUser *user, MsnListOp list_op);
+void msn_user_unset_op(MsnUser *user, MsnListOp list_op);
 
 /*@}*/
 
-
-#endif /* _MSN_USER_H_ */
+#endif /* MSN_USER_H */
--- a/libpurple/protocols/msn/userlist.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/userlist.c	Sat Feb 06 15:45:51 2010 +0900
@@ -119,26 +119,16 @@
 	if (group_id == NULL)
 		return FALSE;
 
-	if (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp))
-		return TRUE;
-
-	return FALSE;
+	return (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp)) != NULL;
 }
 
 gboolean
 msn_userlist_user_is_in_list(MsnUser *user, MsnListId list_id)
 {
-	int list_op;
-
 	if (user == NULL)
 		return FALSE;
 
-	list_op = 1 << list_id;
-
-	if (user->list_op & list_op)
-		return TRUE;
-	else
-		return FALSE;
+	return (user->list_op & (1 << list_id));
 }
 
 /**************************************************************************
@@ -147,7 +137,7 @@
 
 void
 msn_got_lst_user(MsnSession *session, MsnUser *user,
-				 int list_op, GSList *group_ids)
+				 MsnListOp list_op, GSList *group_ids)
 {
 	PurpleConnection *gc;
 	PurpleAccount *account;
@@ -344,14 +334,10 @@
 
 	for (l = userlist->users; l != NULL; l = l->next) {
 		MsnUser *user = (MsnUser *)l->data;
+		const char *user_number = msn_user_get_mobile_phone(user);
 
-		if (user->phone.mobile == NULL) {
-			continue;
-		}
-
-		if (!g_ascii_strcasecmp(number, user->phone.mobile)) {
+		if (user_number && !g_ascii_strcasecmp(number, user_number))
 			return user;
-		}
 	}
 
 	return NULL;
--- a/libpurple/protocols/msn/userlist.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/msn/userlist.h	Sat Feb 06 15:45:51 2010 +0900
@@ -21,24 +21,23 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#ifndef _MSN_USERLIST_H_
-#define _MSN_USERLIST_H_
+#ifndef MSN_USERLIST_H
+#define MSN_USERLIST_H
 
 typedef struct _MsnUserList MsnUserList;
 
-#include "user.h"
-#include "group.h"
-
 typedef enum
 {
-	MSN_LIST_FL,
-	MSN_LIST_AL,
-	MSN_LIST_BL,
-	MSN_LIST_RL,
-	MSN_LIST_PL
-
+	MSN_LIST_FL, /**< Forward list */
+	MSN_LIST_AL, /**< Allow list */
+	MSN_LIST_BL, /**< Block list */
+	MSN_LIST_RL, /**< Reverse list */
+	MSN_LIST_PL  /**< Pending list */
 } MsnListId;
 
+#include "group.h"
+#include "msn.h"
+#include "user.h"
 
 struct _MsnUserList
 {
@@ -57,7 +56,7 @@
 gboolean msn_userlist_user_is_in_list(MsnUser *user, MsnListId list_id);
 
 void msn_got_lst_user(MsnSession *session, MsnUser *user,
-					  int list_op, GSList *group_ids);
+					  MsnListOp list_op, GSList *group_ids);
 
 MsnUserList *msn_userlist_new(MsnSession *session);
 void msn_userlist_destroy(MsnUserList *userlist);
@@ -102,4 +101,4 @@
 
 void msn_userlist_load(MsnSession *session);
 
-#endif /* _MSN_USERLIST_H_ */
+#endif /* MSN_USERLIST_H */
--- a/libpurple/protocols/myspace/myspace.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/myspace/myspace.c	Sat Feb 06 15:45:51 2010 +0900
@@ -251,7 +251,6 @@
 	MsimMessage *msg;
 	const gchar *from_username;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(who != NULL, FALSE);
 	g_return_val_if_fail(text != NULL, FALSE);
 
@@ -344,8 +343,6 @@
 {
 	guint rid;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), -1);
-
 	rid = session->next_rid++;
 
 	g_hash_table_insert(session->user_lookup_cb, GUINT_TO_POINTER(rid), cb);
@@ -394,8 +391,6 @@
 	gc = purple_account_get_connection(account);
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), NULL);
-
 	display_name = headline = NULL;
 
 	/* Retrieve display name and/or headline, depending on user preference. */
@@ -442,11 +437,9 @@
 		MsimSession *session;
 		PurpleAccount *account = purple_buddy_get_account(buddy);
 		PurpleConnection *gc = purple_account_get_connection(account);
- 
+
 		session = (MsimSession *)gc->proto_data;
 
-		g_return_if_fail(MSIM_SESSION_VALID(session));
-
 		/* TODO: if (full), do something different? */
 
 		/* TODO: request information? have to figure out how to do
@@ -694,7 +687,6 @@
 	gsize nc_len;
 	gboolean ret;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE);
@@ -783,7 +775,6 @@
 static gboolean
 msim_is_username_set(MsimSession *session, MsimMessage *msg)
 {
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 	g_return_val_if_fail(session->gc != NULL, FALSE);
 
@@ -842,8 +833,6 @@
 
 	session = (MsimSession *)data;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
-
 	delta = time(NULL) - session->last_comm;
 
 	/* purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); */
@@ -970,11 +959,6 @@
 
 	session = (MsimSession *)data;
 
-	if (!MSIM_SESSION_VALID(session)) {
-		purple_debug_info("msim", "msim_check_inbox: session invalid, stopping the mail check.\n");
-		return FALSE;
-	}
-
 	purple_debug_info("msim", "msim_check_inbox: checking mail\n");
 	g_return_val_if_fail(msim_send(session,
 			"persist", MSIM_TYPE_INTEGER, 1,
@@ -1215,8 +1199,6 @@
 {
 	MsimMessage *body;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
-
 	/* Set display name to username (otherwise will show email address) */
 	purple_connection_set_display_name(session->gc, session->username);
 
@@ -1382,7 +1364,6 @@
 	gchar *username;
 	gchar *unrecognized_msg;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	/* Helpfully looked up by msim_incoming_resolve() for us. */
@@ -1577,7 +1558,6 @@
 	gchar *msg_text, *username;
 	gboolean rc;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	msg_text = msim_msg_get_string(msg, "msg");
@@ -1797,7 +1777,6 @@
 	gpointer data;
 	guint rid, cmd, dsn, lid;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	msim_store_user_info(session, msg, NULL);
@@ -1848,7 +1827,6 @@
 	gchar *errmsg, *full_errmsg;
 	guint err;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	err = msim_msg_get_integer(msg, "err");
@@ -1962,7 +1940,6 @@
 	gchar *username;
 	MsimMessage *msg, *body;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
 	g_return_if_fail(userinfo != NULL);
 
 	body = msim_msg_get_dictionary(userinfo, "body");
@@ -1998,7 +1975,6 @@
 static gboolean
 msim_preprocess_incoming(MsimSession *session, MsimMessage *msg)
 {
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) {
@@ -2071,7 +2047,6 @@
 	}
 
 	g_return_if_fail(cond == PURPLE_INPUT_READ);
-	g_return_if_fail(MSIM_SESSION_VALID(session));
 
 	/* Mark down that we got data, so we don't timeout. */
 	session->last_comm = time(NULL);
@@ -2264,6 +2239,13 @@
 	}
 }
 
+static void
+msim_buddy_free(PurpleBuddy *buddy)
+{
+	msim_user_free(purple_buddy_get_protocol_data(buddy));
+	purple_buddy_set_protocol_data(buddy, NULL);
+}
+
 /**
  * Close the connection.
  *
@@ -2272,22 +2254,30 @@
 static void
 msim_close(PurpleConnection *gc)
 {
+	GSList *buddies;
 	MsimSession *session;
 
 	if (gc == NULL) {
 		return;
 	}
 
+	/*
+	 * Free our protocol-specific buddy data.  It almost seems like libpurple
+	 * should call our buddy_free prpl callback so that we don't need to do
+	 * this... but it doesn't, so we do.
+	 */
+	buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
+	while (buddies != NULL) {
+		msim_buddy_free(buddies->data);
+		buddies = g_slist_delete_link(buddies, buddies);
+	}
+
 	session = (MsimSession *)gc->proto_data;
 	if (session == NULL)
 		return;
 
 	gc->proto_data = NULL;
 
-	if (!MSIM_SESSION_VALID(session)) {
-		return;
-	}
-
 	if (session->gc->inpa) {
 		purple_input_remove(session->gc->inpa);
 	}
@@ -2329,8 +2319,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), -1);
-
 	message_msim = html_to_msim_markup(session, message);
 
 	if (msim_send_bm(session, who, message_msim, MSIM_BM_ACTION_OR_IM_DELAYABLE)) {
@@ -2371,8 +2359,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), 0);
-
 	switch (state) {
 		case PURPLE_TYPING:
 			typing_str = "%typing%";
@@ -2402,8 +2388,6 @@
 	PurpleNotifyUserInfo *user_info;
 	MsimUser *user;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	/* Get user{name,id} from msim_get_info, passed as an MsimMessage for
 	   orthogonality. */
 	msg = (MsimMessage *)data;
@@ -2461,8 +2445,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	/* Obtain uid of buddy. */
 	user = msim_find_user(session, username);
 
@@ -2496,7 +2478,6 @@
 static void
 msim_set_status_code(MsimSession *session, guint status_code, gchar *statstring)
 {
-	g_return_if_fail(MSIM_SESSION_VALID(session));
 	g_return_if_fail(statstring != NULL);
 
 	purple_debug_info("msim", "msim_set_status_code: going to set status to code=%d,str=%s\n",
@@ -2529,8 +2510,6 @@
 
 	session = (MsimSession *)account->gc->proto_data;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	type = purple_status_get_type(status);
 	pres = purple_status_get_presence(status);
 
@@ -2594,8 +2573,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	status = purple_account_get_active_status(session->account);
 
 	if (time == 0) {
@@ -2734,13 +2711,6 @@
 	msim_update_blocklist_for_buddy(session, name, TRUE, FALSE);
 }
 
-static void
-msim_buddy_free(PurpleBuddy *buddy)
-{
-	msim_user_free(purple_buddy_get_protocol_data(buddy));
-	purple_buddy_set_protocol_data(buddy, NULL);
-}
-
 /**
  * Remove a buddy from the user's buddy list.
  */
@@ -2993,8 +2963,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), -1);
-
 	/* Loop until all data is sent, or a failure occurs. */
 	total_bytes_sent = 0;
 	do {
@@ -3029,7 +2997,6 @@
 {
 	size_t len;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	purple_debug_info("msim", "msim_send_raw: writing <%s>\n", msg);
--- a/libpurple/protocols/myspace/session.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/myspace/session.c	Sat Feb 06 15:45:51 2010 +0900
@@ -76,8 +76,6 @@
 void
 msim_session_destroy(MsimSession *session)
 {
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	session->magic = -1;
 
 	g_free(session->rxbuf);
--- a/libpurple/protocols/myspace/session.h	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/myspace/session.h	Sat Feb 06 15:45:51 2010 +0900
@@ -54,9 +54,6 @@
 	guint inbox_handle;                 /**< The handle for the mail check timer */
 } MsimSession;
 
-/* Check if an MsimSession is valid */
-#define MSIM_SESSION_VALID(s) (session != NULL && session->magic == MSIM_SESSION_STRUCT_MAGIC)
-
 MsimSession *msim_session_new(PurpleAccount *acct);
 void msim_session_destroy(MsimSession *session);
 
--- a/libpurple/protocols/myspace/user.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/myspace/user.c	Sat Feb 06 15:45:51 2010 +0900
@@ -92,16 +92,13 @@
 msim_find_user(MsimSession *session, const gchar *username)
 {
 	PurpleBuddy *buddy;
-	MsimUser *user;
 
 	buddy = purple_find_buddy(session->account, username);
 	if (!buddy) {
 		return NULL;
 	}
 
-	user = msim_get_user_from_buddy(buddy, TRUE);
-
-	return user;
+	return msim_get_user_from_buddy(buddy, TRUE);
 }
 
 /**
@@ -355,14 +352,6 @@
 			return;
 		}
 
-		if (user->temporary_user) {
-			/* This user will be destroyed soon; don't try to look up its image or avatar,
-			 * since that won't return immediately and we will end up accessing freed data.
-			 */
-			g_free(value_str);
-			return;
-		}
-
 		g_free(user->image_url);
 
 		user->image_url = value_str;
@@ -425,7 +414,6 @@
 	gchar *username;
 	MsimMessage *body, *body_node;
 
-	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
 	body = msim_msg_get_dictionary(msg, "body");
@@ -577,7 +565,6 @@
 	gchar *field_name;
 	guint rid, cmd, dsn, lid;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
 	g_return_if_fail(user != NULL);
 	/* Callback can be null to not call anything, just lookup & store information. */
 	/*g_return_if_fail(cb != NULL);*/
@@ -637,8 +624,6 @@
 
 	purple_debug_info("msim","username_is_set made\n");
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	cmd = msim_msg_get_integer(userinfo, "cmd");
 	dsn = msim_msg_get_integer(userinfo, "dsn");
 	uid = msim_msg_get_integer(userinfo, "uid");
@@ -718,7 +703,6 @@
 	MsimMessage *body;
 	guint rid;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
 	g_return_if_fail(username != NULL);
 	g_return_if_fail(cb != NULL);
 
@@ -765,9 +749,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
-
 	user_msg = msim_msg_new(
 			"user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
 			NULL);
@@ -794,7 +775,6 @@
 	purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
 
 	msg = (MsimMessage *)data;
-	g_return_if_fail(MSIM_SESSION_VALID(session));
 	g_return_if_fail(msg != NULL);
 
 	username = msim_msg_get_string(msg, "user");
@@ -862,8 +842,6 @@
 
 	session = (MsimSession *)gc->proto_data;
 
-	g_return_if_fail(MSIM_SESSION_VALID(session));
-
 	purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
 
 	user_msg = msim_msg_new(
--- a/libpurple/protocols/oscar/libaim.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/libpurple/protocols/oscar/libaim.c	Sat Feb 06 15:45:51 2010 +0900
@@ -32,8 +32,7 @@
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
 	/* The mimimum icon size below is not needed in AIM 6.0 */
-	{"gif,jpeg,bmp,ico", 48, 48, 50, 50, 7168,
-		PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY},	/* icon_spec */
+	{"gif,jpeg,bmp,ico", 0, 0, 100, 100, 7168, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
 	oscar_list_icon_aim,		/* list_icon */
 	oscar_list_emblem,		/* list_emblems */
 	oscar_status_text,		/* status_text */
--- a/pidgin/gtkblist-theme-loader.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/gtkblist-theme-loader.c	Sat Feb 06 15:45:51 2010 +0900
@@ -58,6 +58,20 @@
 	return pidgin_theme_font_new(font, &color);
 }
 
+static GdkColor *
+parse_color(xmlnode *node, const char *tag)
+{
+	const char *temp = xmlnode_get_attrib(node, tag);
+	GdkColor color;
+
+	if (temp && gdk_color_parse(temp, &color)) {
+		gdk_colormap_alloc_color(gdk_colormap_get_system(), &color, FALSE, TRUE);
+		return gdk_color_copy(&color);
+	} else {
+		return NULL;
+	}
+}
+
 static PurpleTheme *
 pidgin_blist_loader_build(const gchar *dir)
 {
@@ -65,7 +79,7 @@
 	gchar *filename_full, *data = NULL;
 	const gchar *temp, *name;
 	gboolean success = TRUE;
-	GdkColor bgcolor, expanded_bgcolor, collapsed_bgcolor, contact_color;
+	GdkColor *bgcolor, *expanded_bgcolor, *collapsed_bgcolor, *contact_color;
 	PidginThemeFont *expanded, *collapsed, *contact, *online, *away, *offline, *idle, *message, *message_nick_said, *status;
 	PidginBlistLayout layout;
 	PidginBlistTheme *theme;
@@ -119,14 +133,10 @@
 		purple_debug_warning("gtkblist-theme-loader", "Missing attribute or problem with the root element\n");
 
 	if (success) {
-		if ((success = (sub_node = xmlnode_get_child(root_node, "blist")) != NULL)) {
-
-			if ((temp = xmlnode_get_attrib(sub_node, "color")) != NULL && gdk_color_parse(temp, &bgcolor))
-				gdk_colormap_alloc_color(gdk_colormap_get_system(), &bgcolor, FALSE, TRUE);
-			else
-				memset(&bgcolor, 0, sizeof(GdkColor));
-
-		} else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <blist>.\n");
+		if ((success = (sub_node = xmlnode_get_child(root_node, "blist")) != NULL))
+			bgcolor = parse_color(sub_node, "color");
+		else 
+			purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <blist>.\n");
 	}
 
 	/* <groups> */
@@ -134,26 +144,17 @@
 		if ((success = (sub_node = xmlnode_get_child(root_node, "groups")) != NULL
 			     && (sub_sub_node = xmlnode_get_child(sub_node, "expanded")) != NULL)) {
 			expanded = pidgin_theme_font_parse(sub_sub_node);
-
-			if ((temp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(temp, &expanded_bgcolor))
-				gdk_colormap_alloc_color(gdk_colormap_get_system(), &expanded_bgcolor, FALSE, TRUE);
-			else
-				memset(&expanded_bgcolor, 0, sizeof(GdkColor));
-
-		} else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <expanded>.\n");
+			expanded_bgcolor = parse_color(sub_sub_node, "background");
+		} else
+			purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <expanded>.\n");
 	}
 
 	if (success) {
 		if ((success = sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "collapsed")) != NULL)) {
-
 			collapsed = pidgin_theme_font_parse(sub_sub_node);
-
-			if ((temp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(temp, &collapsed_bgcolor))
-				gdk_colormap_alloc_color(gdk_colormap_get_system(), &collapsed_bgcolor, FALSE, TRUE);
-			else
-				memset(&collapsed_bgcolor, 0, sizeof(GdkColor));
-
-		} else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <collapsed>.\n");
+			collapsed_bgcolor = parse_color(sub_sub_node, "background");
+		} else
+			purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <groups> <collapsed>.\n");
 	}
 
 	/* <buddys> */
@@ -172,13 +173,10 @@
 	}
 
 	if (success) {
-		if ((success = (sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "background")) != NULL))) {
-			if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), &contact_color))
-				gdk_colormap_alloc_color(gdk_colormap_get_system(), &contact_color, FALSE, TRUE);
-			else
-				memset(&contact_color, 0, sizeof(GdkColor));
-
-		} else purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <buddys> <background>.\n");
+		if ((success = (sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "background")) != NULL)))
+			contact_color = parse_color(sub_sub_node, "color");
+		else
+			purple_debug_warning("gtkblist-theme-loader", "Missing or problem with tags: <buddys> <background>.\n");
 	}
 
 	for (i = 0; success && lookups[i].tag; i++) {
@@ -201,13 +199,13 @@
 			"image", xmlnode_get_attrib(root_node, "image"),
 			"directory", dir,
 			"description", data,
-			"background-color", &bgcolor,
+			"background-color", bgcolor,
 			"layout", &layout,
-			"expanded-color", &expanded_bgcolor,
+			"expanded-color", expanded_bgcolor,
 			"expanded-text", expanded,
-			"collapsed-color", &collapsed_bgcolor,
+			"collapsed-color", collapsed_bgcolor,
 			"collapsed-text", collapsed,
-			"contact-color", &contact_color,
+			"contact-color", contact_color,
 			"contact", contact,
 			"online", online,
 			"away", away,
@@ -235,6 +233,15 @@
 		theme = NULL;
 	}
 
+	if (bgcolor)
+		gdk_color_free(bgcolor);
+	if (expanded_bgcolor)
+		gdk_color_free(expanded_bgcolor);
+	if (collapsed_bgcolor)
+		gdk_color_free(collapsed_bgcolor);
+	if (contact_color)
+		gdk_color_free(contact_color);
+
 	return PURPLE_THEME(theme);
 }
 
--- a/pidgin/gtkblist-theme.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/gtkblist-theme.c	Sat Feb 06 15:45:51 2010 +0900
@@ -133,7 +133,7 @@
 	copy->font  = g_strdup(pair->font);
 	strncpy(copy->color, pair->color, sizeof(copy->color) - 1);
 	if (pair->gdkcolor)
-		copy->gdkcolor = gdk_color_copy(pair->gdkcolor);
+		copy->gdkcolor = pair->gdkcolor ? gdk_color_copy(pair->gdkcolor) : NULL;
 	return copy;
 }
 
@@ -704,7 +704,7 @@
 
 	if (priv->bgcolor)
 		gdk_color_free(priv->bgcolor);
-	priv->bgcolor = gdk_color_copy(color);
+	priv->bgcolor = color ? gdk_color_copy(color) : NULL;
 }
 
 void
@@ -743,7 +743,7 @@
 
 	if (priv->expanded_color)
 		gdk_color_free(priv->expanded_color);
-	priv->expanded_color = gdk_color_copy(color);
+	priv->expanded_color = color ? gdk_color_copy(color) : NULL;
 }
 
 void
@@ -770,7 +770,7 @@
 
 	if (priv->collapsed_color)
 		gdk_color_free(priv->collapsed_color);
-	priv->collapsed_color = gdk_color_copy(color);
+	priv->collapsed_color = color ? gdk_color_copy(color) : NULL;
 }
 
 void
@@ -797,7 +797,7 @@
 
 	if (priv->contact_color)
 		gdk_color_free(priv->contact_color);
-	priv->contact_color = gdk_color_copy(color);
+	priv->contact_color = color ? gdk_color_copy(color) : NULL;
 }
 
 void
--- a/pidgin/gtkconv.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/gtkconv.c	Sat Feb 06 15:45:51 2010 +0900
@@ -553,17 +553,15 @@
 						prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
 
 					if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) {
-						char *firstspace;
-						char *slash;
-
-						firstspace = strchr(cmdline, ' ');
-						if (firstspace != NULL) {
-							slash = strrchr(firstspace, '/');
-						} else {
-							slash = strchr(cmdline, '/');
-						}
-
-						if (slash == NULL) {
+						char *spaceslash;
+
+						/* If the first word in the entered text has a '/' in it, then the user
+						 * probably didn't mean it as a command. So send the text as message. */
+						spaceslash = cmdline;
+						while (*spaceslash && *spaceslash != ' ' && *spaceslash != '/')
+							spaceslash++;
+
+						if (*spaceslash != '/') {
 							purple_conversation_write(conv, "", _("Unknown command."), PURPLE_MESSAGE_NO_LOG, time(NULL));
 							retval = TRUE;
 						}
--- a/pidgin/gtkdebug.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/gtkdebug.c	Sat Feb 06 15:45:51 2010 +0900
@@ -766,11 +766,12 @@
 		gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
 
 		/* regex toggle button */
+		image = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
 		win->filter =
 			gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
 									   GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
 									   NULL, _("Filter"), _("Filter"),
-									   NULL, NULL,
+									   NULL, image,
 									   G_CALLBACK(regex_filter_toggled_cb),
 									   win);
 		/* we purposely disable the toggle button here in case
--- a/pidgin/gtkimhtml.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/gtkimhtml.c	Sat Feb 06 15:45:51 2010 +0900
@@ -4949,7 +4949,9 @@
 	mark = gtk_text_buffer_get_insert(imhtml->text_buffer);
 
 	gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark);
+	gtk_text_buffer_begin_user_action(imhtml->text_buffer);
 	gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter);
+	gtk_text_buffer_end_user_action(imhtml->text_buffer);
 }
 
 static gboolean
--- a/pidgin/gtkstatusbox.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/gtkstatusbox.c	Sat Feb 06 15:45:51 2010 +0900
@@ -2630,6 +2630,7 @@
 	gpointer data;
 	GList *accounts = NULL, *node;
 	int active;
+	gboolean wastyping = FALSE;
 
 
 	if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path))
@@ -2642,7 +2643,7 @@
 			   TYPE_COLUMN, &type,
 			   DATA_COLUMN, &data,
 			   -1);
-	if (status_box->typing != 0)
+	if ((wastyping = (status_box->typing != 0)))
 		purple_timeout_remove(status_box->typing);
 	status_box->typing = 0;
 
@@ -2666,14 +2667,18 @@
 			pidgin_status_editor_show(FALSE,
 				purple_savedstatus_is_transient(saved_status)
 					? saved_status : NULL);
-			status_menu_refresh_iter(status_box, FALSE);
+			status_menu_refresh_iter(status_box, wastyping);
+			if (wastyping)
+				pidgin_status_box_refresh(status_box);
 			return;
 		}
 
 		if (type == PIDGIN_STATUS_BOX_TYPE_SAVED)
 		{
 			pidgin_status_window_show();
-			status_menu_refresh_iter(status_box, FALSE);
+			status_menu_refresh_iter(status_box, wastyping);
+			if (wastyping)
+				pidgin_status_box_refresh(status_box);
 			return;
 		}
 	}
--- a/pidgin/plugins/timestamp.c	Wed Feb 03 16:00:49 2010 +0900
+++ b/pidgin/plugins/timestamp.c	Sat Feb 06 15:45:51 2010 +0900
@@ -49,25 +49,33 @@
 	const char *mdate;
 	int y, height;
 	GdkRectangle rect;
+	gboolean scrolled = FALSE;
+	GtkTextTag *tag;
 
 	/* display timestamp */
 	mdate = purple_utf8_strftime(then == 0 ? "%H:%M" : "\n%H:%M",
 		localtime(&now));
 	gtk_text_buffer_get_end_iter(buffer, &iter);
 
-	if (gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "TIMESTAMP") == NULL)
-		gtk_text_buffer_create_tag(buffer, "TIMESTAMP",
+	/* is the view already scrolled? */
+	gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect);
+	gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height);
+	if (((y + height) - (rect.y + rect.height)) > height)
+		scrolled = TRUE;
+
+	if ((tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "TIMESTAMP")) == NULL)
+		tag = gtk_text_buffer_create_tag(buffer, "TIMESTAMP",
 			"foreground", "#888888", "justification", GTK_JUSTIFY_CENTER,
 			"weight", PANGO_WEIGHT_BOLD, NULL);
 
-	gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, mdate,
-		strlen(mdate), "TIMESTAMP", NULL);
+	gtk_text_buffer_insert_with_tags(buffer, &iter, mdate,
+		strlen(mdate), tag, NULL);
 
 	/* scroll view if necessary */
 	gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect);
 	gtk_text_view_get_line_yrange(
 		GTK_TEXT_VIEW(imhtml), &iter, &y, &height);
-	if (((y + height) - (rect.y + rect.height)) > height &&
+	if (!scrolled && ((y + height) - (rect.y + rect.height)) > height &&
 	    gtk_text_buffer_get_char_count(buffer)) {
 		gboolean smooth = purple_prefs_get_bool(
 			PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling");
--- a/po/de.po	Wed Feb 03 16:00:49 2010 +0900
+++ b/po/de.po	Sat Feb 06 15:45:51 2010 +0900
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-01-24 23:42+0100\n"
-"PO-Revision-Date: 2010-01-24 23:42+0100\n"
+"POT-Creation-Date: 2010-02-04 11:33+0100\n"
+"PO-Revision-Date: 2010-02-04 11:32+0100\n"
 "Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -4742,6 +4742,11 @@
 msgid "(Code %s)"
 msgstr "(Code %s)"
 
+msgid "A custom smiley in the message is too large to send."
+msgstr ""
+"Ein benutzerdefinierter Smiley in der Nachricht ist zu groß, um gesendet zu "
+"werden."
+
 msgid "XML Parse error"
 msgstr "Fehler beim Einlesen von XML-Daten"
 
@@ -6797,7 +6802,10 @@
 msgid "Server port"
 msgstr "Server-Port"
 
-#. Note to translators: %s in this string is a URL
+#, c-format
+msgid "Received unexpected response from %s: %s"
+msgstr "Unerwartete Antwort von %s erhalten: %s"
+
 #, c-format
 msgid "Received unexpected response from %s"
 msgstr "Unerwartete Antwort von %s erhalten"
@@ -7394,14 +7402,6 @@
 "[Kann die Nachricht von diesem Benutzer nicht anzeigen, da sie ungültige "
 "Zeichen enthält.]"
 
-msgid ""
-"The last action you attempted could not be performed because you are over "
-"the rate limit. Please wait 10 seconds and try again.\n"
-msgstr ""
-"Die letzte gewünschte Aktion konnte nicht durchgeführt werden, da die "
-"Senderate überschritten wurde. Bitte warten Sie 10 Sekunden und versuchen "
-"Sie es erneut.\n"
-
 #, c-format
 msgid "You have been disconnected from chat room %s."
 msgstr "Die Verbindung zum Raum %s wurde unterbrochen."