changeset 32615:fdc865966b01

propagate from branch 'im.pidgin.pidgin' (head e64578dc53c96709f20cb9416d507a4d448a4ee3) to branch 'im.pidgin.cpw.qulogic.gtk3' (head 74eaa11818b4a33e61322235c2b30753e31405d0)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 25 Jul 2010 01:11:18 +0000
parents 47fc498fc34b (current diff) 8e2da15b17cd (diff)
children 0e123a0b7694
files
diffstat 24 files changed, 400 insertions(+), 180 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jul 20 02:48:15 2010 +0000
+++ b/ChangeLog	Sun Jul 25 01:11:18 2010 +0000
@@ -1,6 +1,6 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-version 2.7.2 (??/??/????):
+version 2.7.3 (??/??/????):
 	General:
 	* Use silent build rules for automake >1.11. You can enable verbose
 	  builds with the --disable-silent-rules configure option, or using
@@ -46,6 +46,18 @@
 	* Fix file transfers that get stuck with "Waiting for transfer to
 	  begin".
 
+version 2.7.2 (07/21/2010):
+	AIM and ICQ:
+	* Fix a crash bug related to X-Status messages that can be triggered by
+	  remove users.  This is CVE-2010-2528.
+	* Fix a rare crash bug caused by certain incoming SMS messages
+	  (discovered by Jan Kaluza--thanks Jan!).
+	* Change HTML sent from ICQ accounts so that official ICQ clients
+	  hopefully display it correctly.
+
+	MSN:
+	* Fix a crash related to fast buddy icon transfers.
+
 version 2.7.1 (05/29/2010):
 	General:
 	* Build fixes on OpenSolaris.  (Brian Lu)
--- a/ChangeLog.API	Tue Jul 20 02:48:15 2010 +0000
+++ b/ChangeLog.API	Sun Jul 25 01:11:18 2010 +0000
@@ -1,6 +1,6 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-version 2.7.2 (??/??/????):
+version 2.7.3 (??/??/????):
 	libpurple:
 		Fixed:
 		* purple_account_[gs]et_public_alias no longer crash when
@@ -24,6 +24,9 @@
 		  gnt_tree_row_get_prev, gnt_tree_row_get_child and
 		  gnt_tree_row_get_parent.
 
+version 2.7.2 (07/21/2010):
+	* No changes
+
 version 2.7.1 (05/29/2010):
 	* No changes
 
--- a/ChangeLog.win32	Tue Jul 20 02:48:15 2010 +0000
+++ b/ChangeLog.win32	Sun Jul 25 01:11:18 2010 +0000
@@ -1,6 +1,9 @@
 Starting with Pidgin version 2.7.1, this ChangeLog file will no longer be
 updated.  It will be kept in the source tree for historical reasons only.
 
+version 2.7.1 (05/29/2010):
+	* No changes
+
 version 2.7.0 (05/12/2010):
 	* Updated GTK+ to 2.16.6
 	* Private GTK+ Runtime now used (GTK+ Installer no longer supported)
--- a/NEWS	Tue Jul 20 02:48:15 2010 +0000
+++ b/NEWS	Sun Jul 25 01:11:18 2010 +0000
@@ -2,6 +2,11 @@
 
 Our development blog is available at: http://planet.pidgin.im
 
+2.7.2 (07/21/2010):
+	Mark: We discovered a security issue in Pidgin 2.7.0 and 2.7.1 and
+	decided to release a patched version quickly.  This release contains
+	the fix for that crash, and a few other minor fixes.
+
 2.7.1 (05/29/2010):
 	Elliott: Hey, I'm first!  How did that happen?!  Maybe because of the
 	interesting changes in this release.  Sure there were quite a few bug
@@ -12,7 +17,7 @@
 	previous release!  This fixes a number of bugs that you've all been
 	reporting a ton of duplicate tickets about and even gives you the new
 	direct connection file transfer support for MSN.  Enjoy!
-	
+
 	Marcus: Quite a bit quicker to get this release out, compared with the
 	previous one :).  Fixes a number of bugs, and I'm sure the MSN direct
 	connections will please many users.  Enjoy!
--- a/configure.ac	Tue Jul 20 02:48:15 2010 +0000
+++ b/configure.ac	Sun Jul 25 01:11:18 2010 +0000
@@ -46,7 +46,7 @@
 m4_define([purple_lt_current], [7])
 m4_define([purple_major_version], [2])
 m4_define([purple_minor_version], [7])
-m4_define([purple_micro_version], [2])
+m4_define([purple_micro_version], [3])
 m4_define([purple_version_suffix], [devel])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
--- a/libpurple/protocols/mxit/actions.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/actions.c	Sun Jul 25 01:11:18 2010 +0000
@@ -113,26 +113,26 @@
 
 		/* update name */
 		g_strlcpy( profile->nickname, name, sizeof( profile->nickname ) );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FULLNAME, CP_PROF_TYPE_UTF8, profile->nickname );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FULLNAME, CP_PROFILE_TYPE_UTF8, profile->nickname );
 		g_string_append( attributes, attrib );
 		acount++;
 
 		/* update hidden */
 		field = purple_request_fields_get_field( fields, "hidden" );
 		profile->hidden = purple_request_field_bool_get_value( field );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROF_TYPE_BOOL, ( profile->hidden ) ? "1" : "0" );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROFILE_TYPE_BOOL, ( profile->hidden ) ? "1" : "0" );
 		g_string_append( attributes, attrib );
 		acount++;
 
 		/* update birthday */
-		strcpy( profile->birthday, bday );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROF_TYPE_UTF8, profile->birthday );
+		g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday );
 		g_string_append( attributes, attrib );
 		acount++;
 
 		/* update gender */
 		profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_GENDER, CP_PROF_TYPE_BOOL, ( profile->male ) ? "1" : "0" );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_GENDER, CP_PROFILE_TYPE_BOOL, ( profile->male ) ? "1" : "0" );
 		g_string_append( attributes, attrib );
 		acount++;
 
@@ -141,8 +141,8 @@
 		if ( !name )
 			profile->title[0] = '\0';
 		else
-			strcpy( profile->title, name );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_TITLE, CP_PROF_TYPE_UTF8, profile->title );
+			g_strlcpy( profile->title, name, sizeof( profile->title ) );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_TITLE, CP_PROFILE_TYPE_UTF8, profile->title );
 		g_string_append( attributes, attrib );
 		acount++;
 
@@ -151,8 +151,8 @@
 		if ( !name )
 			profile->firstname[0] = '\0';
 		else
-			strcpy( profile->firstname, name );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FIRSTNAME, CP_PROF_TYPE_UTF8, profile->firstname );
+			g_strlcpy( profile->firstname, name, sizeof( profile->firstname ) );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FIRSTNAME, CP_PROFILE_TYPE_UTF8, profile->firstname );
 		g_string_append( attributes, attrib );
 		acount++;
 
@@ -161,8 +161,8 @@
 		if ( !name )
 			profile->lastname[0] = '\0';
 		else
