changeset 30424:2213849c45a2

propagate from branch 'im.pidgin.pidgin' (head 7072aab86b390122c32faa675284a753c9e97034) to branch 'im.pidgin.pidgin.mxit' (head f36af3ce21a72ca6c4616108e7e156666d092009)
author andrew.victor@mxit.com
date Thu, 20 May 2010 11:25:03 +0000
parents 623660917282 (current diff) 08cae68b25dc (diff)
children cbae3d450db8
files
diffstat 21 files changed, 343 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/mxit/actions.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/actions.c	Thu May 20 11:25:03 2010 +0000
@@ -35,89 +35,6 @@
 #include	"profile.h"
 
 
-/* MXit Moods */
-static const char*	moods[] = {
-	/* 0 */		N_("None"),
-	/* 1 */		N_("Angry"),
-	/* 2 */		N_("Excited"),
-	/* 3 */		N_("Grumpy"),
-	/* 4 */		N_("Happy"),
-	/* 5 */		N_("In Love"),
-	/* 6 */		N_("Invincible"),
-	/* 7 */		N_("Sad"),
-	/* 8 */		N_("Hot"),
-	/* 9 */		N_("Sick"),
-	/* 10 */	N_("Sleepy")
-};
-
-
-/*------------------------------------------------------------------------
- * The user has selected to change their current mood.
- *
- *  @param gc		The connection object
- *  @param fields	The fields from the request pop-up
- */
-static void mxit_cb_set_mood( PurpleConnection* gc, PurpleRequestFields* fields )
-{
-	struct MXitSession*		session	= (struct MXitSession*) gc->proto_data;
-	int						mood	= purple_request_fields_get_choice( fields, "mood" );
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_set_mood (%i)\n", mood );
-
-	if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-		purple_debug_error( MXIT_PLUGIN_ID, "Unable to set mood; account offline.\n" );
-		return;
-	}
-
-	/* Save the new mood in session */
-	session->mood = mood;
-
-	/* now send the update to MXit */
-	mxit_send_mood( session, mood );
-}
-
-
-/*------------------------------------------------------------------------
- * Create and display the mood selection window to the user.
- *
- *  @param action	The action object
- */
-static void mxit_cb_action_mood( PurplePluginAction* action )
-{
-	PurpleConnection*			gc		= (PurpleConnection*) action->context;
-	struct MXitSession*			session	= (struct MXitSession*) gc->proto_data;
-
-	PurpleRequestFields*		fields	= NULL;
-	PurpleRequestFieldGroup*	group	= NULL;
-	PurpleRequestField*			field	= NULL;
-	unsigned int				i		= 0;
-
-	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_action_mood\n" );
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new( NULL );
-	purple_request_fields_add_group( fields, group );
-
-	/* show current mood */
-	field = purple_request_field_string_new( "current", _( "Current Mood" ), _( moods[session->mood] ), FALSE );
-	purple_request_field_string_set_editable( field, FALSE );	/* current mood field is not editable */
-	purple_request_field_group_add_field( group, field );
-
-	/* add all moods to list */
-	field = purple_request_field_choice_new( "mood", _( "New Mood" ), 0 );
-	for ( i = 0; i < ARRAY_SIZE( moods ); i++ ) {
-		purple_request_field_choice_add( field, _( moods[i] ) );
-	}
-	purple_request_field_set_required( field, TRUE );
-	purple_request_field_choice_set_default_value( field, session->mood );
-	purple_request_field_group_add_field( group, field );
-
-	/* (reference: "libpurple/request.h") */
-	purple_request_fields( gc, _( "Mood" ), _( "Change your Mood" ), _( "How do you feel right now?" ), fields, _( "Set" ),
-			G_CALLBACK( mxit_cb_set_mood ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
-}
-
-
 /*------------------------------------------------------------------------
  * The user has selected to change their profile.
  *
@@ -308,6 +225,13 @@
 	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 );
+		purple_request_field_string_set_editable( field, FALSE );
+		purple_request_field_group_add_field( group, field );
+	}
+
 	/* pin */
 	field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE );
 	purple_request_field_string_set_masked( field, TRUE );
@@ -335,7 +259,7 @@
 	purple_request_field_group_add_field( group, field );
 
 	/* title */
-	field = purple_request_field_string_new( "title", _( "Job Title" ), profile->title, FALSE );
+	field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE );
 	purple_request_field_group_add_field( group, field );
 
 	/* first name */
