From c2426e88c9583fab1d58d7d26e3bbe9d500ea570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Wed, 23 Aug 2023 16:48:09 +0200 Subject: [PATCH] irc: add functions to convert strings to lower/upper case (following casemapping) (issue #194) --- src/plugins/irc/irc-server.c | 66 ++++++++++++++++++++++ src/plugins/irc/irc-server.h | 4 ++ tests/unit/plugins/irc/test-irc-server.cpp | 58 +++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index 2cd37d1ff..1c4106796 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -333,6 +333,72 @@ irc_server_strncasecmp (struct t_irc_server *server, return weechat_strncasecmp_range (string1, string2, max, range); } +/* + * Converts string to lower case, following server casemapping. + * + * Note: result must be freed after use. + */ + +char * +irc_server_string_tolower (struct t_irc_server *server, const char *string) +{ + char *result, *ptr_result; + int casemapping, range; + + if (!string) + return NULL; + + casemapping = (server) ? server->casemapping : -1; + if ((casemapping < 0) || (casemapping >= IRC_SERVER_NUM_CASEMAPPING)) + casemapping = IRC_SERVER_CASEMAPPING_RFC1459; + + range = irc_server_casemapping_range[casemapping]; + + result = strdup (string); + ptr_result = result; + while (ptr_result && ptr_result[0]) + { + if ((ptr_result[0] >= 'A') && (ptr_result[0] < 'A' + range)) + ptr_result[0] += ('a' - 'A'); + ptr_result = (char *)weechat_utf8_next_char (ptr_result); + } + + return result; +} + +/* + * Converts string to upper case, following server casemapping. + * + * Note: result must be freed after use. + */ + +char * +irc_server_string_toupper (struct t_irc_server *server, const char *string) +{ + char *result, *ptr_result; + int casemapping, range; + + if (!string) + return NULL; + + casemapping = (server) ? server->casemapping : -1; + if ((casemapping < 0) || (casemapping >= IRC_SERVER_NUM_CASEMAPPING)) + casemapping = IRC_SERVER_CASEMAPPING_RFC1459; + + range = irc_server_casemapping_range[casemapping]; + + result = strdup (string); + ptr_result = result; + while (ptr_result && ptr_result[0]) + { + if ((ptr_result[0] >= 'a') && (ptr_result[0] < 'a' + range)) + ptr_result[0] -= ('a' - 'A'); + ptr_result = (char *)weechat_utf8_next_char (ptr_result); + } + + return result; +} + /* * Evaluates a string using the server as context: * ${irc_server.xxx} and ${server} are replaced by a server option and the diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index d34cb31d0..4ae647ed2 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -348,6 +348,10 @@ extern int irc_server_strcasecmp (struct t_irc_server *server, extern int irc_server_strncasecmp (struct t_irc_server *server, const char *string1, const char *string2, int max); +extern char *irc_server_string_tolower (struct t_irc_server *server, + const char *string); +extern char *irc_server_string_toupper (struct t_irc_server *server, + const char *string); extern char *irc_server_eval_expression (struct t_irc_server *server, const char *string); extern void irc_server_sasl_get_creds (struct t_irc_server *server, diff --git a/tests/unit/plugins/irc/test-irc-server.cpp b/tests/unit/plugins/irc/test-irc-server.cpp index 1e22fc1c4..037f14a22 100644 --- a/tests/unit/plugins/irc/test-irc-server.cpp +++ b/tests/unit/plugins/irc/test-irc-server.cpp @@ -213,6 +213,64 @@ TEST(IrcServer, Strcasecmp) irc_server_free (server); } +/* + * Tests functions: + * irc_server_string_tolower + * irc_server_string_toupper + */ + +TEST(IrcServer, StringToLowerUpper) +{ + struct t_irc_server *server; + char *str; + + server = irc_server_alloc ("server1"); + CHECK(server); + + POINTERS_EQUAL(NULL, irc_server_string_tolower (NULL, NULL)); + POINTERS_EQUAL(NULL, irc_server_string_toupper (NULL, NULL)); + + WEE_TEST_STR("", irc_server_string_tolower (NULL, "")); + WEE_TEST_STR("", irc_server_string_toupper (NULL, "")); + + WEE_TEST_STR("abcdÉ", irc_server_string_tolower (NULL, "ABCDÉ")); + WEE_TEST_STR("ABCDé", irc_server_string_toupper (NULL, "abcdé")); + + WEE_TEST_STR("nick{a}", irc_server_string_tolower (NULL, "NICK[A]")); + WEE_TEST_STR("NICK[A]", irc_server_string_toupper (NULL, "nick{a}")); + WEE_TEST_STR("nick~a", irc_server_string_tolower (NULL, "NICK^A")); + WEE_TEST_STR("NICK^A", irc_server_string_toupper (NULL, "nick~a")); + WEE_TEST_STR("nick_Ô", irc_server_string_tolower (NULL, "NICK_Ô")); + WEE_TEST_STR("NICK_ô", irc_server_string_toupper (NULL, "nick_ô")); + + WEE_TEST_STR("nick{a}", irc_server_string_tolower (server, "NICK[A]")); + WEE_TEST_STR("NICK[A]", irc_server_string_toupper (server, "nick{a}")); + WEE_TEST_STR("nick~a", irc_server_string_tolower (server, "NICK^A")); + WEE_TEST_STR("NICK^A", irc_server_string_toupper (server, "nick~a")); + WEE_TEST_STR("nick_Ô", irc_server_string_tolower (server, "NICK_Ô")); + WEE_TEST_STR("NICK_ô", irc_server_string_toupper (server, "nick_ô")); + + server->casemapping = IRC_SERVER_CASEMAPPING_STRICT_RFC1459; + + WEE_TEST_STR("nick{a}", irc_server_string_tolower (server, "NICK[A]")); + WEE_TEST_STR("NICK[A]", irc_server_string_toupper (server, "nick{a}")); + WEE_TEST_STR("nick^a", irc_server_string_tolower (server, "NICK^A")); + WEE_TEST_STR("NICK~A", irc_server_string_toupper (server, "nick~a")); + WEE_TEST_STR("nick_Ô", irc_server_string_tolower (server, "NICK_Ô")); + WEE_TEST_STR("NICK_ô", irc_server_string_toupper (server, "nick_ô")); + + server->casemapping = IRC_SERVER_CASEMAPPING_ASCII; + + WEE_TEST_STR("nick[a]", irc_server_string_tolower (server, "NICK[A]")); + WEE_TEST_STR("NICK{A}", irc_server_string_toupper (server, "nick{a}")); + WEE_TEST_STR("nick^a", irc_server_string_tolower (server, "NICK^A")); + WEE_TEST_STR("NICK~A", irc_server_string_toupper (server, "nick~a")); + WEE_TEST_STR("nick_Ô", irc_server_string_tolower (server, "NICK_Ô")); + WEE_TEST_STR("NICK_ô", irc_server_string_toupper (server, "nick_ô")); + + irc_server_free (server); +} + /* * Tests functions: * irc_server_eval_expression