-			strcpy( profile->lastname, name );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_LASTNAME, CP_PROF_TYPE_UTF8, profile->lastname );
+			g_strlcpy( profile->lastname, name, sizeof( profile->lastname ) );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_LASTNAME, CP_PROFILE_TYPE_UTF8, profile->lastname );
 		g_string_append( attributes, attrib );
 		acount++;
 
@@ -171,8 +171,8 @@
 		if ( !name )
 			profile->email[0] = '\0';
 		else
-			strcpy( profile->email, name );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_EMAIL, CP_PROF_TYPE_UTF8, profile->email );
+			g_strlcpy( profile->email, name, sizeof( profile->email ) );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_EMAIL, CP_PROFILE_TYPE_UTF8, profile->email );
 		g_string_append( attributes, attrib );
 		acount++;
 
@@ -181,8 +181,8 @@
 		if ( !name )
 			profile->mobilenr[0] = '\0';
 		else
-			strcpy( profile->mobilenr, name );
-		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_MOBILENR, CP_PROF_TYPE_UTF8, profile->mobilenr );
+			g_strlcpy( profile->mobilenr, name, sizeof( profile->mobilenr ) );
+		g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_MOBILENR, CP_PROFILE_TYPE_UTF8, profile->mobilenr );
 		g_string_append( attributes, attrib );
 		acount++;
 
@@ -225,12 +225,14 @@
 	group = purple_request_field_group_new( NULL );
 	purple_request_fields_add_group( fields, group );
 
-	/* mxitId (read-only) */
-	if ( session->mxitId ) {
-		field = purple_request_field_string_new( "mxitid", _( "Your MXitId" ), session->mxitId, FALSE );
+#if	0
+	/* UID (read-only) */
+	if ( session->uid ) {
+		field = purple_request_field_string_new( "mxitid", _( "Your UID" ), session->uid, FALSE );
 		purple_request_field_string_set_editable( field, FALSE );
 		purple_request_field_group_add_field( group, field );
 	}
+#endif
 
 	/* pin */
 	field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE );
@@ -247,6 +249,8 @@
 	/* birthday */
 	field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
 	purple_request_field_group_add_field( group, field );
+	if ( profile->flags & CP_PROF_DOBLOCKED )
+		purple_request_field_string_set_editable( field, FALSE );
 
 	/* gender */
 	field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
--- a/libpurple/protocols/mxit/http.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/http.c	Sun Jul 25 01:11:18 2010 +0000
@@ -118,7 +118,7 @@
 		/* read bytes from the socket */
 		len = read( session->fd, buf + buflen, sizeof( buf ) - buflen );
 		if ( len <= 0 ) {
-			/* connection has been terminated, or error occured */
+			/* connection has been terminated, or error occurred */
 			goto done;
 		}
 
@@ -139,7 +139,7 @@
 		}
 		buflen += len;
 
-		/* we have the header's end now skip over the http seperator to get the body offset */
+		/* we have the header's end now skip over the http separator to get the body offset */
 		ch += strlen( HTTP_11_SEPERATOR );
 		*(ch - 1) = '\0';
 		body = ch;
@@ -206,7 +206,7 @@
 		/* read bytes from the socket */
 		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
 		if ( len <= 0 ) {
-			/* connection has been terminated, or error occured */
+			/* connection has been terminated, or error occurred */
 			goto done;
 		}
 
--- a/libpurple/protocols/mxit/login.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/login.c	Sun Jul 25 01:11:18 2010 +0000
@@ -238,7 +238,7 @@
 	/* nickname */
 	str = purple_request_fields_get_string( fields, "nickname" );
 	if ( ( !str ) || ( strlen( str ) < 3 ) ) {
-		err = _( "The nick name you entered is invalid." );
+		err = _( "The Display Name you entered is invalid." );
 		goto out;
 	}
 	g_strlcpy( profile->nickname, str, sizeof( profile->nickname ) );
@@ -329,12 +329,12 @@
 	purple_request_fields_add_group( fields, group );
 
 	/* mxit login name */
-	field = purple_request_field_string_new( "loginname", _( "MXit Login Name" ), purple_account_get_username( session->acc ), FALSE );
+	field = purple_request_field_string_new( "loginname", _( "MXit ID" ), purple_account_get_username( session->acc ), FALSE );
 	purple_request_field_string_set_editable( field, FALSE );
 	purple_request_field_group_add_field( group, field );
 
 	/* nick name (required) */
-	field = purple_request_field_string_new( "nickname", _( "Nick Name" ), profile->nickname, FALSE );
+	field = purple_request_field_string_new( "nickname", _( "Display Name" ), profile->nickname, FALSE );
 	purple_request_field_set_required( field, TRUE );
 	purple_request_field_group_add_field( group, field );
 
@@ -418,10 +418,10 @@
 				purple_connection_error( session->con, _( "Invalid country selected. Please try again." ) );
 				return;
 			case '6' :
-				purple_connection_error( session->con, _( "Username is not registered. Please register first." ) );
+				purple_connection_error( session->con, _( "The MXit ID you entered is not registered. Please register first." ) );
 				return;
 			case '7' :
-				purple_connection_error( session->con, _( "Username is already registered. Please choose another username." ) );
+				purple_connection_error( session->con, _( "The MXit ID you entered is already registered. Please choose another." ) );
 				/* this user's account already exists, so we need to change the registration login flag to be login */
 				purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
 				return;
@@ -637,7 +637,7 @@
 
 	/* add the captcha */
 	logindata->captcha = purple_base64_decode( parts[3], &logindata->captcha_size );
-	field = purple_request_field_image_new( "capcha", _( "Security Code" ), (gchar*) logindata->captcha, logindata->captcha_size );
+	field = purple_request_field_image_new( "captcha", _( "Security Code" ), (gchar*) logindata->captcha, logindata->captcha_size );
 	purple_request_field_group_add_field( group, field );
 
 	/* ask for input (required) */
@@ -659,7 +659,7 @@
 		}
 		purple_request_field_list_add( field, country[1], g_strdup( country[0] ) );
 		if ( strcmp( country[1], parts[6] ) == 0 ) {
-			/* based on the user's ip, this is his current country code, so we default to it */
+			/* based on the user's IP, this is his current country code, so we default to it */
 			purple_request_field_list_add_selected( field, country[1] );
 		}
 		g_strfreev( country );
--- a/libpurple/protocols/mxit/markup.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/markup.c	Sun Jul 25 01:11:18 2010 +0000
@@ -257,7 +257,7 @@
 	 * all the text as is to the conversation window. this message dump is very
 	 * confusing and makes it totally unusable. to work around this we will count
 	 * the amount of tags and if its more than the pidgin threshold, we will just
-	 * break the message up into smaller parts and send them seperately to pidgin.
+	 * break the message up into smaller parts and send them separately to pidgin.
 	 * to the user it will look like multiple messages, but at least he will be able
 	 * to use and understand it.
 	 */