@@ -387,11 +311,12 @@
 	char	version[256];
 
 	g_snprintf( version, sizeof( version ), "MXit libPurple Plugin v%s\n"
-											"MXit Client Protocol v%s\n\n"
+											"MXit Client Protocol v%i.%i\n\n"
 											"Author:\nPieter Loubser\n\n"
 											"Contributors:\nAndrew Victor\n\n"
 											"Testers:\nBraeme Le Roux\n\n",
-											MXIT_PLUGIN_VERSION, MXIT_CP_RELEASE );
+											MXIT_PLUGIN_VERSION,
+											( MXIT_CP_PROTO_VESION / 10 ), ( MXIT_CP_PROTO_VESION % 10 ) );
 
 	mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "About" ), version );
 }
@@ -409,10 +334,6 @@
 	PurplePluginAction*		action	= NULL;
 	GList*					m		= NULL;
 
-	/* display / change mood */
-	action = purple_plugin_action_new( _( "Change Mood..." ), mxit_cb_action_mood );
-	m = g_list_append( m, action );
-
 	/* display / change profile */
 	action = purple_plugin_action_new( _( "Change Profile..." ), mxit_cb_action_profile );
 	m = g_list_append( m, action );
--- a/libpurple/protocols/mxit/formcmds.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/formcmds.c	Thu May 20 11:25:03 2010 +0000
@@ -42,7 +42,7 @@
 typedef enum
 {
 	MXIT_CMD_UNKNOWN = 0,		/* Unknown command */
-	MXIT_CMD_CLRSCR,			/* Clear screen (clrmsgscreen) */
+	MXIT_CMD_CLEAR,				/* Clear (clear) */
 	MXIT_CMD_SENDSMS,			/* Send SMS (sendsms) */
 	MXIT_CMD_REPLY,				/* Reply (reply) */
 	MXIT_CMD_PLATREQ,			/* Platform Request (platreq) */
@@ -138,8 +138,8 @@
 			type = g_hash_table_lookup(hash, "type");
 			if (type == NULL)								/* no command provided */
 				return MXIT_CMD_UNKNOWN;
-			else if (strcmp(type, "clrmsgscreen") == 0)		/* clear the screen */
-				return MXIT_CMD_CLRSCR;
+			else if (strcmp(type, "clear") == 0)			/* clear */
+				return MXIT_CMD_CLEAR;
 			else if (strcmp(type, "sendsms") == 0)			/* send an SMS */
 				return MXIT_CMD_SENDSMS;
 			else if (strcmp(type, "reply") == 0)			/* list of options */
@@ -205,27 +205,38 @@
 
 
 /*------------------------------------------------------------------------
- * Process a ClearScreen MXit command.
+ * Process a Clear MXit command.
+ *  [::op=cmd|type=clear|clearmsgscreen=true|auto=true|id=12345:]
  *
- *  @param session			The MXit session object
- *  @param from				The sender of the message.
+ *  @param session		The MXit session object
+ *  @param from			The sender of the message.
+ *  @param hash			The MXit command <key,value> map
  */
-static void command_clearscreen(struct MXitSession* session, const char* from)
+static void command_clear(struct MXitSession* session, const char* from, GHashTable* hash)
 {
 	PurpleConversation *conv;
+	char* clearmsgscreen;
 
-    conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, session->acc);
-    if (conv == NULL) {
-        purple_debug_error(MXIT_PLUGIN_ID, _( "Conversation with '%s' not found\n" ), from);
-        return;
-    }
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, session->acc);
+	if (conv == NULL) {
+		purple_debug_error(MXIT_PLUGIN_ID, _( "Conversation with '%s' not found\n" ), from);
+		return;
+	}
 
-	purple_conversation_clear_message_history(conv);			// TODO: This doesn't actually clear the screen.
+	clearmsgscreen = g_hash_table_lookup(hash, "clearmsgscreen");
+	if ( (clearmsgscreen) && (strcmp(clearmsgscreen, "true") == 0) ) {
+		/* this is a command to clear the chat screen */
+		purple_debug_info(MXIT_PLUGIN_ID, "Clear the screen\n");
+
+		purple_conversation_clear_message_history(conv);			// TODO: This doesn't actually clear the screen.
+	}
 }
 
 
 /*------------------------------------------------------------------------
  * Process a Reply MXit command.
+ *  [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|id=12345:]
+ *  [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|id=12345:]
  *
  *  @param mx			The received message data object
  *  @param hash			The MXit command <key,value> map
@@ -234,10 +245,21 @@
 {
 	char* replymsg;
 	char* selmsg;
+	char* nm;
 
 	selmsg = g_hash_table_lookup(hash, "selmsg");			/* find the selection message */
 	replymsg = g_hash_table_lookup(hash, "replymsg");		/* find the reply message */
