summaryrefslogtreecommitdiff
path: root/src/idle-handles.c
diff options
context:
space:
mode:
authorJonathon Jongsma <jonathon.jongsma@collabora.co.uk>2009-02-24 15:01:58 -0600
committerJonathon Jongsma <jonathon.jongsma@collabora.co.uk>2009-02-24 15:01:58 -0600
commit5258ef39b7e24faefd733d30b9abcf8453adb2f2 (patch)
treef883481804b8a09b41174a8fe05c9551afde8cf2 /src/idle-handles.c
parent1b6f1549a8c66356a9ea2d4a7240be98efb38ec7 (diff)
downloadtelepathy-idle-5258ef39b7e24faefd733d30b9abcf8453adb2f2.tar.gz
Be strict for what nicks we allow, and liberal for what nicks we accept from others
Bip has a nasty habit of sending backlog activity from a fictional '-bip' user. Unfortunately, a nick with a leading '-' character is illegal according to the IRC RFCs, but we have to accept it since people appear to be using it in the wild. This patch adds a flag to the nick validation script that specifies whether we should use strict mode or lenient mode. We use strict mode for validating local nicknames, and lenient mode for validating remote nicknames.
Diffstat (limited to 'src/idle-handles.c')
-rw-r--r--src/idle-handles.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/src/idle-handles.c b/src/idle-handles.c
index 73396c1..f5d0e5d 100644
--- a/src/idle-handles.c
+++ b/src/idle-handles.c
@@ -27,14 +27,28 @@
#include <telepathy-glib/errors.h>
#include <telepathy-glib/handle-repo-dynamic.h>
-gboolean idle_nickname_is_valid(const gchar *nickname) {
+#define IDLE_DEBUG_FLAG IDLE_DEBUG_PARSER
+#include "idle-debug.h"
+
+/* When strict_mode is true, we validate the nick strictly against the IRC
+ * RFCs (e.g. only ascii characters, no leading '-'. When strict_mode is
+ * false, we releax the requirements slightly. This is because we don't want
+ * to allow contribute to invalid nicks on IRC, but we want to be able to
+ * handle them if another client allows people to use invalid nicks */
+gboolean idle_nickname_is_valid(const gchar *nickname, gboolean strict_mode) {
const gchar *char_pos = nickname;
+ IDLE_DEBUG("Validating nickname '%s' with strict mode %d", nickname, strict_mode);
+
/* FIXME: also check for max length? */
if (!nickname || *nickname == '\0')
return FALSE;
- while (TRUE) {
+ while (*char_pos) {
+
+ /* only used for non-strict checks */
+ gunichar ucs4char = g_utf8_get_char_validated(char_pos, -1);
+ IDLE_DEBUG("testing character %d", ucs4char);
switch (*char_pos) {
case '[':
@@ -48,23 +62,35 @@ gboolean idle_nickname_is_valid(const gchar *nickname) {
case '}':
break;
- /* - not allowed as first char in a nickname */
+ /* '-' is technically not allowed as first char in a nickname */
case '-':
- if (char_pos == nickname)
- return FALSE;
- break;
-
- case '\0':
- return TRUE;
+ if (strict_mode) {
+ if (char_pos == nickname)
+ return FALSE;
+ }
break;
default:
- if (!(g_ascii_isalpha(*char_pos) || ((char_pos != nickname) && g_ascii_isdigit(*char_pos))))
- return FALSE;
+ if (strict_mode) {
+ /* only accept ascii characters in strict mode */
+ if (!(g_ascii_isalpha(*char_pos) || ((char_pos != nickname) && g_ascii_isdigit(*char_pos)))) {
+ IDLE_DEBUG("invalid character '%c'", *char_pos);
+ return FALSE;
+ }
+ } else {
+ /* allow unicode and digits as first char in non-strict mode */
+ if (!(g_unichar_isalpha(ucs4char) || g_unichar_isdigit(ucs4char))) {
+ IDLE_DEBUG("invalid character %d", ucs4char);
+ return FALSE;
+ }
+ }
break;
}
- ++char_pos;
+ /* in strict mode, a multi-byte character would have already failed the
+ * test above, so the following line should be equivalent to ++char, but
+ * it doesn't seem worthwhile to special-case it */
+ char_pos = g_utf8_find_next_char(char_pos, NULL);
}
return TRUE;
@@ -109,7 +135,7 @@ static gboolean _channelname_is_valid(const gchar *channel) {
}
static gchar *_nick_normalize_func(TpHandleRepoIface *repo, const gchar *id, gpointer ctx, GError **error) {
- if (!idle_nickname_is_valid(id)) {
+ if (!idle_nickname_is_valid(id, FALSE)) {
g_set_error(error, TP_ERRORS, TP_ERROR_INVALID_HANDLE, "invalid nickname");
return NULL;
}