--- a/libpurple/protocols/mxit/multimx.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/multimx.c	Sun Jul 25 01:11:18 2010 +0000
@@ -557,6 +557,9 @@
 {
 	struct MXitSession* session = (struct MXitSession*) gc->proto_data;
 	struct multimx* multimx = NULL;
+	PurpleBuddy* buddy;
+	PurpleConversation *convo;
+	char* tmp;
 
 	purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s'\n", username);
 
@@ -569,6 +572,24 @@
 
 	/* Send invite to MXit */
 	mxit_send_groupchat_invite(session, multimx->roomid, 1, &username);
+
+	/* Find the buddy information for this contact (reference: "libpurple/blist.h") */
+	buddy = purple_find_buddy(session->acc, username);
+	if (!buddy) {
+		purple_debug_warning(MXIT_PLUGIN_ID, "mxit_chat_invite: unable to find the buddy '%s'\n", username);
+		return;
+	}
+
+	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc);
+	if (convo == NULL) {
+		purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
+		return;
+	}
+
+	/* Display system message in chat window */
+	tmp = g_strdup_printf("%s: %s", _("You have invited"), purple_buddy_get_alias(buddy));
+	purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+	g_free(tmp);
 }
 
 
--- a/libpurple/protocols/mxit/mxit.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.c	Sun Jul 25 01:11:18 2010 +0000
@@ -91,6 +91,8 @@
 	if ( !account )
 		goto skip;
 	con = purple_account_get_connection( account );
+	if ( !con )
+		goto skip;
 
 	/* determine if it's a command-response to send */
 	is_command = g_str_has_prefix( parts[4], "::type=reply|" );
@@ -145,7 +147,7 @@
 
 
 /*------------------------------------------------------------------------
- * Unegister MXit from receiving URI click notifications from the UI
+ * Unregister MXit from receiving URI click notifications from the UI
  */
 static void mxit_unregister_uri_handler()
 {
@@ -203,7 +205,7 @@
 	if ( find_active_chat( session->active_chats, who ) )
 		return;
 
-	/* determite if this buddy is a MXit service */
+	/* determine if this buddy is a MXit service */
 	switch ( contact->type ) {
 		case MXIT_TYPE_BOT :
 		case MXIT_TYPE_CHATROOM :
@@ -559,7 +561,8 @@
 {
 	struct MXitSession*		session			= (struct MXitSession*) gc->proto_data;
 	const char*				profilelist[]	= { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
-												CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY };
+												CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN,
+												CP_PROFILE_STATUS, CP_PROFILE_AVATAR };
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who );
 
@@ -578,11 +581,34 @@
 
 	table = g_hash_table_new( g_str_hash, g_str_equal );
 
-	g_hash_table_insert( table, "login_label", (gpointer)_( "Your Mobile Number..." ) );
+	g_hash_table_insert( table, "login_label", (gpointer)_( "Your MXit ID..." ) );
 
 	return table;
 }
 
+
+/*------------------------------------------------------------------------
+ * Buddy list menu.
+ *
+ *  @param node		The entry in the buddy list.
+ */
+static GList* mxit_blist_menu( PurpleBlistNode *node )
+{
+	PurpleBuddy*		buddy;
+	struct contact*		contact;
+	GList*				m = NULL;
+
+	if ( !PURPLE_BLIST_NODE_IS_BUDDY( node ) )
+		return NULL;
+
+	buddy = (PurpleBuddy *) node;
+	contact = purple_buddy_get_protocol_data( buddy );
+	if ( !contact )
+		return NULL;
+
+	return m;
+}
+
 /*========================================================================================================================*/
 
 static PurplePluginProtocolInfo proto_info = {
@@ -594,7 +620,7 @@
 		32, 32,												/* min width & height */
 		MXIT_AVATAR_SIZE,									/* max width */
 		MXIT_AVATAR_SIZE,									/* max height */
-		100000,												/* max filezize */
+		100000,												/* max filesize */
 		PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY	/* scaling rules */
 	},
 	mxit_list_icon,			/* list_icon */
@@ -602,7 +628,7 @@
 	mxit_status_text,		/* status_text */
 	mxit_tooltip,			/* tooltip_text */
 	mxit_status_types,		/* status types				[roster.c] */
-	NULL,					/* blist_node_menu */
+	mxit_blist_menu,		/* blist_node_menu */
 	mxit_chat_info,			/* chat_info				[multimx.c] */
 	NULL,					/* chat_info_defaults */
 	mxit_login,				/* login					[login.c] */
--- a/libpurple/protocols/mxit/mxit.h	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.h	Sun Jul 25 01:11:18 2010 +0000
@@ -105,7 +105,7 @@
 /* Client session flags */
 #define		MXIT_FLAG_CONNECTED			0x01		/* established connection to the server */
 #define		MXIT_FLAG_LOGGEDIN			0x02		/* user currently logged in */
-#define		MXIT_FLAG_FIRSTROSTER		0x04		/* set to true once the first roster update has been recevied and processed */
+#define		MXIT_FLAG_FIRSTROSTER		0x04		/* set to true once the first roster update has been received and processed */
 
 
 /* define this to enable the link clicking support */
@@ -151,7 +151,7 @@
 
 	/* personal (profile) */
 	struct MXitProfile*	profile;					/* user's profile information */
-	char*				mxitId;						/* the user's MXitId */
+	char*				uid;						/* the user's UID */
 
 	/* libpurple */
 	PurpleAccount*		acc;						/* pointer to the libpurple internal account struct */
--- a/libpurple/protocols/mxit/profile.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/profile.c	Sun Jul 25 01:11:18 2010 +0000
@@ -101,6 +101,23 @@
 
 
 /*------------------------------------------------------------------------
+ * Returns timestamp field in date & time format (DD-MM-YYYY HH:MM:SS)
+ *
+ * @param msecs		The timestamps (milliseconds since epoch)
+ * @return			Date & Time in a display'able format.
+ */
+static const char* datetime( int64_t msecs )
+{  
+    time_t secs = msecs / 1000;
+
+    struct tm t;
+    localtime_r( &secs, &t );
+
+	return purple_utf8_strftime( "%d-%m-%Y %H:%M:%S", &t );
+}
+
+
+/*------------------------------------------------------------------------
  * Display the profile information.
  *
  *  @param session		The MXit session object
@@ -120,7 +137,7 @@
 		contact = purple_buddy_get_protocol_data(buddy);
 	}
 
-	purple_notify_user_info_add_pair( info, _( "Nick Name" ), profile->nickname );
+	purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname );
 	purple_notify_user_info_add_pair( info, _( "Birthday" ), profile->birthday );
 	purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
 //	purple_notify_user_info_add_pair( info, _( "Hidden Number" ), profile->hidden ? _( "Yes" ) : _( "No" ) );
@@ -138,6 +155,10 @@
 		/* presence */
 		purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
 
+		/* last online */
+		if ( contact->presence == MXIT_PRESENCE_OFFLINE )
+			purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
+
 		/* mood */
 		if ( contact->mood != MXIT_MOOD_NONE )   
 			purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
@@ -153,7 +174,6 @@
 
 		/* hidden number */
 		purple_notify_user_info_add_pair( info, _( "Hidden Number" ), ( contact->flags & MXIT_CFLAG_HIDDEN ) ? _( "Yes" ) : _( "No" ) );
-
 	}
 
 	purple_notify_userinfo( session->con, username, info, NULL, NULL );