-	if ((selmsg) && (replymsg)) {
+	nm = g_hash_table_lookup(hash, "nm");					/* name parameter */
+	if ((selmsg) && (replymsg) && (nm)) {
+		gchar*	seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
+		gchar*	replycmd = g_strdup_printf("::type=reply|nm=%s|res=%s|err=0:", nm, replymsg);
+
+		mxit_add_html_link( mx, replycmd, seltext );
+
+		g_free(seltext);
+		g_free(replycmd);
+	}
+	else if ((selmsg) && (replymsg)) {
 		gchar*	seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
 
 		mxit_add_html_link( mx, purple_url_decode(replymsg), seltext );
@@ -366,8 +388,8 @@
 			MXitCommandType type = command_type(hash);
 
 			switch (type) {
-				case MXIT_CMD_CLRSCR :
-					command_clearscreen(mx->session, mx->from);
+				case MXIT_CMD_CLEAR :
+					command_clear(mx->session, mx->from, hash);
 					break;
 				case MXIT_CMD_REPLY :
 					command_reply(mx, hash);
--- a/libpurple/protocols/mxit/login.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/login.c	Thu May 20 11:25:03 2010 +0000
@@ -67,7 +67,7 @@
 	/* configure the connection (reference: "libpurple/connection.h") */
 	con = purple_account_get_connection( account );
 	con->proto_data = session;
-	con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML;
+	con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS;
 	session->con = con;
 
 	/* add account */
--- a/libpurple/protocols/mxit/multimx.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/multimx.c	Thu May 20 11:25:03 2010 +0000
@@ -142,6 +142,10 @@
 	multimx->chatid = groupchatID++;
 	multimx->state = state;
 
+	/* determine our nickname (from profile) */
+	if (session->profile && (session->profile->nickname[0] != '\0'))
+		multimx->nickname = g_strdup(session->profile->nickname);
+
 	/* Add to GroupChat list */
 	session->rooms = g_list_append(session->rooms, multimx);
 
@@ -160,6 +164,10 @@
 	/* Remove from GroupChat list */
 	session->rooms = g_list_remove(session->rooms, multimx);
 
+	/* free nickname */
+	if (multimx->nickname)
+		g_free(multimx->nickname);
+
 	/* Deallocate it */
 	free (multimx);
 	multimx = NULL;
@@ -213,6 +221,38 @@
 
 
 /*------------------------------------------------------------------------
+ * A user was kicked from the GroupChat.
+ *
+ *  @param session		The MXit session object
+ *  @param multimx		The MultiMX room object
+ *  @param nickname		The nickname of the user who was kicked
+ */
+static void member_kicked(struct MXitSession* session, struct multimx* multimx, const char* nickname)
+{
+	PurpleConversation *convo;
+
+	purple_debug_info(MXIT_PLUGIN_ID, "member_kicked: '%s'\n", nickname);
+
+	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;
+	}
+
+	/* who was kicked? - compare to our original nickname */
+	if (purple_utf8_strcasecmp(nickname, multimx->nickname) == 0)
+	{
+		/* you were kicked */
+		purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL));
+		purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
+		serv_got_chat_left(session->con, multimx->chatid);
+	}
+	else
+		purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked"));
+}
+
+
+/*------------------------------------------------------------------------
  * Update the full GroupChat member list.
  *
  *  @param session		The MXit session object
@@ -375,6 +415,12 @@
 			member_removed(mx->session, multimx, msg);
 			mx->processed = TRUE;
 		}
+		else if ((ofs = strstr(msg, " has been kicked")) != NULL) {
+			/* Somebody has been kicked */
+			*ofs = '\0';
+			member_kicked(mx->session, multimx, msg);
+			mx->processed = TRUE;
+		}
 		else if (g_str_has_prefix(msg, "The following users are in this MultiMx:") == TRUE) {
 			member_update(mx->session, multimx, msg + strlen("The following users are in this MultiMx:") + 1);
 			mx->processed = TRUE;
@@ -582,8 +628,8 @@
 	mxit_send_message(session, multimx->roomid, message, TRUE, FALSE);
 	
 	/* Determine our nickname to display */
-	if (session->profile && (session->profile->nickname[0] != '\0'))		/* default is profile name (since that's what everybody else sees) */
-		 nickname = session->profile->nickname;
+	if (multimx->nickname)
+		nickname = multimx->nickname;
 	else
 		nickname = purple_account_get_alias(purple_connection_get_account(gc));		/* local alias */
 
--- a/libpurple/protocols/mxit/multimx.h	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/multimx.h	Thu May 20 11:25:03 2010 +0000
@@ -41,6 +41,7 @@
 	char	roomname[MXIT_CP_MAX_ALIAS_LEN];	/* name of the room */
 	char	roomid[MXIT_CP_MAX_JID_LEN];		/* internal JID for room */
 	int		chatid;								/* libpurple chat ID */
+	char*	nickname;							/* our nickname in the room */
 	short	state;								/* state */
 };
 
