changeset 30481:4463cd2aba2d

merge of 'b5086a027dfbc0926b74627b9783794d250c2cb4' and 'ea400018f9483ac602c6fa1e16d8c94e37a655b2'
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Fri, 14 May 2010 06:57:26 +0000
parents 3f6daa187665 (current diff) eafb928fe614 (diff)
children 783d736704b8
files COPYRIGHT ChangeLog libpurple/protocols/msn/slp.c libpurple/protocols/msn/slplink.c
diffstat 37 files changed, 321 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue May 11 06:32:00 2010 +0000
+++ b/COPYRIGHT	Fri May 14 06:57:26 2010 +0000
@@ -118,6 +118,7 @@
 Jeramey Crawford
 Michael Culbertson
 Steven Danna
+Simon Danner
 Chris Davies
 Josh Davis
 Martijn Dekker
--- a/ChangeLog	Tue May 11 06:32:00 2010 +0000
+++ b/ChangeLog	Fri May 14 06:57:26 2010 +0000
@@ -1,6 +1,16 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-version 2.7.0 (??/??/????):
+version 2.7.1 (??/??/????):
+	Bonjour:
+	* Fix a crash on disconnect.
+
+	MSN:
+	* Fix unnecessary bandwidth consumption for buddy icon requests when
+	  buddies have capital letters in their passport addresses.
+	* Support for direct connections, enabling faster file transfers,
+	  smiley and buddy icon loading.  (Gábor Szuromi)
+
+version 2.7.0 (05/12/2010):
 	General:
 	* Changed GTK+ minimum version requirement to 2.10.0.
 	* Changed GLib minimum version requirement to 2.12.0.
@@ -81,8 +91,7 @@
 	* Support for version 9 of the MSN protocol has been removed.  This
 	  version is no longer supported on the servers.
 	* Support file transfer thumbnails (previews) for images.
-	* Support for direct connections, enabling faster file transfers,
-	  smiley and buddy icon loading.  (Gábor Szuromi)
+	* Fix CVE-2010-1624 (custom emoticon remote crash).
 
 	XMPP:
 	* Direct messages to a specific resource only upon receipt of a message
--- a/ChangeLog.API	Tue May 11 06:32:00 2010 +0000
+++ b/ChangeLog.API	Fri May 14 06:57:26 2010 +0000
@@ -1,6 +1,8 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-version 2.7.0 (??/??/????):
+version 2.7.1 (??/??/????):
+
+version 2.7.0 (05/12/2010):
 	libpurple:
 		Added:
 		* Account signals (see account-signals.dox); useful for D-Bus
--- a/ChangeLog.win32	Tue May 11 06:32:00 2010 +0000
+++ b/ChangeLog.win32	Fri May 14 06:57:26 2010 +0000
@@ -1,4 +1,8 @@
-version 2.7.0 (??/??/????):
+version 2.7.1 (??/??/????):
+	* Fix a regression introduced in 2.7.0 that caused Window Flashing not
+	  to work.
+
+version 2.7.0 (05/12/2010):
 	* Updated GTK+ to 2.16.6
 	* Private GTK+ Runtime now used (GTK+ Installer no longer supported)
 	* Minimum required GTK+ version increased to 2.14.7
--- a/NEWS	Tue May 11 06:32:00 2010 +0000
+++ b/NEWS	Fri May 14 06:57:26 2010 +0000
@@ -2,6 +2,31 @@
 
 Our development blog is available at: http://planet.pidgin.im
 
+2.7.0 (05/12/2010):
+	John: We FINALLY got the ICQ X-Status stuff merged in!  And a few other
+	patches that have been sitting on Trac forever.  Couple that with some
+	new features and we have an excellent release for all of you!
+
+	Marcus: Finally time for a new release, seems like it took
+	quite a while this time.  But then again, there are some new features
+	in there, like file transfer preview (thumbnails) support (only on MSN
+	so far), plus a lot of bug fixes.  Enjoy!
+
+	Paul: Yay, a new release!  I don't think I added very much useful to
+	this release, other than fixing a paste bug from Chrome (no weird
+	characters appended to the end of your URI).  Enjoy!
+
+	Jorge: This is my first NEWS!  I'm not sure I added something nice
+	to this release.  I know it took a lot of time to bring this one
+	out, however I'm really excited by this release.  I hope everyone
+	likes the new features this release brings.
+
+	Elliott: This release took so long, I had to go check the ChangeLog
+	just to see what happened.  I doubt many people will notice, but we
+	dropped support for many old things, like GTK+<2.10 and MSNP9.  In more
+	exciting news, we have file transfer previews on MSN, and support for
+	setting moods on ICQ and XMPP (which has been waiting forever.)
+
 2.6.6 (02/18/2010):
 	Mark: This release includes some great little changes and fixes a few
 	security-related bugs.  See the ChangeLog for details.
