Mercurial > pidgin
diff libpurple/protocols/jabber/usermood.c @ 32777:3b1070cb4f29
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?
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Wed, 23 May 2012 05:01:14 +0000 |
parents | 2ec94166be43 |
children |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/usermood.c Wed May 23 03:25:01 2012 +0000 +++ b/libpurple/protocols/jabber/usermood.c Wed May 23 05:01:14 2012 +0000 @@ -115,10 +115,26 @@ {"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 @@ 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 @@ 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)