pidgin: 79a577d0: jabber: Validate user moods, and make th...

darkrain42 at pidgin.im darkrain42 at pidgin.im
Wed May 23 01:18:34 EDT 2012


----------------------------------------------------------------------
Revision: 79a577d0889f9db570dd39f03efd0605e9aba218
Parent:   c783586116efc784f256230deebc63785a85afde
Author:   darkrain42 at pidgin.im
Date:     05/23/12 01:01:14
Branch:   im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/79a577d0889f9db570dd39f03efd0605e9aba218

Changelog: 

jabber: Validate user moods, and make the /mood cmd behave flexibly.

A user in Pidgin running "/mood ?" or "/mood -" would result in invalid
XML being sent to the server (similar to #14342, except '<-/>' or '<?/>').

Prevent this by ensuring the user is specifying something from the list.
The /mood command will also now try to treat its entire arguments as
a single string, and set that as the mood -- I figure this is what a
user would expect?

Changes against parent c783586116efc784f256230deebc63785a85afde

  patched  ChangeLog
  patched  libpurple/protocols/jabber/jabber.c
  patched  libpurple/protocols/jabber/usermood.c
  patched  libpurple/protocols/jabber/usermood.h

-------------- next part --------------
============================================================
--- ChangeLog	5a4561bb8357c230985a73f1d99098cd6c3e0585
+++ ChangeLog	1f0fbe0b557c962686d9606bf38142e72608555a
@@ -39,6 +39,7 @@ version 3.0.0 (??/??/????):
 	  to the core (and UIs) as incoming messages (Thijs Alkemade).
 	  (#14529)
 	* Support file transfers up to ~9 EiB.
+	* Invalid user moods can no longer be sent to the server.
 
 	Plugins:
 	* The Voice/Video Settings plugin supports using the sndio GStreamer
============================================================
--- libpurple/protocols/jabber/jabber.c	6af9f2854e3229d956ff808b18167eb71dfd48fc
+++ libpurple/protocols/jabber/jabber.c	0f5984a6923dac0c50285e8cc76270ea16e051e2
@@ -3575,16 +3575,32 @@ jabber_cmd_mood(PurpleConversation *conv
 	JabberStream *js = purple_connection_get_protocol_data(purple_account_get_connection(account));
 
 	if (js->pep) {
-		/* if no argument was given, unset mood */
+		gboolean ret;
+
 		if (!args || !args[0]) {
-			jabber_mood_set(js, NULL, NULL);
-		} else if (!args[1]) {
-			jabber_mood_set(js, args[0], NULL);
+			/* No arguments; unset mood */
+			ret = jabber_mood_set(js, NULL, NULL);
 		} else {
-			jabber_mood_set(js, args[0], args[1]);
+			/* At least one argument.  Relying on the list of arguments
+			 * being NULL-terminated.
+			 */
+			ret = jabber_mood_set(js, args[0], args[1]);
+			if (!ret) {
+				/* Let's try again */
+				char *tmp = g_strjoin(" ", args[0], args[1], NULL);
+				ret = jabber_mood_set(js, "undefined", tmp);
+				g_free(tmp);
+			}
 		}
 
-		return PURPLE_CMD_RET_OK;
+		if (ret) {
+			return PURPLE_CMD_RET_OK;
+		} else {
+			purple_conversation_write(conv, NULL,
+				_("Failed to specify mood"),
+				PURPLE_MESSAGE_ERROR, time(NULL));
+			return PURPLE_CMD_RET_FAILED;
+		}
 	} else {
 		/* account does not support PEP, can't set a mood */
 		purple_conversation_write(conv, NULL,
@@ -3713,7 +3729,7 @@ static void jabber_register_commands(Pur
 	    			  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM |
 	    			  PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
 	    			  "prpl-jabber", jabber_cmd_mood,
-	    			  _("mood: Set current user mood"), NULL);
+	    			  _("mood <mood> [text]: Set current user mood"), NULL);
 	commands = g_slist_prepend(commands, GUINT_TO_POINTER(id));
 
 	g_hash_table_insert(jabber_cmds, plugin, commands);
============================================================
--- libpurple/protocols/jabber/usermood.c	892cc11f7a3655233ee93f88e22ab9f251880681
+++ libpurple/protocols/jabber/usermood.c	4204a3409450c86ca68e9af66e5db655582da49c
@@ -115,10 +115,26 @@ static PurpleMood moods[] = {
 	{"undefined", N_("Undefined"), NULL},
 	{"weak", N_("Weak"), NULL},
 	{"worried", N_("Worried"), NULL},
-	/* Mark the last record. */
+	/* Mar last record. */
 	{NULL, NULL, NULL}
 };
 
+static const PurpleMood*
+find_mood_by_name(const gchar *name)
+{
+	int i;
+
+	g_return_val_if_fail(name && *name, NULL);
+
+	for (i = 0; moods[i].mood != NULL; ++i) {
+		if (g_str_equal(name, moods[i].mood)) {
+			return &moods[i];
+		}
+	}
+
+	return NULL;
+}
+
 static void jabber_mood_cb(JabberStream *js, const char *from, xmlnode *items) {
 	/* it doesn't make sense to have more than one item here, so let's just pick the first one */
 	xmlnode *item = xmlnode_get_child(items, "item");
@@ -139,15 +155,13 @@ static void jabber_mood_cb(JabberStream 
 				if (!moodtext) /* only pick the first one */
 					moodtext = xmlnode_get_data(moodinfo);
 			} else {
-				int i;
-				for (i = 0; moods[i].mood; ++i) {
-					/* verify that the mood is known (valid) */
-					if (!strcmp(moodinfo->name, moods[i].mood)) {
-						newmood = moods[i].mood;
-						break;
-					}
-				}
+				const PurpleMood *target_mood;
+
+				/* verify that the mood is known (valid) */
+				target_mood = find_mood_by_name(moodinfo->name);
+				newmood = target_mood ? target_mood->mood : NULL;
 			}
+
 			if (newmood != NULL && moodtext != NULL)
 			   break;
 		}
@@ -170,26 +184,41 @@ void jabber_mood_init(void) {
 	jabber_pep_register_handler("http://jabber.org/protocol/mood", jabber_mood_cb);
 }
 
-void jabber_mood_set(JabberStream *js, const char *mood, const char *text) {
+gboolean
+jabber_mood_set(JabberStream *js, const char *mood, const char *text)
+{
+	const PurpleMood *target_mood = NULL;
 	xmlnode *publish, *moodnode;
 
+	if (mood && *mood) {
+		target_mood = find_mood_by_name(mood);
+		/* Mood specified, but is invalid --
+		 * fail so that the command can handle this.
+		 */
+		if (!target_mood)
+			return FALSE;
+	}
+
 	publish = xmlnode_new("publish");
 	xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/mood");
 	moodnode = xmlnode_new_child(xmlnode_new_child(publish, "item"), "mood");
 	xmlnode_set_namespace(moodnode, "http://jabber.org/protocol/mood");
-	if (mood && *mood) {
-		/* if mood is NULL, set an empty mood node, meaning: unset mood */
+
+	if (target_mood) {
+		/* If target_mood is not NULL, then
+		 * target_mood->mood == mood, and is a valid element name.
+		 */
 	    xmlnode_new_child(moodnode, mood);
-	}
 
-	if (text && *text) {
-		xmlnode *textnode = xmlnode_new_child(moodnode, "text");
-		xmlnode_insert_data(textnode, text, -1);
+		/* Only set text when setting a mood */
+		if (text && *text) {
+			xmlnode *textnode = xmlnode_new_child(moodnode, "text");
+			xmlnode_insert_data(textnode, text, -1);
+		}
 	}
 
 	jabber_pep_publish(js, publish);
-	/* publish is freed by jabber_pep_publish -> jabber_iq_send -> jabber_iq_free
-	   (yay for well-defined memory management rules) */
+	return TRUE;
 }
 
 PurpleMood *jabber_get_moods(PurpleAccount *account)
============================================================
--- libpurple/protocols/jabber/usermood.h	d20b021d8b2a06f7dc870613c8c8ed2e5d04361a
+++ libpurple/protocols/jabber/usermood.h	7f4ea0b588473aca197075dc22bceb66a3d366d3
@@ -30,9 +30,20 @@ void jabber_mood_init(void);
 
 void jabber_mood_init(void);
 
-void jabber_mood_set(JabberStream *js,
-		     const char *mood, /* must be one of the valid strings defined in the XEP */
-		     const char *text /* might be NULL */);
+/**
+ * Sets / unsets the mood for the specified account.  The mood passed in
+ * must either be NULL, "", or one of the moods returned by
+ * jabber_get_moods().
+ *
+ * @param js The JabberStream object.
+ * @param mood The mood to set, NULL, or ""
+ * @param text Optional text that goes along with a mood.  Only used when
+ *             setting a mood (not when unsetting a mood).
+ *
+ * @return FALSE if an invalid mood was specified, or TRUE otherwise.
+ */
+gboolean
+jabber_mood_set(JabberStream *js, const char *mood, const char *text);
 
 PurpleMood *jabber_get_moods(PurpleAccount *account);
 


More information about the Commits mailing list