--- a/configure.ac	Tue May 11 06:32:00 2010 +0000
+++ b/configure.ac	Fri May 14 06:57:26 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], [0])
+m4_define([purple_micro_version], [1])
 m4_define([purple_version_suffix], [devel])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
@@ -55,7 +55,7 @@
 m4_define([gnt_lt_current], [7])
 m4_define([gnt_major_version], [2])
 m4_define([gnt_minor_version], [7])
-m4_define([gnt_micro_version], [0])
+m4_define([gnt_micro_version], [1])
 m4_define([gnt_version_suffix], [devel])
 m4_define([gnt_version],
           [gnt_major_version.gnt_minor_version.gnt_micro_version])
--- a/libpurple/gconf/Makefile.am	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/gconf/Makefile.am	Fri May 14 06:57:26 2010 +0000
@@ -2,17 +2,17 @@
 
 EXTRA_DIST = purple.schemas.in
 
-if GCONF_SCHEMAS_INSTALL
-
 if INSTALL_I18N
 schema_in_files = purple.schemas.in
 schema_DATA = $(schema_in_files:.schemas.in=.schemas)
 @INTLTOOL_SCHEMAS_RULE@
-endif #INSTALL_I18N
 
+if GCONF_SCHEMAS_INSTALL
 install-data-local:
 	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA) 2>&1 | \
 		grep -v "^WARNING: failed to install schema" | grep -v "^Attached schema" 1>&2
 else
 install-data-local:
 endif #GCONF_SCHEMAS_INSTALL
+
+endif #INSTALL_I18N
--- a/libpurple/protocols/bonjour/bonjour.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Fri May 14 06:57:26 2010 +0000
@@ -70,7 +70,6 @@
 			buddy = (PurpleBuddy *) bnode;
 			if (purple_buddy_get_account(buddy) != account)
 				continue;
-			purple_prpl_got_user_status(account, purple_buddy_get_name(buddy), "offline", NULL);
 			purple_account_remove_buddy(account, buddy, NULL);
 			purple_blist_remove_buddy(buddy);
 		}
@@ -172,7 +171,9 @@
 		g_free(bd->jabber_data);
 	}
 
-	/* Delete the bonjour group */
+	/* Delete the bonjour group
+	 * (purple_blist_remove_group will bail out if the group isn't empty)
+	 */
 	if (bonjour_group != NULL)
 		purple_blist_remove_group(bonjour_group);
 
--- a/libpurple/protocols/bonjour/jabber.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Fri May 14 06:57:26 2010 +0000
@@ -1184,7 +1184,7 @@
 		buddies = purple_find_buddies(jdata->account, NULL);
 		for (l = buddies; l; l = l->next) {
 			BonjourBuddy *bb = purple_buddy_get_protocol_data((PurpleBuddy*) l->data);
-			if (bb != NULL) {
+			if (bb && bb->conversation) {
 				/* Any ongoing connection attempt is cancelled
 				 * by _purple_connection_destroy */
 				bb->conversation->connect_data = NULL;
--- a/libpurple/protocols/gg/Makefile.am	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/gg/Makefile.am	Fri May 14 06:57:26 2010 +0000
@@ -9,6 +9,7 @@
 	lib/http.c \
 	lib/libgadu.c \
 	lib/libgadu-config.h \
+	lib/libgadu-internal.h \
 	lib/libgadu.h \
 	lib/obsolete.c \
 	lib/protocol.h \
@@ -30,6 +31,7 @@
 	lib/http.c \
 	lib/libgadu.c \
 	lib/libgadu-config.h \
+	lib/libgadu-internal.h \
 	lib/libgadu.h \
 	lib/obsolete.c \
 	lib/protocol.h \
--- a/libpurple/protocols/gg/lib/common.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/gg/lib/common.c	Fri May 14 06:57:26 2010 +0000
@@ -101,7 +101,7 @@
  * \param format Format wiadomości (zgodny z \c printf)
  * \param ap Lista argumentów (zgodna z \c printf)
  */
-static void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
+void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
 {
 	if (gg_debug_handler_session)
 		(*gg_debug_handler_session)(sess, level, format, ap);
--- a/libpurple/protocols/gg/lib/libgadu-internal.h	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/gg/lib/libgadu-internal.h	Fri May 14 06:57:26 2010 +0000
@@ -26,5 +26,6 @@
 char *gg_cp_to_utf8(const char *b);
 char *gg_utf8_to_cp(const char *b);
 int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length);
+void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap);
 
 #endif /* LIBGADU_INTERNAL_H */
--- a/libpurple/protocols/gg/lib/libgadu.h	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/gg/lib/libgadu.h	Fri May 14 06:57:26 2010 +0000
@@ -1245,8 +1245,8 @@
 struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async) GG_DEPRECATED;
 
 int gg_resolve(int *fd, int *pid, const char *hostname) GG_DEPRECATED;
+int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) GG_DEPRECATED;
 void gg_resolve_pthread_cleanup(void *arg, int kill) GG_DEPRECATED;