--- a/libpurple/protocols/mxit/mxit.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.c	Thu May 20 11:25:03 2010 +0000
@@ -92,6 +92,9 @@
 		goto skip;
 	con = purple_account_get_connection( account );
 
+	/* determine if it's a command-response to send */
+	is_command = g_str_has_prefix( parts[4], "::type=reply|" );
+
 	/* send click message back to MXit */
 	mxit_send_message( con->proto_data, parts[3], parts[4], FALSE, is_command );
 
@@ -349,6 +352,10 @@
 	if ( contact->subtype != 0 )
 		purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
 
+	/* rejection message */
+	if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) )
+		purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg );
+
 	/* hidden number */
 	if ( contact->flags & MXIT_CFLAG_HIDDEN )
 		purple_notify_user_info_add_pair( info, _( "Hidden Number" ), _( "Yes" ) );
@@ -418,6 +425,24 @@
 	char*					statusmsg1;
 	char*					statusmsg2;
 
+	/* Handle mood changes */
+	if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+		const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME );
+		int mood;
+
+		/* convert the purple mood to a mxit mood */
+		mood = mxit_convert_mood( moodid );
+		if ( mood < 0 ) {
+			/* error, mood not found */
+			purple_debug_info( MXIT_PLUGIN_ID, "Mood status NOT found! (id = %s)\n", moodid );
+			return;
+		}
+
+		/* update mood state */
+		mxit_send_mood( session, mood );
+		return;
+	}
+
 	/* get the status id (reference: "libpurple/status.h") */
 	statusid = purple_status_get_id( status );
 
@@ -470,6 +495,8 @@
 			g_free( contact->statusMsg );
 		if ( contact->avatarId )
 			g_free( contact->avatarId );
+		if ( contact->msg )
+			g_free( contact->msg );
 		g_free( contact );
 	}
 
@@ -531,8 +558,8 @@
 static void mxit_get_info( PurpleConnection *gc, const char *who )
 {
 	struct MXitSession*		session			= (struct MXitSession*) gc->proto_data;
-	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 };
+	const char*				profilelist[]	= { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
+												CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY };
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who );
 
@@ -635,7 +662,7 @@
 	mxit_get_text_table,	/* get_account_text_table */
 	NULL,					/* initiate_media */
 	NULL,					/* get_media_caps */
-	NULL,					/* get_moods */
+	mxit_get_moods,			/* get_moods */
 	NULL,					/* set_public_alias */
 	NULL					/* get_public_alias */
 };
--- a/libpurple/protocols/mxit/mxit.h	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.h	Thu May 20 11:25:03 2010 +0000
@@ -63,7 +63,7 @@
 /* Plugin details */
 #define		MXIT_PLUGIN_ID				"prpl-loubserp-mxit"
 #define		MXIT_PLUGIN_NAME			"MXit"
-#define		MXIT_PLUGIN_VERSION			"2.3.0"
+#define		MXIT_PLUGIN_VERSION			"2.4.0"
 #define		MXIT_PLUGIN_EMAIL			"Pieter Loubser <libpurple@mxit.com>"
 #define		MXIT_PLUGIN_WWW				"http://www.mxit.com"
 #define		MXIT_PLUGIN_SUMMARY			"MXit Protocol Plugin"
@@ -151,7 +151,7 @@
 
 	/* personal (profile) */
 	struct MXitProfile*	profile;					/* user's profile information */
-	int					mood;						/* user's current mood */
+	char*				mxitId;						/* the user's MXitId */
 
 	/* libpurple */
 	PurpleAccount*		acc;						/* pointer to the libpurple internal account struct */
--- a/libpurple/protocols/mxit/profile.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/profile.c	Thu May 20 11:25:03 2010 +0000
@@ -123,15 +123,14 @@
 	purple_notify_user_info_add_pair( info, _( "Nick 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" ) );
