From d239a1278b4c5761cc08f0514e411b1594c6ed23 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sat, 26 Jan 2013 16:13:11 +0000 Subject: [PATCH] Fixed jid handling to allow @ and / in resource --- src/jid.c | 113 ++++++++++++++++++++++------------------------- tests/test_jid.c | 48 ++++++++++++++++++++ 2 files changed, 100 insertions(+), 61 deletions(-) diff --git a/src/jid.c b/src/jid.c index 66a066dd..1798c987 100644 --- a/src/jid.c +++ b/src/jid.c @@ -36,70 +36,59 @@ jid_create(const gchar * const str) if (str == NULL) { return NULL; } - if (strlen(str) == 0) { - return NULL; - } gchar *trimmed = g_strdup(str); + if (strlen(trimmed) == 0) { + return NULL; + } + if (g_str_has_prefix(trimmed, "/") || g_str_has_prefix(trimmed, "@")) { g_free(trimmed); return NULL; - } else if (g_str_has_suffix(trimmed, "/") || g_str_has_suffix(trimmed, "@")) { - g_free(trimmed); + } + + if (!g_utf8_validate(trimmed, -1, NULL)) { return NULL; } - gchar *slashp = g_strrstr(trimmed, "/"); + result = malloc(sizeof(struct jid_t)); + result->localpart = NULL; + result->domainpart = NULL; + result->resourcepart = NULL; + result->barejid = NULL; + result->fulljid = NULL; - // has resourcepart - if (slashp != NULL) { - result = malloc(sizeof(struct jid_t)); - result->str = strdup(trimmed); - result->resourcepart = g_strdup(slashp + 1); - result->barejid = g_strndup(trimmed, strlen(trimmed) - strlen(result->resourcepart) - 1); - result->fulljid = g_strdup(trimmed); + gchar *atp = g_utf8_strchr(trimmed, -1, '@'); + gchar *slashp = g_utf8_strchr(trimmed, -1, '/'); + gchar *domain_start = trimmed; - gchar *atp = g_strrstr(result->barejid, "@"); - // has domain and local parts - if (atp != NULL) { - result->domainpart = g_strndup(atp + 1, strlen(trimmed)); - result->localpart = g_strndup(trimmed, strlen(trimmed) - (strlen(result->resourcepart) + strlen(result->domainpart) + 2)); - - // only domain part - } else { - result->domainpart = strdup(result->barejid); - result->localpart = NULL; - } - - g_free(trimmed); - return result; - - // no resourcepart - } else { - result = malloc(sizeof(struct jid_t)); - result->str = strdup(trimmed); - result->resourcepart = NULL; - result->barejid = g_strdup(trimmed); - result->fulljid = NULL; - - gchar *atp = g_strrstr(trimmed, "@"); - - // has local and domain parts - if (atp != NULL) { - result->domainpart = g_strdup(atp + 1); - result->localpart = g_strndup(trimmed, strlen(trimmed) - strlen(result->domainpart) - 1); - - // only domain part - } else { - result->domainpart = g_strdup(trimmed); - result->localpart = NULL; - } - - g_free(trimmed); - return result; + if (atp != NULL) { + result->localpart = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, atp)); + domain_start = atp + 1; } + + if (slashp != NULL) { + result->resourcepart = g_strdup(slashp + 1); + result->domainpart = g_utf8_substring(domain_start, 0, g_utf8_pointer_to_offset(domain_start, slashp)); + result->barejid = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, slashp)); + result->fulljid = g_strdup(trimmed); + } else { + result->domainpart = g_strdup(domain_start); + result->barejid = g_strdup(trimmed); + } + + if (result->domainpart == NULL) { + free(trimmed); + return NULL; + } + + result->str = g_strdup(trimmed); + + free(trimmed); + + return result; } Jid * @@ -142,21 +131,23 @@ jid_is_valid_room_form(Jid *jid) gboolean parse_room_jid(const char * const full_room_jid, char **room, char **nick) { - gboolean result = FALSE; - char **tokens = g_strsplit(full_room_jid, "/", 0); + Jid *jid = jid_create(full_room_jid); - if (tokens == NULL) + if (jid == NULL) { return FALSE; - - if (tokens[0] != NULL && tokens[1] != NULL) { - *room = strdup(tokens[0]); - *nick = strdup(tokens[1]); - result = TRUE; } - g_strfreev(tokens); + if (jid->resourcepart == NULL) { + jid_destroy(jid); + return FALSE; + } - return result; + *room = strdup(jid->barejid); + *nick = strdup(jid->resourcepart); + + jid_destroy(jid); + + return TRUE; } /* diff --git a/tests/test_jid.c b/tests/test_jid.c index 99ae4f12..ce33909a 100644 --- a/tests/test_jid.c +++ b/tests/test_jid.c @@ -119,6 +119,50 @@ void create_room_jid_returns_nick(void) assert_string_equals("myname", result->resourcepart); } +void create_with_slash_in_resource(void) +{ + Jid *result = jid_create("room@conference.domain.org/my/nick"); + + assert_string_equals("room", result->localpart); + assert_string_equals("conference.domain.org", result->domainpart); + assert_string_equals("my/nick", result->resourcepart); + assert_string_equals("room@conference.domain.org", result->barejid); + assert_string_equals("room@conference.domain.org/my/nick", result->fulljid); +} + +void create_with_at_in_resource(void) +{ + Jid *result = jid_create("room@conference.domain.org/my@nick"); + + assert_string_equals("room", result->localpart); + assert_string_equals("conference.domain.org", result->domainpart); + assert_string_equals("my@nick", result->resourcepart); + assert_string_equals("room@conference.domain.org", result->barejid); + assert_string_equals("room@conference.domain.org/my@nick", result->fulljid); +} + +void create_with_at_and_slash_in_resource(void) +{ + Jid *result = jid_create("room@conference.domain.org/my@nick/something"); + + assert_string_equals("room", result->localpart); + assert_string_equals("conference.domain.org", result->domainpart); + assert_string_equals("my@nick/something", result->resourcepart); + assert_string_equals("room@conference.domain.org", result->barejid); + assert_string_equals("room@conference.domain.org/my@nick/something", result->fulljid); +} + +void create_full_with_trailing_slash(void) +{ + Jid *result = jid_create("room@conference.domain.org/nick/"); + + assert_string_equals("room", result->localpart); + assert_string_equals("conference.domain.org", result->domainpart); + assert_string_equals("nick/", result->resourcepart); + assert_string_equals("room@conference.domain.org", result->barejid); + assert_string_equals("room@conference.domain.org/nick/", result->fulljid); +} + void register_jid_tests(void) { TEST_MODULE("jid tests"); @@ -141,4 +185,8 @@ void register_jid_tests(void) TEST(create_jid_from_bare_returns_domainpart); TEST(create_room_jid_returns_room); TEST(create_room_jid_returns_nick); + TEST(create_with_slash_in_resource); + TEST(create_with_at_in_resource); + TEST(create_with_at_and_slash_in_resource); + TEST(create_full_with_trailing_slash); }