-int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) GG_DEPRECATED;
 
 struct gg_change_info_request {
 	char *first_name;
--- a/libpurple/protocols/jabber/message.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/jabber/message.c	Fri May 14 06:57:26 2010 +0000
@@ -75,12 +75,8 @@
 	jbr = jabber_buddy_find_resource(jb, jid->resource);
 
 	if(!jm->xhtml && !jm->body) {
-		if (jbr) {
-			if (jm->chat_state != JM_STATE_NONE)
-				jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
-			else
-				jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED;
-		}
+		if (jbr && jm->chat_state != JM_STATE_NONE)
+			jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
 
 		if(JM_STATE_COMPOSING == jm->chat_state) {
 			serv_got_typing(gc, jm->from, 0, PURPLE_TYPING);
@@ -142,10 +138,13 @@
 		}
 
 		if(jbr) {
-			if (jm->chat_state != JM_STATE_NONE)
-				jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
-			else
-				jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED;
+			/* Treat SUPPORTED as a terminal with no escape :) */
+			if (jbr->chat_states != JABBER_CHAT_STATES_SUPPORTED) {
+				if (jm->chat_state != JM_STATE_NONE)
+					jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
+				else
+					jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED;
+			}
 
 			if(jbr->thread_id)
 				g_free(jbr->thread_id);
@@ -1250,7 +1249,14 @@
 
 	g_free(resource);
 
-	if (!jbr || (jbr->chat_states == JABBER_CHAT_STATES_UNSUPPORTED))
+	/* We know this entity doesn't support chat states */
+	if (jbr && jbr->chat_states == JABBER_CHAT_STATES_UNSUPPORTED)
+		return 0;
+
+	/* *If* we don't have presence /and/ the buddy can't see our
+	 * presence, don't send typing notifications.
+	 */
+	if (!jbr && !(jb->subscription & JABBER_SUB_FROM))
 		return 0;
 
 	/* TODO: figure out threading */
--- a/libpurple/protocols/msn/slp.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/msn/slp.c	Fri May 14 06:57:26 2010 +0000
@@ -1119,6 +1119,8 @@
 	conv = swboard->conv;
 
 	body = msn_message_get_bin_data(msg, &body_len);
+	if (!body || !body_len)
+		return;
 	body_str = g_strndup(body, body_len);
 
 	/* MSN Messenger 7 may send more than one MSNObject in a single message...
--- a/libpurple/protocols/msn/slplink.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/msn/slplink.c	Fri May 14 06:57:26 2010 +0000
@@ -393,6 +393,7 @@
 msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
 {
 	MsnMessage *msg;
+	const char *passport;
 
 	slpmsg->msg = msg = msn_message_new_msnslp();
 
@@ -431,7 +432,8 @@
 
 	msg->msnslp_header.total_size = slpmsg->size;
 
-	msn_message_set_attr(msg, "P2P-Dest", slplink->remote_user);
+	passport = purple_normalize(slplink->session->account, slplink->remote_user);
+	msn_message_set_attr(msg, "P2P-Dest", passport);
 
 	msg->ack_cb = msg_ack;
 	msg->nak_cb = msg_nak;
--- a/libpurple/protocols/mxit/actions.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/actions.c	Fri May 14 06:57:26 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.
  *
@@ -409,10 +326,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/login.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/login.c	Fri May 14 06:57:26 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	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/multimx.c	Fri May 14 06:57:26 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	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/multimx.h	Fri May 14 06:57:26 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	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.c	Fri May 14 06:57:26 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 );
 
@@ -418,6 +421,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 );
 
@@ -635,7 +656,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	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/mxit.h	Fri May 14 06:57:26 2010 +0000
@@ -151,7 +151,6 @@
 
 	/* personal (profile) */
 	struct MXitProfile*	profile;					/* user's profile information */
-	int					mood;						/* user's current mood */
 
 	/* libpurple */
 	PurpleAccount*		acc;						/* pointer to the libpurple internal account struct */
--- a/libpurple/protocols/mxit/protocol.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/protocol.c	Fri May 14 06:57:26 2010 +0000
@@ -962,6 +962,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
@@ -1355,6 +1380,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 );
@@ -1917,6 +1948,8 @@
 				/* profile update */
 		case CP_CMD_SPLASHCLICK :
 				/* splash-screen clickthrough */
+		case CP_CMD_MSGEVENT :
+				/* event message */
 				break;
 
 		default :
@@ -2020,6 +2053,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 :
--- a/libpurple/protocols/mxit/protocol.h	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/protocol.h	Fri May 14 06:57:26 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 )
@@ -126,6 +129,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 +151,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 +170,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) */
@@ -284,6 +293,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	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/roster.c	Fri May 14 06:57:26 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	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/protocols/mxit/roster.h	Fri May 14 06:57:26 2010 +0000
@@ -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/libpurple/tests/check_libpurple.c	Tue May 11 06:32:00 2010 +0000
+++ b/libpurple/tests/check_libpurple.c	Fri May 14 06:57:26 2010 +0000
@@ -37,16 +37,22 @@
 
 static void
 purple_check_init(void) {
-	gchar *home_dir;
-
 	g_type_init();
 
 	purple_eventloop_set_ui_ops(&eventloop_ui_ops);
 
+#if 0
 	/* build our fake home directory */
-	home_dir = g_build_path(G_DIR_SEPARATOR_S, BUILDDIR, "libpurple", "tests", "home", NULL);
-	purple_util_set_user_dir(home_dir);
-	g_free(home_dir);
+	{
+		gchar *home_dir;
+
+		home_dir = g_build_path(G_DIR_SEPARATOR_S, BUILDDIR, "libpurple", "tests", "home", NULL);
+		purple_util_set_user_dir(home_dir);
+		g_free(home_dir);
+	}
+#else
+	purple_util_set_user_dir("/dev/null");
+#endif
 
 	purple_core_init("check");
 }
