xeme/xeme

Add some basic jid parsing

6 months ago, Gary Kramlich
713f2c59c863
Parents 531c2c131179
Children 62de723fb97c
Add some basic jid parsing

We still need to figure out stringprep/precis, but this will work for the
moment as we decide what to do there.
--- a/xeme/meson.build Thu Dec 07 21:33:41 2023 -0600
+++ b/xeme/meson.build Thu Dec 07 21:35:02 2023 -0600
@@ -1,4 +1,5 @@
XEME_SOURCES = [
+ 'xemeaddress.c',
'xemeinputstream.c',
'xememessage.c',
'xemeoutputstream.c',
@@ -8,6 +9,7 @@
]
XEME_HEADERS = [
+ 'xemeaddress.h',
'xemecore.h',
'xemeinputstream.h',
'xememessage.h',
--- a/xeme/tests/meson.build Thu Dec 07 21:33:41 2023 -0600
+++ b/xeme/tests/meson.build Thu Dec 07 21:35:02 2023 -0600
@@ -1,4 +1,5 @@
PROGRAMS = [
+ 'address',
'inputstream',
'message',
'outputstream',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xeme/tests/testaddress.c Thu Dec 07 21:35:02 2023 -0600
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 Xeme Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include <xeme.h>
+
+/******************************************************************************
+ * Tests
+ *****************************************************************************/
+static void
+test_xeme_address_valid(void) {
+ const char *data[] = {
+ "gmail.com",
+ "gmail.com/Test",
+ "gmail.com/Test@",
+ "gmail.com/@",
+ "gmail.com/Test@alkjaweflkj",
+ "noone@example.com",
+ "noone@example.com/Test12345",
+ "noone@example.com/Test@12345",
+ "noone@example.com/Te/st@12@//345",
+ "わいど@conference.jabber.org",
+ "まりるーむ@conference.jabber.org",
+ "noone@example.com/まりるーむ",
+ "noone@example/stuff.org",
+ "noone@nödåtXäYZ.example",
+ "noone@nödåtXäYZ.example/まりるーむ",
+ "noone@わいど.org",
+ "noone@まつ.おおかみ.net",
+ "noone@310.0.42.230/s",
+ "noone@[::1]", /* IPv6 */
+ "noone@[3001:470:1f05:d58::2]",
+ "noone@[3001:470:1f05:d58::2]/foo",
+ "no=one@310.0.42.230",
+ "no,one@310.0.42.230",
+ NULL,
+ };
+
+ for(int i = 0; data[i] != NULL; i++) {
+ g_assert_true(xeme_address_parse(data[i], NULL, NULL, NULL));
+ }
+}
+
+static void
+test_xeme_address_invalid(void) {
+ const gchar *data[] = {
+ "@gmail.com",
+ "@@gmail.com",
+ "noone@@example.com/Test12345",
+ "no@one@example.com/Test12345",
+ "@example.com/Test@12345",
+ "/Test@12345",
+ "noone@",
+ "noone/",
+ "noone@gmail_stuff.org",
+ "noone@gmail[stuff.org",
+ "noone@gmail\\stuff.org",
+ "noone@[::1]124",
+ "noone@2[::1]124/as",
+ NULL,
+ };
+
+ for(int i = 0; data[i] != NULL; i++) {
+ g_assert_false(xeme_address_parse(data[i], NULL, NULL, NULL));
+ }
+}
+
+/******************************************************************************
+ * Main
+ *****************************************************************************/
+int
+main(int argc, char *argv[]) {
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/xeme/address/valid", test_xeme_address_valid);
+ g_test_add_func("/xeme/address/invalid", test_xeme_address_invalid);
+
+ return g_test_run();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xeme/xemeaddress.c Thu Dec 07 21:35:02 2023 -0600
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 Xeme Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "xemeaddress.h"
+
+#include "xemestring.h"
+
+#define XEME_ADDRESS_REGEX \
+ "^(?:(?P<local>[^\\\"&'/:<>@]+)@)?" \
+ "(?P<domain>(?:[^@/[\\\\_$]+|(\\[[0-9a-fA-F:]+\\])))" \
+ "(?:/(?P<resource>.+))?$"
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+gboolean
+xeme_address_parse(const char *address, char **local, char **domain,
+ char **resource)
+{
+ static GRegex *regexp = NULL;
+ GMatchInfo *info = NULL;
+ gchar *tmp = NULL;
+
+ g_return_val_if_fail(!xeme_str_is_empty(address), FALSE);
+
+ if(regexp == NULL) {
+ GError *error = NULL;
+
+ regexp = g_regex_new(XEME_ADDRESS_REGEX, G_REGEX_DEFAULT,
+ G_REGEX_MATCH_DEFAULT, &error);
+
+ if(error != NULL) {
+ g_critical("failed to compiled the regular expression for "
+ "addresses %s",
+ error->message != NULL ? error->message : "unknown");
+
+ g_clear_error(&error);
+ }
+ }
+
+ if(!g_regex_match(regexp, address, G_REGEX_MATCH_DEFAULT, &info)) {
+ g_clear_pointer(&info, g_match_info_free);
+
+ return FALSE;
+ }
+
+ if(local != NULL) {
+ tmp = g_match_info_fetch_named(info, "local");
+ if(xeme_str_is_empty(tmp)) {
+ g_clear_pointer(&tmp, g_free);
+ }
+
+ *local = tmp;
+ }
+
+ if(domain != NULL) {
+ tmp = g_match_info_fetch_named(info, "domain");
+ if(xeme_str_is_empty(tmp)) {
+ g_clear_pointer(&tmp, g_free);
+ }
+
+ *domain = tmp;
+ }
+
+ if(resource != NULL) {
+ tmp = g_match_info_fetch_named(info, "resource");
+ if(xeme_str_is_empty(tmp)) {
+ g_clear_pointer(&tmp, g_free);
+ }
+
+ *resource = tmp;
+ }
+
+ g_clear_pointer(&info, g_match_info_free);
+
+ return TRUE;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xeme/xemeaddress.h Thu Dec 07 21:35:02 2023 -0600
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 Xeme Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef XEME_ADDRESS_H
+#define XEME_ADDRESS_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <xeme/xemeversion.h>
+
+G_BEGIN_DECLS
+
+/**
+ * xeme_address_parse:
+ * @address: The address to parse.
+ * @local: (nullable): An optional return address for the localpart.
+ * @domain: (nullable): An optional return address for the domainpart.
+ * @resource: (nullable): An optional return address for the resourcepart.
+ *
+ * Splits @address according to the rules of
+ * [RFC 6122](https://www.rfc-editor.org/rfc/rfc6122#section-2) and returns the
+ * results into the optional @local, @domain, and @resource.
+ *
+ * Returns: %TRUE if @address was valid, otherwise %FALSE.
+ *
+ * Since: 0.1.0
+ */
+XEME_AVAILABLE_IN_0_1
+gboolean xeme_address_parse(const char *address, char **local, char **domain, char **resource);
+
+G_END_DECLS
+
+#endif /* XEME_ADDRESS_H */