-
-	purple_notify_user_info_add_section_break( info );
+//	purple_notify_user_info_add_pair( info, _( "Hidden Number" ), profile->hidden ? _( "Yes" ) : _( "No" ) );
 
 	/* optional information */
-	purple_notify_user_info_add_pair( info, _( "Job Title" ), profile->title );
+//	purple_notify_user_info_add_pair( info, _( "Title" ), profile->title );
 	purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname );
 	purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname );
-	purple_notify_user_info_add_pair( info, _( "Email" ), profile->email );
+//	purple_notify_user_info_add_pair( info, _( "Email" ), profile->email );
+	purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry );
 
 	purple_notify_user_info_add_section_break( info );
 
@@ -151,6 +150,10 @@
 
 		/* subscription type */
 		purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
+
+		/* 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	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/profile.h	Thu May 20 11:25:03 2010 +0000
@@ -43,6 +43,7 @@
 	char		lastname[64];						/* user's last name (aka 'surname') */
 	char		email[64];							/* user's email address */
 	char		mobilenr[21];						/* user's mobile number */
+	char		regcountry[3];						/* user's registered country code */
 
 	gboolean	hidden;								/* set if the user's msisdn should remain hidden */
 };
--- a/libpurple/protocols/mxit/protocol.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/protocol.c	Thu May 20 11:25:03 2010 +0000
@@ -672,10 +672,12 @@
 	/* convert the packet to a byte stream */
 	datalen = sprintf( 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",					/* dialingcode\1locale */
+								"%s%c%s%c"					/* dialingcode\1locale\1 */
+								"%i%c%i%c%i",				/* maxReplyLen\1protocolVer\1lastRosterUpdate */
 								session->encpwd, CP_FLD_TERM, MXIT_CP_VERSION, CP_FLD_TERM, 1, CP_FLD_TERM,
 								MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, MXIT_CP_FEATURES, CP_FLD_TERM,
-								session->dialcode, CP_FLD_TERM, locale
+								session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
+								CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
 	);
 
 	/* include "custom resource" information */
@@ -962,6 +964,31 @@
 
 
 /*------------------------------------------------------------------------
+ * Send a message event packet.
+ *
+ *  @param session		The MXit session object
+ *  @param to           The username of the original sender (ie, recipient of the event)
+ *  @param id			The identifier of the event (received in message)
+ *  @param event		Identified the type of event
+ */
+void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event)
+{
+	char		data[CP_MAX_PACKET];
+	int			datalen;
+
+	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 */
+								to, CP_FLD_TERM, id, CP_FLD_TERM, event
+	);
+
+	/* queue packet for transmission */
+	mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
+}
+
+
+/*------------------------------------------------------------------------
  * Send packet to create a MultiMX room.
  *
  *  @param session		The MXit session object
@@ -1275,6 +1302,10 @@
 		session->http_sesid = atoi( records[0]->fields[0]->data );
 	}
 
+	/* extract MXitId (from protocol 5.9) */
+	if ( records[1]->fcount >= 9 )
+		session->mxitId = g_strdup( records[1]->fields[8]->data );
+
 	/* display the current splash-screen */
 	if ( splash_popup_enabled( session ) )
 		splash_display( session );
@@ -1355,6 +1386,12 @@
 		return;
 	}
 
+	if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
+		/* delivery notification is requested */
+		if ( records[0]->fcount >= 4 )
+			mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
+	}
+
 	/* create and initialise new markup struct */
 	mx = g_new0( struct RXMsgData, 1 );
 	mx->msg = g_string_sized_new( msglen );
@@ -1482,10 +1519,14 @@
 		contact->mood = atoi( rec->fields[5]->data );
 
 		if ( rec->fcount > 6 ) {
-			/* added in protocol 5.9.0 - flags & subtype */
+			/* added in protocol 5.9 - flags & subtype */
 			contact->flags = atoi( rec->fields[6]->data );
 			contact->subtype = rec->fields[7]->data[0];
 		}
+		if ( rec->fcount > 8 ) {
+			/* added in protocol 6.0 - reject message */
+			contact->msg = g_strdup( rec->fields[8]->data );
+		}
 
 		/* add the contact to the buddy list */
 		if ( contact-> type == MXIT_TYPE_MULTIMX )			/* contact is a MultiMX room */
@@ -1551,7 +1592,16 @@
 
 	purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
 