--- a/libpurple/protocols/mxit/profile.h	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/profile.h	Sun Jul 25 01:11:18 2010 +0000
@@ -44,6 +44,8 @@
 	char		email[64];							/* user's email address */
 	char		mobilenr[21];						/* user's mobile number */
 	char		regcountry[3];						/* user's registered country code */
+	int64_t		flags;								/* user's profile flags */
+	int64_t		lastonline;							/* user's last-online timestamp */
 
 	gboolean	hidden;								/* set if the user's msisdn should remain hidden */
 };
--- a/libpurple/protocols/mxit/protocol.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/protocol.c	Sun Jul 25 01:11:18 2010 +0000
@@ -445,7 +445,7 @@
 	packet->headerlen = 0;
 
 	/* create generic packet header */
-	hlen = sprintf( header,	"id=%s%c", session->acc->username, CP_REC_TERM );			/* client msisdn */
+	hlen = snprintf( header, sizeof( header ), "id=%s%c", session->acc->username, CP_REC_TERM );			/* client msisdn */
 
 	if ( session->http ) {
 		/* http connection only */
@@ -520,7 +520,7 @@
 		/* we are still waiting for an outstanding ACK from the MXit server */
 		if ( session->last_tx <= time( NULL ) - MXIT_ACK_TIMEOUT ) {
 			/* ack timeout! so we close the connection here */
-			purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%X'\n", session->outack );
+			purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
 			purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
 		}
 		return TRUE;
@@ -642,7 +642,8 @@
 	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%i%c%s%c"		/* "ms"=password\1version\1maxreplyLen\1name\1 */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i%c%s%c"		/* "ms"=password\1version\1maxreplyLen\1name\1 */
 								"%s%c%i%c%s%c%s%c"			/* dateOfBirth\1gender\1location\1capabilities\1 */
 								"%s%c%i%c%s%c%s",			/* dc\1features\1dialingcode\1locale */
 								session->encpwd, CP_FLD_TERM, MXIT_CP_VERSION, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
@@ -670,7 +671,8 @@
 	locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%i%c"			/* "ms"=password\1version\1getContacts\1 */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i%c"			/* "ms"=password\1version\1getContacts\1 */
 								"%s%c%s%c%i%c"				/* capabilities\1dc\1features\1 */
 								"%s%c%s%c"					/* dialingcode\1locale\1 */
 								"%i%c%i%c%i",				/* maxReplyLen\1protocolVer\1lastRosterUpdate */
@@ -711,7 +713,8 @@
 		markuped_msg = g_strdup( msg );
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%i%c%i",		/* "ms"=jid\1msg\1type\1flags */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i%c%i",		/* "ms"=jid\1msg\1type\1flags */
 								to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
 	);
 
@@ -737,7 +740,8 @@
 	int				datalen;
 	unsigned int	i;
 
-	datalen = sprintf( data,	"ms=%s%c%i",		/* "ms="mxitid\1nr_attributes */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%i",		/* "ms="mxitid\1nr_attributes */
 								(username ? username : ""), CP_FLD_TERM, nr_attrib);
 
 	/* add attributes */
@@ -767,7 +771,8 @@
 	parts = g_strsplit( attributes, "\01", ( MXIT_MAX_ATTRIBS * 3 ) );
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%i",	/* "ms"=password\1nr_attibutes  */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%i",	/* "ms"=password\1nr_attibutes  */
 								( password ) ? password : "", CP_FLD_TERM, nr_attrib
 	);
 
@@ -797,7 +802,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%i%c",					/* "ms"=show\1status */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%i%c",					/* "ms"=show\1status */
 								presence, CP_FLD_TERM
 	);
 
@@ -822,7 +828,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%i",	/* "ms"=mood */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%i",	/* "ms"=mood */
 								mood
 	);
 
@@ -845,7 +852,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%s%c%i%c%s",	/* "ms"=group\1username\1alias\1type\1msg */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%s%c%i%c%s",	/* "ms"=group\1username\1alias\1type\1msg */
 								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
 								CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM, ""
 	);
@@ -867,7 +875,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s",	/* "ms"=username */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s",	/* "ms"=username */
 								username
 	);
 
@@ -889,7 +898,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%s",	/* "ms"=username\1group\1alias */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%s",	/* "ms"=username\1group\1alias */
 								username, CP_FLD_TERM, "", CP_FLD_TERM, alias
 	);
 
@@ -910,7 +920,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s",	/* "ms"=username */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s",	/* "ms"=username */
 								username
 	);
 
@@ -933,7 +944,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%s",	/* "ms"=groupname\1username\1alias */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%s",	/* "ms"=groupname\1username\1alias */
 								groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
 	);
 
@@ -954,7 +966,8 @@
 	int			datalen;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s",	/* "ms"=splashId */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s",	/* "ms"=splashId */
 								splashid
 	);
 
@@ -979,7 +992,8 @@
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%s%c%i",		/* "ms"=contactAddress \1 id \1 event */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%s%c%i",		/* "ms"=contactAddress \1 id \1 event */
 								to, CP_FLD_TERM, id, CP_FLD_TERM, event
 	);
 
@@ -1003,7 +1017,8 @@
 	int			i;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%i",	/* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%i",	/* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
 								groupname, CP_FLD_TERM, nr_usernames
 	);
 
@@ -1032,7 +1047,8 @@
 	int			i;
 
 	/* convert the packet to a byte stream */
-	datalen = sprintf( data,	"ms=%s%c%i",	/* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
+	datalen = snprintf( data, sizeof( data ),
+								"ms=%s%c%i",	/* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
 								roomid, CP_FLD_TERM, nr_usernames
 	);
 
@@ -1284,7 +1300,7 @@
 	const char*		statusmsg;
 	const char*		profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_HIDENUMBER, CP_PROFILE_FULLNAME,
 									CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
-									CP_PROFILE_MOBILENR };
+									CP_PROFILE_MOBILENR, CP_PROFILE_FLAGS };
 
 	purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
 
@@ -1304,7 +1320,7 @@
 
 	/* extract MXitId (from protocol 5.9) */
 	if ( records[1]->fcount >= 9 )
-		session->mxitId = g_strdup( records[1]->fields[8]->data );
+		session->uid = g_strdup( records[1]->fields[8]->data );
 
 	/* display the current splash-screen */
 	if ( splash_popup_enabled( session ) )
@@ -1456,9 +1472,9 @@
 		/* build up a new contact info struct */
 		contact = g_new0( struct contact, 1 );
 
-		strcpy( contact->username, rec->fields[0]->data );
+		g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
 		mxit_strip_domain( contact->username );				/* remove dummy domain */
-		strcpy( contact->alias, rec->fields[1]->data );
+		g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
 		contact->type = atoi( rec->fields[2]->data );
 
 		if ( rec->fcount >= 5 ) {
@@ -1509,10 +1525,10 @@
 		/* build up a new contact info struct */
 		contact = g_new0( struct contact, 1 );
 
-		strcpy( contact->groupname, rec->fields[0]->data );
-		strcpy( contact->username, rec->fields[1]->data );
+		g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
+		g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
 		mxit_strip_domain( contact->username );				/* remove dummy domain */
-		strcpy( contact->alias, rec->fields[2]->data );
+		g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
 
 		contact->presence = atoi( rec->fields[3]->data );
 		contact->type = atoi( rec->fields[4]->data );
@@ -1566,12 +1582,13 @@
 
 		/*
 		 * The format of the record is:
-		 * contactAddressN\1presenceN\1\moodN\1customMoodN\1statusMsgN\1avatarIdN
+		 * contactAddressN\1presenceN\1moodN\1customMoodN\1statusMsgN\1avatarIdN
 		 */
 		mxit_strip_domain( rec->fields[0]->data );		/* contactAddress */
 
 		mxit_update_buddy_presence( session, rec->fields[0]->data, atoi( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
-				rec->fields[3]->data, rec->fields[4]->data, rec->fields[5]->data );
+				rec->fields[3]->data, rec->fields[4]->data );
+		mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
 	}
 }
 
