From 94bcf1889d5a07305784ff5bc92afffa71a5ccd3 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sat, 12 Jan 2013 23:10:56 +0000 Subject: [PATCH] Added jid datatype --- Makefile.am | 5 +- src/common.c | 100 ----------------------- src/common.h | 8 -- src/jabber.c | 1 + src/jid.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++ src/jid.h | 48 +++++++++++ src/muc.h | 4 +- src/windows.c | 1 + tests/test_jid.c | 128 +++++++++++++++++++++++++++++ tests/testsuite.c | 1 + tests/testsuite.h | 1 + 11 files changed, 384 insertions(+), 112 deletions(-) create mode 100644 src/jid.c create mode 100644 src/jid.h create mode 100644 tests/test_jid.c diff --git a/Makefile.am b/Makefile.am index 14d0cf33..2a0e1e37 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,14 +10,15 @@ profanity_SOURCES = src/command.c src/contact.c src/history.c src/jabber.h \ src/chat_session.h src/release.c src/release.h src/muc.c \ src/muc.h src/stanza.c src/stanza.h src/parser.c src/parser.h \ src/theme.c src/theme.h src/window.c src/window.h src/xdg_base.c \ - src/xdg_base.h src/files.c src/files.h src/accounts.c src/accounts.h + src/xdg_base.h src/files.c src/files.h src/accounts.c src/accounts.h \ + src/jid.h src/jid.c TESTS = tests/testsuite check_PROGRAMS = tests/testsuite tests_testsuite_SOURCES = tests/test_contact_list.c src/contact_list.c src/contact.c \ tests/test_common.c tests/test_prof_history.c src/prof_history.c src/common.c \ tests/test_prof_autocomplete.c src/prof_autocomplete.c tests/testsuite.c \ - tests/test_parser.c src/parser.c + tests/test_parser.c src/parser.c tests/test_jid.c src/jid.c tests_testsuite_LDADD = -lheadunit -lstdc++ man_MANS = docs/profanity.1 diff --git a/src/common.c b/src/common.c index 4bb4cc4d..d79bff64 100644 --- a/src/common.c +++ b/src/common.c @@ -167,103 +167,3 @@ prof_getline(FILE *stream) free(buf); return s; } - -/* - * Given a full room JID of the form - * room@server/nick - * Will create two new strings and point room and nick to them e.g. - * *room = "room@server", *nick = "nick" - * The strings must be freed by the caller - * Returns TRUE if the JID was parsed successfully, FALSE otherwise - */ -gboolean -parse_room_jid(const char * const full_room_jid, char **room, char **nick) -{ - char **tokens = g_strsplit(full_room_jid, "/", 0); - - if (tokens == NULL || tokens[0] == NULL || tokens[1] == NULL) { - return FALSE; - } else { - *room = strdup(tokens[0]); - *nick = strdup(tokens[1]); - - g_strfreev(tokens); - - return TRUE; - } -} - -/* - * Given a room name, and a nick name create and return a full JID of the form - * room@server/nick - * Will return a newly created string that must be freed by the caller - */ -char * -create_full_room_jid(const char * const room, const char * const nick) -{ - GString *full_jid = g_string_new(room); - g_string_append(full_jid, "/"); - g_string_append(full_jid, nick); - - char *result = strdup(full_jid->str); - - g_string_free(full_jid, TRUE); - - return result; -} - -/* - * Returns TRUE if the JID is a room JID - * The test is that the passed JID does not contain a "/" - */ -gboolean -jid_is_room(const char * const room_jid) -{ - gchar *result = g_strrstr(room_jid, "/"); - return (result == NULL); -} - -/* - * Get the room name part of the full JID, e.g. - * Full JID = "test@conference.server/person" - * returns "test@conference.server" - */ -char * -get_room_from_full_jid(const char * const full_room_jid) -{ - char **tokens = g_strsplit(full_room_jid, "/", 0); - char *room_part; - - if (tokens == NULL || tokens[0] == NULL) { - return NULL; - } else { - room_part = strdup(tokens[0]); - - g_strfreev(tokens); - - return room_part; - } -} - -/* - * Get the nickname part of the full JID, e.g. - * Full JID = "test@conference.server/person" - * returns "person" - */ -char * -get_nick_from_full_jid(const char * const full_room_jid) -{ - char **tokens = g_strsplit(full_room_jid, "/", 0); - char *nick_part; - - if (tokens == NULL || tokens[1] == NULL) { - return NULL; - } else { - nick_part = strdup(tokens[1]); - - g_strfreev(tokens); - - return nick_part; - } -} - diff --git a/src/common.h b/src/common.h index 5974b517..72623f0c 100644 --- a/src/common.h +++ b/src/common.h @@ -44,12 +44,4 @@ int str_contains(char str[], int size, char ch); char* encode_xml(const char * const xml); char * prof_getline(FILE *stream); -gboolean jid_is_room(const char * const room_jid); -char * create_full_room_jid(const char * const room, - const char * const nick); -char * get_room_from_full_jid(const char * const full_room_jid); -char * get_nick_from_full_jid(const char * const full_room_jid); -gboolean parse_room_jid(const char * const full_room_jid, char **room, - char **nick); - #endif diff --git a/src/jabber.c b/src/jabber.c index 8b60a837..15410c01 100644 --- a/src/jabber.c +++ b/src/jabber.c @@ -30,6 +30,7 @@ #include "common.h" #include "contact_list.h" #include "jabber.h" +#include "jid.h" #include "log.h" #include "preferences.h" #include "profanity.h" diff --git a/src/jid.c b/src/jid.c new file mode 100644 index 00000000..839cbe68 --- /dev/null +++ b/src/jid.c @@ -0,0 +1,199 @@ +/* + * jid.c + * + * Copyright (C) 2012, 2013 James Booth + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see . + * + */ + +#include + +#include + +#include "jid.h" + +Jid +jid_create(const gchar * const str) +{ + Jid result = NULL; + + if (str == NULL) { + return NULL; + } + if (strlen(str) == 0) { + return NULL; + } + + gchar *trimmed = g_strdup(str); + + 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); + return NULL; + } + + gchar *slashp = g_strrstr(trimmed, "/"); + + // has resourcepart + if (slashp != NULL) { + result = malloc(sizeof(struct jid_t)); + 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_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->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; + } +} + +/* + * Given a full room JID of the form + * room@server/nick + * Will create two new strings and point room and nick to them e.g. + * *room = "room@server", *nick = "nick" + * The strings must be freed by the caller + * Returns TRUE if the JID was parsed successfully, FALSE otherwise + */ +gboolean +parse_room_jid(const char * const full_room_jid, char **room, char **nick) +{ + char **tokens = g_strsplit(full_room_jid, "/", 0); + + if (tokens == NULL || tokens[0] == NULL || tokens[1] == NULL) { + return FALSE; + } else { + *room = strdup(tokens[0]); + *nick = strdup(tokens[1]); + + g_strfreev(tokens); + + return TRUE; + } +} + +/* + * Given a room name, and a nick name create and return a full JID of the form + * room@server/nick + * Will return a newly created string that must be freed by the caller + */ +char * +create_full_room_jid(const char * const room, const char * const nick) +{ + GString *full_jid = g_string_new(room); + g_string_append(full_jid, "/"); + g_string_append(full_jid, nick); + + char *result = strdup(full_jid->str); + + g_string_free(full_jid, TRUE); + + return result; +} + +/* + * Returns TRUE if the JID is a room JID + * The test is that the passed JID does not contain a "/" + */ +gboolean +jid_is_room(const char * const room_jid) +{ + gchar *result = g_strrstr(room_jid, "/"); + return (result == NULL); +} + +/* + * Get the room name part of the full JID, e.g. + * Full JID = "test@conference.server/person" + * returns "test@conference.server" + */ +char * +get_room_from_full_jid(const char * const full_room_jid) +{ + char **tokens = g_strsplit(full_room_jid, "/", 0); + char *room_part; + + if (tokens == NULL || tokens[0] == NULL) { + return NULL; + } else { + room_part = strdup(tokens[0]); + + g_strfreev(tokens); + + return room_part; + } +} + +/* + * Get the nickname part of the full JID, e.g. + * Full JID = "test@conference.server/person" + * returns "person" + */ +char * +get_nick_from_full_jid(const char * const full_room_jid) +{ + char **tokens = g_strsplit(full_room_jid, "/", 0); + char *nick_part; + + if (tokens == NULL || tokens[1] == NULL) { + return NULL; + } else { + nick_part = strdup(tokens[1]); + + g_strfreev(tokens); + + return nick_part; + } +} + diff --git a/src/jid.h b/src/jid.h new file mode 100644 index 00000000..608d7ef4 --- /dev/null +++ b/src/jid.h @@ -0,0 +1,48 @@ +/* + * jid.h + * + * Copyright (C) 2012, 2013 James Booth + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see . + * + */ + +#ifndef JID_H +#define JID_H + +#include + +struct jid_t { + char *localpart; + char *domainpart; + char *resourcepart; + char *barejid; + char *fulljid; +}; + +typedef struct jid_t *Jid; + +Jid jid_create(const gchar * const str); + +gboolean jid_is_room(const char * const room_jid); +char * create_full_room_jid(const char * const room, + const char * const nick); +char * get_room_from_full_jid(const char * const full_room_jid); +char * get_nick_from_full_jid(const char * const full_room_jid); +gboolean parse_room_jid(const char * const full_room_jid, char **room, + char **nick); + +#endif diff --git a/src/muc.h b/src/muc.h index a27b8432..0cabd9b8 100644 --- a/src/muc.h +++ b/src/muc.h @@ -20,8 +20,8 @@ * */ -#ifndef ROOM_CHAT_H -#define ROOM_CHAT_H +#ifndef MUC_H +#define MUC_H #include diff --git a/src/windows.c b/src/windows.c index 7015017d..cd16aeb7 100644 --- a/src/windows.c +++ b/src/windows.c @@ -50,6 +50,7 @@ #include "common.h" #include "contact.h" #include "contact_list.h" +#include "jid.h" #include "log.h" #include "preferences.h" #include "release.h" diff --git a/tests/test_jid.c b/tests/test_jid.c new file mode 100644 index 00000000..0b56b09d --- /dev/null +++ b/tests/test_jid.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include "jid.h" + +void create_jid_from_null_returns_null(void) +{ + Jid result = jid_create(NULL); + assert_is_null(result); +} + +void create_jid_from_empty_string_returns_null(void) +{ + Jid result = jid_create(""); + assert_is_null(result); +} + +void create_jid_from_full_returns_full(void) +{ + Jid result = jid_create("myuser@mydomain/laptop"); + assert_string_equals("myuser@mydomain/laptop", result->fulljid); +} + +void create_jid_from_full_returns_bare(void) +{ + Jid result = jid_create("myuser@mydomain/laptop"); + assert_string_equals("myuser@mydomain", result->barejid); +} + +void create_jid_from_full_returns_resourcepart(void) +{ + Jid result = jid_create("myuser@mydomain/laptop"); + assert_string_equals("laptop", result->resourcepart); +} + +void create_jid_from_full_returns_localpart(void) +{ + Jid result = jid_create("myuser@mydomain/laptop"); + assert_string_equals("myuser", result->localpart); +} + +void create_jid_from_full_returns_domainpart(void) +{ + Jid result = jid_create("myuser@mydomain/laptop"); + assert_string_equals("mydomain", result->domainpart); +} + +void create_jid_from_full_nolocal_returns_full(void) +{ + Jid result = jid_create("mydomain/laptop"); + assert_string_equals("mydomain/laptop", result->fulljid); +} + +void create_jid_from_full_nolocal_returns_bare(void) +{ + Jid result = jid_create("mydomain/laptop"); + assert_string_equals("mydomain", result->barejid); +} + +void create_jid_from_full_nolocal_returns_resourcepart(void) +{ + Jid result = jid_create("mydomain/laptop"); + assert_string_equals("laptop", result->resourcepart); +} + +void create_jid_from_full_nolocal_returns_domainpart(void) +{ + Jid result = jid_create("mydomain/laptop"); + assert_string_equals("mydomain", result->domainpart); +} + +void create_jid_from_full_nolocal_returns_null_localpart(void) +{ + Jid result = jid_create("mydomain/laptop"); + assert_is_null(result->localpart); +} + +void create_jid_from_bare_returns_null_full(void) +{ + Jid result = jid_create("myuser@mydomain"); + assert_is_null(result->fulljid); +} + +void create_jid_from_bare_returns_null_resource(void) +{ + Jid result = jid_create("myuser@mydomain"); + assert_is_null(result->resourcepart); +} + +void create_jid_from_bare_returns_bare(void) +{ + Jid result = jid_create("myuser@mydomain"); + assert_string_equals("myuser@mydomain", result->barejid); +} + +void create_jid_from_bare_returns_localpart(void) +{ + Jid result = jid_create("myuser@mydomain"); + assert_string_equals("myuser", result->localpart); +} + +void create_jid_from_bare_returns_domainpart(void) +{ + Jid result = jid_create("myuser@mydomain"); + assert_string_equals("mydomain", result->domainpart); +} + +void register_jid_tests(void) +{ + TEST_MODULE("jid tests"); + TEST(create_jid_from_null_returns_null); + TEST(create_jid_from_empty_string_returns_null); + TEST(create_jid_from_full_returns_full); + TEST(create_jid_from_full_returns_bare); + TEST(create_jid_from_full_returns_resourcepart); + TEST(create_jid_from_full_returns_localpart); + TEST(create_jid_from_full_returns_domainpart); + TEST(create_jid_from_full_nolocal_returns_full); + TEST(create_jid_from_full_nolocal_returns_bare); + TEST(create_jid_from_full_nolocal_returns_resourcepart); + TEST(create_jid_from_full_nolocal_returns_domainpart); + TEST(create_jid_from_full_nolocal_returns_null_localpart); + TEST(create_jid_from_bare_returns_null_full); + TEST(create_jid_from_bare_returns_null_resource); + TEST(create_jid_from_bare_returns_bare); + TEST(create_jid_from_bare_returns_localpart); + TEST(create_jid_from_bare_returns_domainpart); +} diff --git a/tests/testsuite.c b/tests/testsuite.c index 7c1b81dc..bbaa06d6 100644 --- a/tests/testsuite.c +++ b/tests/testsuite.c @@ -8,6 +8,7 @@ int main(void) register_common_tests(); register_prof_autocomplete_tests(); register_parser_tests(); + register_jid_tests(); run_suite(); return 0; } diff --git a/tests/testsuite.h b/tests/testsuite.h index 029cd48c..96d601dc 100644 --- a/tests/testsuite.h +++ b/tests/testsuite.h @@ -6,5 +6,6 @@ void register_contact_list_tests(void); void register_common_tests(void); void register_prof_autocomplete_tests(void); void register_parser_tests(void); +void register_jid_tests(void); #endif