-	profile = g_new0( struct MXitProfile, 1 );
+	if ( records[0]->fields[0]->len == 0 ) {
+		/* no MXitId provided, so this must be our own profile information */
+		if ( session->profile == NULL )
+			session->profile = g_new0( struct MXitProfile, 1 );
+		profile = session->profile;
+	}
+	else {
+		/* is a buddy's profile */
+		profile = g_new0( struct MXitProfile, 1 );
+	}
 
 	/* set the count for attributes */
 	count = atoi( records[0]->fields[1]->data );
@@ -1616,23 +1666,19 @@
 			/* mobile number */
 			g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
 		}
+		else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
+			/* registered country */
+			g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
+		}
 		else {
 			/* invalid profile attribute */
 			purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
 		}
 	}
 
-	if ( records[0]->fields[0]->len == 0 ) {
-		/* no MXit id provided, so this must be our own profile information */
-		if ( session->profile )
-			g_free( session->profile );
-		session->profile = profile;
-	}
-	else {
-		/* display other user's profile */
+	/* if this is not our profile, just display it */
+	if ( profile != session->profile ) {
 		mxit_show_profile( session, mxitId, profile );
-
-		/* cleanup */
 		g_free( profile );
 	}
 }
@@ -1917,6 +1963,8 @@
 				/* profile update */
 		case CP_CMD_SPLASHCLICK :
 				/* splash-screen clickthrough */
+		case CP_CMD_MSGEVENT :
+				/* event message */
 				break;
 
 		default :
@@ -2020,6 +2068,7 @@
 				mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
 				break;
 		case CP_CMD_SPLASHCLICK :
+		case CP_CMD_MSGEVENT :
 				/* ignore error */
 				break;
 		case CP_CMD_PING :
@@ -2438,6 +2487,8 @@
 	mxit_free_emoticon_cache( session );
 
 	/* free allocated memory */
+	if ( session->mxitId )
+		g_free( session->mxitId );
 	g_free( session->encpwd );
 	session->encpwd = NULL;
 
--- a/libpurple/protocols/mxit/protocol.h	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/protocol.h	Thu May 20 11:25:03 2010 +0000
@@ -72,6 +72,9 @@
 #define		MXIT_CF_EXT_MARKUP		0x040000
 #define		MXIT_CF_PLAIN_PWD		0x080000
 #define		MXIT_CF_NO_GATEWAYS		0x100000
+#define		MXIT_CF_NO_AVATARS		0x200000
+#define		MXIT_CF_GAMING			0x400000
+#define		MXIT_CF_GAMING_UPDATE	0x800000
 
 /* Client features supported by this implementation */
 #define		MXIT_CP_FEATURES		( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 )
@@ -82,11 +85,12 @@
 
 /* MXit client version */
 #define		MXIT_CP_DISTCODE		"P"						/* client distribution code (magic, do not touch!) */
-#define		MXIT_CP_RELEASE			"5.9.0"					/* client protocol release version supported */
+#define		MXIT_CP_RELEASE			"5.9.0"					/* client version */
 #define		MXIT_CP_ARCH			"Y"						/* client architecture series (Y not for Yoda but for PC-client) */
 #define		MXIT_CLIENT_ID			"LP"					/* client ID as specified by MXit */
 #define		MXIT_CP_PLATFORM		"PURPLE"				/* client platform */
 #define		MXIT_CP_VERSION			MXIT_CP_DISTCODE"-"MXIT_CP_RELEASE"-"MXIT_CP_ARCH"-"MXIT_CP_PLATFORM
+#define		MXIT_CP_PROTO_VESION	60						/* client protocol version */
 
 /* set operating system name */
 #if defined( __APPLE__ )
@@ -126,6 +130,7 @@
 #define		CP_CMD_MEDIA			0x001B					/* (27) get multimedia message */
 #define		CP_CMD_SPLASHCLICK		0x001F					/* (31) splash-screen clickthrough */
 #define		CP_CMD_STATUS			0x0020					/* (32) set shown presence & status */
+#define		CP_CMD_MSGEVENT			0x0023					/* (35) Raise message event */ 
 #define		CP_CMD_MOOD				0x0029					/* (41) set mood */
 #define		CP_CMD_KICK				0x002B					/* (43) login kick */
 #define		CP_CMD_GRPCHAT_CREATE	0x002C					/* (44) create new groupchat */
@@ -147,6 +152,8 @@
 #define		RX_STATE_PROC			0x03					/* process read data */
 
 /* message flags */