@@ -1589,11 +1606,13 @@
 	struct MXitProfile*		profile		= NULL;
 	int						count;
 	int						i;
+	const char*				avatarId	= NULL;
+	const char*				statusMsg	= NULL;
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
 
-	if ( records[0]->fields[0]->len == 0 ) {
-		/* no MXitId provided, so this must be our own profile information */
+	if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
+		/* No UserId or Our UserId provided, so this must be our own profile information */
 		if ( session->profile == NULL )
 			session->profile = g_new0( struct MXitProfile, 1 );
 		profile = session->profile;
@@ -1643,8 +1662,13 @@
 			/* nickname */
 			g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
 		}
+		else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
+			/* status message - just keep a reference to the value */
+			statusMsg = fvalue;
+		}
 		else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
-			/* avatar id, we just ingore it cause we dont need it */
+			/* avatar id - just keep a reference to the value */
+			avatarId = fvalue;
 		}
 		else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
 			/* title */
@@ -1670,14 +1694,26 @@
 			/* registered country */
 			g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
 		}
+		else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
+			/* profile flags */
+			profile->flags = strtoll( fvalue, NULL, 10 );
+		}
+		else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
+			/* last seen online */
+			profile->lastonline = strtoll( fvalue, NULL, 10 );
+		}
 		else {
 			/* invalid profile attribute */
 			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
 		}
 	}
 
-	/* if this is not our profile, just display it */
 	if ( profile != session->profile ) {
+		/* update avatar (if necessary) */
+		if ( avatarId )
+			mxit_update_buddy_avatar( session, mxitId, avatarId );
+
+		/* if this is not our profile, just display it */
 		mxit_show_profile( session, mxitId, profile );
 		g_free( profile );
 	}
@@ -2010,12 +2046,12 @@
 					return 0;
 				}
 				else {
-					sprintf( errmsg, _( "Login error: %s (%i)" ), errdesc, packet->errcode );
+					snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
 					purple_connection_error( session->con, errmsg );
 					return -1;
 				}
 		case CP_CMD_LOGOUT :
-				sprintf( errmsg, _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
+				snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
 				purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
 				return -1;
 		case CP_CMD_CONTACT :
@@ -2487,8 +2523,8 @@
 	mxit_free_emoticon_cache( session );
 
 	/* free allocated memory */
-	if ( session->mxitId )
-		g_free( session->mxitId );
+	if ( session->uid )
+		g_free( session->uid );
 	g_free( session->encpwd );
 	session->encpwd = NULL;
 
--- a/libpurple/protocols/mxit/protocol.h	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/protocol.h	Sun Jul 25 01:11:18 2010 +0000
@@ -190,13 +190,17 @@
 #define		CP_PROFILE_EMAIL		"email"					/* Email address (UTF8 String) */
 #define		CP_PROFILE_MOBILENR		"mobilenumber"			/* Mobile Number (UTF8 String) */
 #define		CP_PROFILE_REGCOUNTRY	"registeredcountry"		/* Registered Country Code (UTF8 String) */
+#define		CP_PROFILE_FLAGS		"flags"					/* Profile flags (Bitset) */
+#define		CP_PROFILE_LASTSEEN		"lastseen"				/* Last-Online timestamp */
 
 /* extended profile field types */
-#define		CP_PROF_TYPE_BOOL		0x02					/* boolean profile attribute type */
-#define		CP_PROF_TYPE_INT		0x05					/* integer profile attribute type */
-#define		CP_PROF_TYPE_UTF8		0x0A					/* UTF8 string profile attribute type */
-#define		CP_PROF_TYPE_DATE		0x0B					/* date-time profile attribute type */
+#define		CP_PROFILE_TYPE_BOOL	0x02					/* boolean profile attribute type */
+#define		CP_PROFILE_TYPE_INT		0x05					/* integer profile attribute type */
+#define		CP_PROFILE_TYPE_UTF8	0x0A					/* UTF8 string profile attribute type */
+#define		CP_PROFILE_TYPE_DATE	0x0B					/* date-time profile attribute type */
 
+/* profile flags */
+#define		CP_PROF_DOBLOCKED		0x40					/* date-of-birth cannot be changed */
 
 /* define this to enable protocol debugging (very verbose logging) */
 #define		DEBUG_PROTOCOL
--- a/libpurple/protocols/mxit/roster.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/roster.c	Sun Jul 25 01:11:18 2010 +0000
@@ -44,12 +44,12 @@
 /* statuses (reference: libpurple/status.h) */
 static struct status
 {
-	PurpleStatusPrimitive	primative;
+	PurpleStatusPrimitive	primitive;
 	int						mxit;
 	const char*				id;
 	const char*				name;
 } const mxit_statuses[] = {
-		/*	primative,						no,							id,			name					*/
+		/*	primitive,						no,							id,			name					*/
 		{	PURPLE_STATUS_OFFLINE,			MXIT_PRESENCE_OFFLINE,		"offline",	N_( "Offline" )			},	/* 0 */
 		{	PURPLE_STATUS_AVAILABLE,		MXIT_PRESENCE_ONLINE,		"online",	N_( "Available" )		},	/* 1 */
 		{	PURPLE_STATUS_AWAY,				MXIT_PRESENCE_AWAY,			"away",		N_( "Away" )			},	/* 2 */
@@ -74,7 +74,7 @@
 		const struct status* status = &mxit_statuses[i];
 
 		/* add mxit status (reference: "libpurple/status.h") */
-		type = purple_status_type_new_with_attrs( status->primative, status->id, _( status->name ), TRUE, TRUE, FALSE,
+		type = purple_status_type_new_with_attrs( status->primitive, status->id, _( status->name ), TRUE, TRUE, FALSE,
 					"message", _( "Message" ), purple_value_new( PURPLE_TYPE_STRING ),
 					NULL );
 
@@ -292,7 +292,7 @@
 		 * XXX: libPurple does not currently provide an API to change or rename the group name
 		 * for a specific buddy. One option is to remove the buddy from the list and re-adding
 		 * him in the new group, but by doing that makes the buddy go offline and then online
-		 * again. This is really not ideal and very iretating, but how else then?
+		 * again. This is really not ideal and very irritating, but how else then?
 		 */
 
 		/* create new buddy */
@@ -358,7 +358,7 @@
 	 * So if this MXit contact isn't in a group, pretend it is.
 	 */
 	if ( *contact->groupname == '\0' ) {
-		strcpy( contact->groupname, MXIT_DEFAULT_GROUP );
+		g_strlcpy( contact->groupname, MXIT_DEFAULT_GROUP, sizeof( contact->groupname ) );
 	}
 
 	/* find or create a group for this contact */
@@ -428,15 +428,14 @@
  *  @param mood			The new mood for the contact
  *  @param customMood	The custom mood identifier
  *  @param statusMsg	This is the contact's status message
- *  @param avatarId		This is the contact's avatar id
  */
-void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, const char* avatarId )
+void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg )
 {
 	PurpleBuddy*		buddy	= NULL;
 	struct contact*		contact	= NULL;
 
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: user='%s' presence=%i mood=%i customMood='%s' statusMsg='%s' avatar='%s'\n",
-		username, presence, mood, customMood, statusMsg, avatarId );
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: user='%s' presence=%i mood=%i customMood='%s' statusMsg='%s'\n",
+		username, presence, mood, customMood, statusMsg );
 
 	if ( ( presence < MXIT_PRESENCE_OFFLINE ) || ( presence > MXIT_PRESENCE_DND ) ) {
 		purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: invalid presence state %i\n", presence );
@@ -472,7 +471,46 @@
 	if ( statusMsg[0] != '\0' )
 		contact->statusMsg = g_markup_escape_text( statusMsg, -1 );
 
-	/* update avatarId */
+	/* update the buddy's status (reference: "libpurple/prpl.h") */
+	if ( contact->statusMsg )
+		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
+	else
+		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
+
+	/* update the buddy's mood */
+	if ( contact->mood == MXIT_MOOD_NONE )
+		purple_prpl_got_user_status_deactive( session->acc, username, "mood" );
+	else
+		purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+}
+
+
+/*------------------------------------------------------------------------
+ * Update the buddy's avatar.
+ * Either a presence update packet was received from the MXit server, or a profile response.
+ *
+ *  @param session		The MXit session object
+ *  @param username		The contact which presence to update
+ *  @param avatarId		This is the contact's avatar id
+ */
+void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId )
+{
+	PurpleBuddy*		buddy	= NULL;
+	struct contact*		contact	= NULL;
+
+	purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_avatar: user='%s' avatar='%s'\n", username, avatarId );
+
+	/* find the buddy information for this contact (reference: "libpurple/blist.h") */
+	buddy = purple_find_buddy( session->acc, username );
+	if ( !buddy ) {
+		purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
+		return;
+	}
+
+	contact = purple_buddy_get_protocol_data( buddy );
+	if ( !contact )
+		return;
+
 	if ( ( contact->avatarId ) && ( g_ascii_strcasecmp( contact->avatarId, avatarId ) == 0 ) ) {
 		/*  avatar has not changed - do nothing */
 	}
@@ -486,18 +524,6 @@
 	}
 	else		/* clear current avatar */
 		purple_buddy_icons_set_for_user( session->acc, username, NULL, 0, NULL );