--- a/pidgin.spec.in	Tue May 11 06:32:00 2010 +0000
+++ b/pidgin.spec.in	Fri May 14 06:57:26 2010 +0000
@@ -415,7 +415,7 @@
 %doc PLUGIN_HOWTO
 
 %dir %{_includedir}/libpurple
-%{_includedir}/libpurple/*.h
+%{_includedir}/libpurple/*
 %{_libdir}/libpurple.so
 %{_libdir}/pkgconfig/purple.pc
 %{_datadir}/aclocal/purple.m4
@@ -470,6 +470,9 @@
 %endif
 
 %changelog
+* Thu May 13 2010 Stu Tomlinson <stu@nosnilmot.com>
+- Include all libpurple headers in libpurple-devel
+
 * Sat Sep 05 2009 Stu Tomlinson <stu@nosnilmot.com>
 - Disable Voice & Video unless --with vv is used
 - Add BuildRequires for libidn-devel
--- a/pidgin/Makefile.am	Tue May 11 06:32:00 2010 +0000
+++ b/pidgin/Makefile.am	Fri May 14 06:57:26 2010 +0000
@@ -25,6 +25,7 @@
 		win32/nsis/pixmaps/pidgin-header.bmp \
 		win32/nsis/pixmaps/pidgin-intro.bmp \
 		win32/nsis/pixmaps/pidgin-install.ico \
+		win32/nsis/available.lst \
 		win32/nsis/pidgin-installer.nsi \
 		win32/nsis/pidgin-plugin.nsh \
 		win32/nsis/langmacros.nsh \
--- a/pidgin/pixmaps/emotes/small/16/Makefile.am	Tue May 11 06:32:00 2010 +0000
+++ b/pidgin/pixmaps/emotes/small/16/Makefile.am	Fri May 14 06:57:26 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
--- a/pidgin/win32/gtkwin32dep.c	Tue May 11 06:32:00 2010 +0000
+++ b/pidgin/win32/gtkwin32dep.c	Fri May 14 06:57:26 2010 +0000
@@ -327,6 +327,7 @@
 		info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
 	} else
 		info.dwFlags = FLASHW_STOP;
+	FlashWindowEx(&info);
 	info.dwTimeout = 0;
 
 }
--- a/po/ChangeLog	Tue May 11 06:32:00 2010 +0000
+++ b/po/ChangeLog	Fri May 14 06:57:26 2010 +0000
@@ -1,5 +1,7 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.7.1
+
 version 2.7.0
 	* Afrikaans translation updated (Friedel Wolff)
 	* Albanian translation updated (Besnik Bleta)
--- a/po/ca.po	Tue May 11 06:32:00 2010 +0000
+++ b/po/ca.po	Fri May 14 06:57:26 2010 +0000
@@ -33,8 +33,8 @@
 msgstr ""
 "Project-Id-Version: Pidgin\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-05-06 07:36+0200\n"
-"PO-Revision-Date: 2010-05-08 16:11+0200\n"
+"POT-Creation-Date: 2010-05-11 22:08+0200\n"
+"PO-Revision-Date: 2010-05-11 22:10+0200\n"
 "Last-Translator: Josep Puigdemont i Casamajó <josep.puigdemont@gmail.com>\n"
 "Language-Team: Catalan <tradgnome@softcatala.net>\n"
 "MIME-Version: 1.0\n"
@@ -12215,6 +12215,9 @@
 msgid "Arabic"
 msgstr "Àrab"
 
+msgid "Assamese"
+msgstr "Assamès"
+
 msgid "Belarusian Latin"
 msgstr "Bielorús (llatí)"
 
@@ -12342,6 +12345,9 @@
 msgid "Macedonian"
 msgstr "Macedoni"
 
+msgid "Malayalam"
+msgstr "Malaiàlam"
+
 msgid "Mongolian"
 msgstr "Mongol"
 
--- a/po/de.po	Tue May 11 06:32:00 2010 +0000
+++ b/po/de.po	Fri May 14 06:57:26 2010 +0000
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-05-09 16:11+0200\n"
-"PO-Revision-Date: 2010-05-09 16:05+0200\n"
+"POT-Creation-Date: 2010-05-11 17:11+0200\n"
+"PO-Revision-Date: 2010-05-11 17:11+0200\n"
 "Last-Translator: Björn Voigt <bjoern@cs.tu-berlin.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -12260,6 +12260,9 @@
 msgid "Arabic"
 msgstr "Arabisch"
 
+msgid "Assamese"
+msgstr "Assamesisch"
+
 msgid "Belarusian Latin"
 msgstr "Weißrussisch (Latin)"
 
@@ -12267,10 +12270,10 @@
 msgstr "Bulgarisch"
 
 msgid "Bengali"
-msgstr "Bengalisch"
+msgstr "Bengali"
 
 msgid "Bengali-India"
-msgstr "Bengalisch"
+msgstr "Bengali-Indien"
 
 msgid "Bosnian"
 msgstr "Bosnisch"
@@ -12386,6 +12389,9 @@
 msgid "Macedonian"
 msgstr "Makedonisch"
 
+msgid "Malayalam"
+msgstr "Malayalam"
+
 msgid "Mongolian"
 msgstr "Mongolisch"
 
@@ -12426,7 +12432,7 @@
 msgstr "Portugiesisch (Brasilien)"
 
 msgid "Pashto"
-msgstr "Paschtunisch"
+msgstr "Paschtu"
 
 msgid "Romanian"
 msgstr "Rumänisch"
@@ -12456,7 +12462,7 @@
 msgstr "Swahili"
 
 msgid "Tamil"
-msgstr "Tamilisch"
+msgstr "Tamil"
 
 msgid "Telugu"
 msgstr "Telugu"