+#define		CP_MSG_NOTIFY_DELIVERY	0x0002					/* request delivery notification */
+#define		CP_MSG_NOTIFY_READ		0x0004					/* request read notification */
 #define		CP_MSG_ENCRYPTED		0x0010					/* message is encrypted */
 #define		CP_MSG_MARKUP			0x0200					/* message may contain markup */
 #define		CP_MSG_EMOTICON			0x0400					/* message may contain custom emoticons */
@@ -164,6 +171,9 @@
 #define		CP_MSGTYPE_FORM			0x06					/* mxit custom form */
 #define		CP_MSGTYPE_COMMAND		0x07					/* mxit command */
 
+/* message event types */
+#define		CP_MSGEVENT_DELIVERED	0x02					/* message was delivered */
+#define		CP_MSGEVENT_DISPLAYED	0x04					/* message was viewed */
 
 /* extended profile attribute fields */
 #define		CP_PROFILE_BIRTHDATE	"birthdate"				/* Birthdate (String - ISO 8601 format) */
@@ -179,6 +189,7 @@
 #define		CP_PROFILE_LASTNAME		"lastname"				/* Last name (UTF8 String) */
 #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) */
 
 /* extended profile field types */
 #define		CP_PROF_TYPE_BOOL		0x02					/* boolean profile attribute type */
@@ -284,6 +295,7 @@
 void mxit_send_deny_sub( struct MXitSession* session, const char* username );
 void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname );
 void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
+void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
 
 void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
 void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
--- a/libpurple/protocols/mxit/roster.c	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/roster.c	Thu May 20 11:25:03 2010 +0000
@@ -81,6 +81,12 @@
 		statuslist = g_list_append( statuslist, type );
 	}
 
+	/* add Mood option */
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE,
+		PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new( PURPLE_TYPE_STRING ),
+		NULL);
+	statuslist = g_list_append( statuslist, type );
+
 	return statuslist;
 }
 
@@ -127,6 +133,57 @@
  * Moods
  */
 
+/* moods (reference: libpurple/status.h) */
+static PurpleMood mxit_moods[] = {
+	{"angry",		N_("Angry"),		NULL},
+	{"excited",		N_("Excited"),		NULL},
+	{"grumpy",		N_("Grumpy"),		NULL},
+	{"happy",		N_("Happy"),		NULL},
+	{"in_love",		N_("In love"),		NULL},
+	{"invincible",	N_("Invincible"),	NULL},
+	{"sad",			N_("Sad"),			NULL},
+	{"hot",			N_("Hot"),			NULL},
+	{"sick",		N_("Sick"),			NULL},
+	{"sleepy",		N_("Sleepy"),		NULL},
+	/* Mark the last record. */
+	{ NULL, NULL, NULL }
+};
+
+
+/*------------------------------------------------------------------------
+ * Returns the MXit mood code, given the unique mood ID.
+ *
+ *  @param id		The mood ID
+ *  @return			The MXit mood code
+ */
+int mxit_convert_mood( const char* id )
+{
+	unsigned int	i;
+
+	/* Mood is being unset */
+	if ( id == NULL )
+		return MXIT_MOOD_NONE;
+
+	for ( i = 0; i < ARRAY_SIZE( mxit_moods ) - 1; i++ ) {
+		if ( strcmp( mxit_moods[i].mood, id ) == 0 )	/* mood found! */
+			return i + 1;		/* because MXIT_MOOD_NONE is 0 */
+	}
+
+	return -1;
+}
+
+
+/*------------------------------------------------------------------------
+ * Return the list of MXit-supported moods.
+ *
+ *  @param account	The MXit account object
+ */
+PurpleMood* mxit_get_moods(PurpleAccount *account)
+{
+	return mxit_moods;
+}
+
+
 /*------------------------------------------------------------------------
  * Returns the MXit mood as a string, given the MXit mood's ID.
  *
@@ -259,6 +316,12 @@
 			else
 				purple_prpl_got_user_status( session->acc, newbuddy->name, 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, newbuddy->name, "mood" );
+			else
+				purple_prpl_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+
 			/* update avatar */
 			if ( contact->avatarId ) {
 				mxit_get_avatar( session, newbuddy->name, contact->avatarId );
@@ -346,6 +409,12 @@
 
 	/* update the buddy's status (reference: "libpurple/prpl.h") */
 	purple_prpl_got_user_status( session->acc, contact->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, contact->username, "mood" );
+	else
+		purple_prpl_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
 }
 
 