-
-	/* update the buddy's status (reference: "libpurple/prpl.h") */
-	if ( contact->statusMsg )
-		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
-	else
-		purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
-
-	/* update the buddy's mood */
-	if ( contact->mood == MXIT_MOOD_NONE )
-		purple_prpl_got_user_status_deactive( session->acc, username, "mood" );
-	else
-		purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
 }
 
 
--- a/libpurple/protocols/mxit/roster.h	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/mxit/roster.h	Sun Jul 25 01:11:18 2010 +0000
@@ -124,7 +124,8 @@
 
 /* MXit Protocol callbacks */
 void mxit_update_contact( struct MXitSession* session, struct contact* contact );
-void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, const char* avatarId );
+void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg );
+void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId );
 void mxit_new_subscription( struct MXitSession* session, struct contact* contact );
 void mxit_update_blist( struct MXitSession* session );
 gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username );
--- a/libpurple/protocols/oscar/family_icbm.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Sun Jul 25 01:11:18 2010 +0000
@@ -249,9 +249,6 @@
 	}
 	g_free(buf);
 
-
-
-
 	g_free(snac2->data);
 	g_free(snac2);
 
@@ -2687,7 +2684,6 @@
 	guint16 hdrlen;
 	int curpos;
 	guint16 num1, num2;
-	char *desc, *title, *temp;
 	PurpleAccount *account;
 	PurpleBuddy *buddy;
 	PurplePresence *presence;
@@ -2714,33 +2710,41 @@
 				xml = byte_stream_getstr(bs, bs->len - curpos);
 				purple_debug_misc("oscar", "X-Status: Received XML reply\n");
 				if (xml) {
-				/* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", xml); */
-					desc = strstr(xml, "&lt;desc&gt;");
-					if (desc != NULL) {
-						temp = strstr(xml, "&lt;/desc&gt;");
-						temp[0] = 0;
-						desc = desc + 12;
+					GString *xstatus;
+					char *tmp1, *tmp2;
+
+					/* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", xml); */
+
+					xstatus = g_string_new(NULL);
+
+					tmp1 = strstr(xml, "&lt;title&gt;");
+					if (tmp1 != NULL) {
+						tmp1 += 13;
+						tmp2 = strstr(tmp1, "&lt;/title&gt;");
+						if (tmp2 != NULL)
+							g_string_append_len(xstatus, tmp1, tmp2 - tmp1);
 					}
-					title = strstr(xml, "&lt;title&gt;");
-					if (title != NULL) {
-						temp = strstr(xml, "&lt;/title&gt;");
-						temp[0] = 0;
-						title = title + 13;
-					} else {
-						title = "";
+					tmp1 = strstr(xml, "&lt;desc&gt;");
+					if (tmp1 != NULL) {
+						tmp1 += 12;
+						tmp2 = strstr(tmp1, "&lt;/desc&gt;");
+						if (tmp2 != NULL) {
+							if (xstatus->len > 0)
+								g_string_append(xstatus, " - ");
+							g_string_append_len(xstatus, tmp1, tmp2 - tmp1);
+						}
 					}
-					strcpy(xml,title);
-					if (desc) {
-						strcat(xml, " - ");
-						strcat(xml, desc);
+					if (xstatus->len > 0) {
+						purple_debug_misc("oscar", "X-Status reply: %s\n", xstatus->str);
+						account = purple_connection_get_account(od->gc);
+						buddy = purple_find_buddy(account, bn);
+						presence = purple_buddy_get_presence(buddy);
+						status = purple_presence_get_active_status(presence);
+						purple_prpl_got_user_status(account, bn,
+								purple_status_get_id(status),
+								"message", xstatus->str, NULL);
 					}
-					purple_debug_misc("oscar", "X-Status reply: %s\n", xml);
-					account = purple_connection_get_account(od->gc);
-					buddy = purple_find_buddy(account, bn);
-					presence = purple_buddy_get_presence(buddy);
-					status = purple_presence_get_active_status(presence);
-					purple_prpl_got_user_status(account, bn,
-							purple_status_get_id(status), "message", xml, NULL);
+					g_string_free(xstatus, TRUE);
 				} else {
 					purple_debug_misc("oscar", "X-Status: Can't get XML reply string\n");
 				}
--- a/libpurple/protocols/oscar/oscar.c	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Sun Jul 25 01:11:18 2010 +0000
@@ -3028,12 +3028,23 @@
 			if (smstype != 0)
 				break;
 			taglen = byte_stream_getle32(&qbs);
+			if (taglen > 2000) {
+				/* Avoid trying to allocate large amounts of memory, in
+				   case we get something unexpected. */
+				break;
+			}
 			tagstr = byte_stream_getstr(&qbs, taglen);
 			if (tagstr == NULL)
 				break;
 			byte_stream_advance(&qbs, 3);
 			byte_stream_advance(&qbs, 4);
 			smslen = byte_stream_getle32(&qbs);
+			if (smslen > 2000) {
+				/* Avoid trying to allocate large amounts of memory, in
+				   case we get something unexpected. */
+				g_free(tagstr);
+				break;
+			}
 			smsmsg = byte_stream_getstr(&qbs, smslen);
 
 			/* Check if this is an SMS being sent from server */
--- a/libpurple/purple-url-handler	Tue Jul 20 02:48:15 2010 +0000
+++ b/libpurple/purple-url-handler	Sun Jul 25 01:11:18 2010 +0000
@@ -73,7 +73,8 @@
 def findaccount(protocolname, accountname="", matcher=None):
     if matcher:
         for account in cpurple.PurpleAccountsGetAll():
-            if accountname != "" and accountname != cpurple.PurpleAccountGetUsername(a):
+            if (protocolname != cpurple.PurpleAccountGetProtocolID(account)) or \
+               (accountname != "" and accountname != cpurple.PurpleAccountGetUsername(account)):
                 continue
             if matcher(account):
                 bring_account_online(account)
@@ -182,7 +183,7 @@
 
 def irc(uri):
     protocol = "prpl-irc"
-    match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri)
+    match = re.match(r"^irc:(//([^/]*))?/?([^?]*)(\?(.*))?", uri)
     if not match:
         print "Invalid irc URI: %s" % uri
         return
@@ -207,7 +208,7 @@
 
     def correct_server(account):
         username = cpurple.PurpleAccountGetUsername(account)
-        return ("@" in username) and (server == (username.split("@"))[1])
+        return ((server == "") or ("@" in username) and (server == (username.split("@"))[1]))
 
     account = findaccount(protocol, matcher=correct_server)
 
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in	Tue Jul 20 02:48:15 2010 +0000
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in	Sun Jul 25 01:11:18 2010 +0000
@@ -459,7 +459,7 @@
 wink.png            ;-)     ;)
 excited.png         :-D     :D     :->      :>
 neutral.png         :-|     :|