@@ -388,6 +457,10 @@
 	contact->presence = presence;	
 	contact->mood = mood;
 
+	/* validate mood */
+	if (( contact->mood < MXIT_MOOD_NONE ) || ( contact->mood > MXIT_MOOD_SLEEPY ))
+		contact->mood = MXIT_MOOD_NONE;
+
 	g_strlcpy( contact->customMood, customMood, sizeof( contact->customMood ) );
 	// TODO: Download custom mood frame.
 
@@ -419,6 +492,12 @@
 		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	Thu May 13 05:11:00 2010 +0000
+++ b/libpurple/protocols/mxit/roster.h	Thu May 20 11:25:03 2010 +0000
@@ -105,7 +105,7 @@
 	short		presence;							/* presence state */
 	short		subtype;							/* subscription type */
 
-	char*		msg;								/* invite message */
+	char*		msg;								/* invite/rejection message */
 
 	char		customMood[16];						/* custom mood */
 	char*		statusMsg;							/* status message */
@@ -119,6 +119,7 @@
 const char* mxit_convert_subtype_to_name( short subtype );
 
 /* Moods */
+int mxit_convert_mood( const char* id );
 const char* mxit_convert_mood_to_name( short id );
 
 /* MXit Protocol callbacks */
@@ -134,6 +135,7 @@
 void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias );
 void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group );
 void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies );
+PurpleMood* mxit_get_moods(PurpleAccount *account);
 
 
 #endif		/* _MXIT_ROSTER_H_ */
--- a/pidgin/pixmaps/emotes/default/24/Makefile.am	Thu May 13 05:11:00 2010 +0000
+++ b/pidgin/pixmaps/emotes/default/24/Makefile.am	Thu May 20 11:25:03 2010 +0000
@@ -27,6 +27,7 @@
     car.png \
     cat.png \
     chicken.png \
+    chilli.png \
     cigarette.png \
     clap.png \
     clock.png \
@@ -109,6 +110,7 @@
     moneymouth.png \
     monkey.png \
     moon.png \
+    mrgreen.png \
     msn-away.png \
     msn-busy.png \
     msn_online.png \
Binary file pidgin/pixmaps/emotes/default/24/chilli.png has changed
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in	Thu May 13 05:11:00 2010 +0000
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in	Thu May 20 11:25:03 2010 +0000
@@ -451,3 +451,41 @@
 ! monkey.png        :-(|)   :(|)    8-|)
 ! cyclops.png       O-)     o-)
 
+
+# MXit standard emoticons
+[MXit]
+happy.png           :-)     :)
+sad.png             :-(     :(
+wink.png            ;-)     ;)
+excited.png         :-D     :D     :->      :>
+neutral.png         :-|     :|
+shock.png           :-O     :O
+tongue.png          :-P     :P
+embarrassed.png     :-$     :$
+glasses-cool.png    8-)
+in_love.png         (H)
+rose.png            (F)
+### Added in v3.0
+boy.png             (m)
+girl.png            (f)
+star.png            (*)
+chilli.png          (c)
+kiss.png            (x)
+lamp.png            (i)
+pissed-off.png      :e      :-e
+shut-mouth.png      :-x     :x
+thunder.png         (z)
+coffee.png          (U)
+mrgreen.png         (G)
+### Added in v5.0
+sick.png            :o(
+excruciating.png    :-{     :{
+amorous.png         :-}     :}
+eyeroll.png         8-o     8o
+crying.png          :'(
+thinking.png        :-?     :?
+drool.png           :-~     :~
+sleeping.png        :-z     :z
+lying.png           :L)
+glasses-nerdy.png   8-|     8|
+pirate.png          P-)
Binary file pidgin/pixmaps/emotes/default/24/mrgreen.png has changed
--- a/pidgin/pixmaps/emotes/small/16/Makefile.am	Thu May 13 05:11:00 2010 +0000
+++ b/pidgin/pixmaps/emotes/small/16/Makefile.am	Thu May 20 11:25:03 2010 +0000
@@ -5,7 +5,10 @@
     cinema.png \
     disappointed.png \
     embarrassed.png \
+    grumpy.png \
+    hot.png \
     internet.png \
+    invincible.png \
     music.png \
     restroom.png \
     search.png \
Binary file pidgin/pixmaps/emotes/small/16/grumpy.png has changed
Binary file pidgin/pixmaps/emotes/small/16/hot.png has changed
Binary file pidgin/pixmaps/emotes/small/16/invincible.png has changed