-shock.png           :-O     :O
+shocked.png         :-O     :O
 tongue.png          :-P     :P
 embarrassed.png     :-$     :$
 glasses-cool.png    8-)
--- a/po/ChangeLog	Tue Jul 20 02:48:15 2010 +0000
+++ b/po/ChangeLog	Sun Jul 25 01:11:18 2010 +0000
@@ -1,5 +1,8 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.7.2
+	* No changes
+
 version 2.7.1
 	* Chinese (Hong Kong) translation updated (Ambrose C. Li, Paladin R.
 	  Liu)
--- a/po/de.po	Tue Jul 20 02:48:15 2010 +0000
+++ b/po/de.po	Sun Jul 25 01:11:18 2010 +0000
@@ -11,14 +11,14 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-05-30 23:15-0400\n"
-"PO-Revision-Date: 2010-05-29 17:30+0200\n"
+"POT-Creation-Date: 2010-07-20 19:00+0200\n"
+"PO-Revision-Date: 2010-07-20 18:52+0200\n"
 "Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
-"Language: de\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 #. Translators may want to transliterate the name.
@@ -65,12 +65,27 @@
 msgid "Error"
 msgstr "Fehler"
 
+msgid "Account was not modified"
+msgstr "Konto wurde nicht modifiziert"
+
 msgid "Account was not added"
 msgstr "Konto wurde nicht hinzugefügt"
 
 msgid "Username of an account must be non-empty."
 msgstr "Benutzername eines Kontos darf nicht leer sein."
 
+msgid ""
+"The account's protocol cannot be changed while it is connected to the server."
+msgstr ""
+"Das Protokoll des Kontos kann nicht geändert werden solange das Konto mit "
+"dem Server verbunden ist."
+
+msgid ""
+"The account's username cannot be changed while it is connected to the server."
+msgstr ""
+"Der Benutzername des Kontos kann nicht geändert werden solange das Konto mit "
+"dem Server verbunden ist."
+
 msgid "New mail notifications"
 msgstr "Benachrichtigung über neue Mails"
 
@@ -1269,6 +1284,9 @@
 msgid "Someone says your username in chat"
 msgstr "Jemand nennt Ihren Benutzernamen im Chat"
 
+msgid "Attention received"
+msgstr "Aufmerksamkeitsgesuch erhalten"
+
 msgid "GStreamer Failure"
 msgstr "GStreamer-Fehler"
 
@@ -1685,8 +1703,12 @@
 "Diesem Zertifikat wird nicht vertraut, da kein Zertifikat bestätigen kann, "
 "dass ihm aktuell vertraut wird."
 
-msgid "The certificate is not valid yet."
-msgstr "Das Zertifikat ist noch nicht gültig."
+msgid ""
+"The certificate is not valid yet.  Check that your computer's date and time "
+"are accurate."
+msgstr ""
+"Das Zertifikat ist nicht mehr gültig.  Überprüfen Sie, ob Datum und Zeit "
+"Ihres Computers stimmen."
 
 msgid "The certificate has expired and should not be considered valid."
 msgstr ""
@@ -3857,6 +3879,19 @@
 "Der Server ist der Meinung, dass die Authentifizierung vollständig ist, der "
 "Client aber nicht"
 
+msgid "Server may require plaintext authentication over an unencrypted stream"
+msgstr ""
+"Der Server könnte eine Klartext-Authentifizierung über einen "
+"unverschlüsselten Kanal anfordern"
+
+#, c-format
+msgid ""
+"%s may require plaintext authentication over an unencrypted connection.  "
+"Allow this and continue authentication?"
+msgstr ""
+"%s könnte eine Klartext-Authentifizierung über einen unverschlüsselten Kanal "
+"anfordern.  Wollen Sie dies erlauben und mit der Authentifikation fortfahren?"
+
 msgid "SASL authentication failed"
 msgstr "SASL-Authentifizierung fehlgeschlagen"
 
@@ -6175,17 +6210,14 @@
 msgstr "Startbildschirm-Popup aktivieren"
 
 #. you were kicked
-#, fuzzy
 msgid "You have been kicked from this MultiMX."
-msgstr "Sie wurden hinausgeworfen: (%s)"
-
-#, fuzzy
+msgstr "Sie wurden von MultiMX hinausgeworfen."
+
 msgid "was kicked"
-msgstr "Falsches Ticket"
-
-#, fuzzy
+msgstr "wurde hinausgeworfen"
+
 msgid "_Room Name:"
-msgstr "_Raum:"
+msgstr "_Raumname:"
 
 #. we must have lost the connection, so terminate it so that we can reconnect
 msgid "We have lost the connection to MXit. Please reconnect."
@@ -6767,8 +6799,8 @@
 #, c-format
 msgid "Unable to send message. Could not get details for user (%s)."
 msgstr ""
-"Kann die Nachricht nicht senden. Kann die Details vom Benutzer nicht holen "
-"(%s)."
+"Kann die Nachricht nicht senden. Kann die Details vom Benutzer nicht holen (%"
+"s)."
 
 #, c-format
 msgid "Unable to add %s to your buddy list (%s)."
@@ -6786,8 +6818,8 @@
 #, c-format
 msgid "Unable to send message to %s. Could not create the conference (%s)."
 msgstr ""
-"Kann die Nachricht nicht an %s senden. Kann die Konferenz nicht erstellen "
-"(%s)."
+"Kann die Nachricht nicht an %s senden. Kann die Konferenz nicht erstellen (%"
+"s)."
 
 #, c-format
 msgid "Unable to send message. Could not create the conference (%s)."
@@ -7200,8 +7232,8 @@
 "(There was an error receiving this message.  Either you and %s have "
 "different encodings selected, or %s has a buggy client.)"
 msgstr ""
-"(Es gab einen Fehler beim Empfang dieser Nachricht.  Entweder haben Sie und "
-"%s unterschiedliche Kodierungen gesetzt oder %s hat einen fehlerhaften "
+"(Es gab einen Fehler beim Empfang dieser Nachricht.  Entweder haben Sie und %"
+"s unterschiedliche Kodierungen gesetzt oder %s hat einen fehlerhaften "
 "Client.)"
 
 #. Label
@@ -7512,10 +7544,10 @@
 msgid_plural ""
 "You missed %hu messages from %s because the rate limit has been exceeded."
 msgstr[0] ""
-"Sie haben %hu Nachricht von %s nicht erhalten, da die Senderate "
+"Sie haben %hu Nachricht von %s nicht erhalten, da die Datenrate "
 "überschritten wurde."
 msgstr[1] ""
-"Sie haben %hu Nachrichten von %s nicht erhalten, da die Senderate "
+"Sie haben %hu Nachrichten von %s nicht erhalten, da die Datenrate "
 "überschritten wurde."
 
 #, c-format
@@ -7989,11 +8021,11 @@
 msgid "Invalid SNAC"
 msgstr "Ungültiger SNAC"
 
-msgid "Rate to host"
-msgstr "Bewertung zum Host"
-
-msgid "Rate to client"
-msgstr "Bewertung zum Client"
+msgid "Server rate limit exceeded"
+msgstr "Server-Datenrate überschritten"
+
+msgid "Client rate limit exceeded"
+msgstr "Client-Datenrate überschritten"
 
 msgid "Service unavailable"
 msgstr "Dienst nicht verfügbar"
@@ -8428,8 +8460,8 @@
 #, c-format
 msgid "<b>Joining Qun %u is approved by admin %u for %s</b>"
 msgstr ""
-"<b>Das Betreten des Qun %u wurde vom Admin bestätigt wegen by admin %u for "
-"%s</b>"
+"<b>Das Betreten des Qun %u wurde vom Admin bestätigt wegen by admin %u for %"
+"s</b>"
 
 #, c-format
 msgid "<b>Removed buddy %u.</b>"
@@ -10283,8 +10315,8 @@
 msgid "Ignore conference and chatroom invitations"
 msgstr "Konferenz- und Chateinladungen ignorieren"
 
-msgid "Use account proxy for SSL connections"
-msgstr "Proxy-Zugang für SSL-Verbindungen benutzen"
+msgid "Use account proxy for HTTP and HTTPS connections"
+msgstr "Proxy-Zugang für HTTP- und HTTPS-Verbindungen benutzen"
 
 msgid "Chat room list URL"
 msgstr "Chatraumliste (URL)"
@@ -12501,8 +12533,8 @@
 "to multiple messaging services at once.  %s is written in C using GTK+.  %s "
 "is released, and may be modified and redistributed,  under the terms of the "
 "GPL version 2 (or later).  A copy of the GPL is distributed with %s.  %s is "
-"copyrighted by its contributors, a list of whom is also distributed with "
-"%s.  There is no warranty for %s.<BR><BR>"
+"copyrighted by its contributors, a list of whom is also distributed with %"
+"s.  There is no warranty for %s.<BR><BR>"
 msgstr ""
 "%s ist ein Nachrichtendienst, basierend auf libpurple, der die Verbindung zu "
 "mehreren Nachrichtendiensten gleichzeitig unterstützt.  %s wird in C "
@@ -13074,16 +13106,16 @@
 
 #, c-format
 msgid ""
-"Are you sure you want to permanently delete the log of the conversation in "
-"%s which started at %s?"
+"Are you sure you want to permanently delete the log of the conversation in %"
+"s which started at %s?"
 msgstr ""
 "Wollen Sie wirklich den Mitschnitt der Unterhaltung in %s, gestartet am %s, "
 "permanent löschen?"
 
 #, c-format
 msgid ""
-"Are you sure you want to permanently delete the system log which started at "
-"%s?"
+"Are you sure you want to permanently delete the system log which started at %"
+"s?"
 msgstr ""
 "Wollen Sie wirklich den Systemmitschnitt, gestartet am %s, permanent löschen?"
 
@@ -14003,9 +14035,6 @@
 msgid "Custom Smiley Manager"
 msgstr "Verwaltung für benutzerdefinierte Smileys"
 
-msgid "Attention received"
-msgstr "Aufmerksamkeitsgesuch erhalten"
-
 msgid "Select Buddy Icon"
 msgstr "Buddy-Icon auswählen"
 
@@ -15429,13 +15458,13 @@
 #, no-c-format
 msgid ""
 "Error Installing Spellchecking ($R3).$\\rIf retrying fails, manual "
-"installation instructions are at: http://developer.pidgin.im/wiki/Installing"
-"%20Pidgin#manual_win32_spellcheck_installation"
+"installation instructions are at: http://developer.pidgin.im/wiki/Installing%"
+"20Pidgin#manual_win32_spellcheck_installation"
 msgstr ""
 "Fehler beim Installieren der Rechtschreibkontrolle ($R3).$\\rFalls ein "
 "erneuter Versuch fehlschlägt, finden Sie Anweisungen zur manuellen "
-"Installation unter: http://developer.pidgin.im/wiki/Installing"
-"%20Pidgin#manual_win32_spellcheck_installation"
+"Installation unter: http://developer.pidgin.im/wiki/Installing%"
+"20Pidgin#manual_win32_spellcheck_installation"
 
 #. Installer Subsection Text
 msgid "GTK+ Runtime (required if not present)"
@@ -15515,6 +15544,15 @@
 msgid "You do not have permission to uninstall this application."
 msgstr "Sie haben keine Berechtigung, diese Anwendung zu deinstallieren."
 
+#~ msgid "The certificate is not valid yet."
+#~ msgstr "Das Zertifikat ist noch nicht gültig."
+
+#~ msgid "Rate to host"
+#~ msgstr "Bewertung zum Host"
+
+#~ msgid "Rate to client"
+#~ msgstr "Bewertung zum Client"
+
 #~ msgid "Unknown reason."
 #~ msgstr "Unbekannter Grund."