diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index ab83e2e5..4f4c6407 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -71,6 +71,7 @@ + diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index d3d87016..f3b3b822 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -172,6 +172,9 @@ Source Files + + Source Files + Source Files diff --git a/src/common/meson.build b/src/common/meson.build index 76a3c5ca..f5556fe4 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -18,6 +18,7 @@ common_sources = [ 'scram.c', 'server.c', 'servlist.c', + 'sts.c', 'text.c', 'tree.c', 'url.c', diff --git a/src/common/sts.c b/src/common/sts.c new file mode 100644 index 00000000..d529945d --- /dev/null +++ b/src/common/sts.c @@ -0,0 +1,152 @@ +/* ZoiteChat + * Copyright (C) 2024 + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "sts.h" + +static gboolean +sts_parse_bool (const char *value) +{ + if (!value || !*value) + { + return FALSE; + } + + return g_ascii_strcasecmp (value, "1") == 0 || + g_ascii_strcasecmp (value, "true") == 0 || + g_ascii_strcasecmp (value, "yes") == 0; +} + +sts_profile * +sts_profile_new (const char *host, guint16 port, time_t expires_at, gboolean preload) +{ + sts_profile *profile = g_new0 (sts_profile, 1); + + profile->host = g_strdup (host); + profile->port = port; + profile->expires_at = expires_at; + profile->preload = preload; + + return profile; +} + +void +sts_profile_free (sts_profile *profile) +{ + if (!profile) + { + return; + } + + g_free (profile->host); + g_free (profile); +} + +char * +sts_profile_serialize (const sts_profile *profile) +{ + GString *serialized; + char *escaped_host; + char *result; + + if (!profile || !profile->host || !*profile->host) + { + return NULL; + } + + escaped_host = g_strdup (profile->host); + serialized = g_string_new (escaped_host); + g_free (escaped_host); + + g_string_append_printf (serialized, " %u %" G_GINT64_FORMAT, + profile->port, (gint64) profile->expires_at); + + if (profile->preload) + { + g_string_append (serialized, " 1"); + } + + result = g_string_free (serialized, FALSE); + return result; +} + +sts_profile * +sts_profile_deserialize (const char *serialized) +{ + char *host = NULL; + guint16 port = 0; + gint64 expires_at = -1; + gboolean preload = FALSE; + gchar **pairs = NULL; + int i = 0; + + if (!serialized || !*serialized) + { + return NULL; + } + + pairs = g_strsplit_set (serialized, " \t", -1); + { + const char *fields[4] = {0}; + int field_count = 0; + + for (i = 0; pairs[i]; i++) + { + if (!pairs[i][0]) + { + continue; + } + + if (field_count < 4) + { + fields[field_count++] = pairs[i]; + } + } + + if (field_count >= 3) + { + host = g_strdup (fields[0]); + + gint64 port_value = g_ascii_strtoll (fields[1], NULL, 10); + if (port_value > 0 && port_value <= G_MAXUINT16) + { + port = (guint16) port_value; + } + + expires_at = g_ascii_strtoll (fields[2], NULL, 10); + + if (field_count >= 4) + { + preload = sts_parse_bool (fields[3]); + } + } + } + + if (!host || !*host || expires_at < 0) + { + g_free (host); + g_strfreev (pairs); + return NULL; + } + + sts_profile *profile = sts_profile_new (host, port, (time_t) expires_at, preload); + g_free (host); + g_strfreev (pairs); + return profile; +} diff --git a/src/common/sts.h b/src/common/sts.h new file mode 100644 index 00000000..2e60bae3 --- /dev/null +++ b/src/common/sts.h @@ -0,0 +1,43 @@ +/* ZoiteChat + * Copyright (C) 2024 + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef HEXCHAT_STS_H +#define HEXCHAT_STS_H + +#include +#include + +G_BEGIN_DECLS + +typedef struct sts_profile +{ + char *host; + guint16 port; + time_t expires_at; + gboolean preload; +} sts_profile; + +sts_profile *sts_profile_new (const char *host, guint16 port, time_t expires_at, gboolean preload); +void sts_profile_free (sts_profile *profile); + +char *sts_profile_serialize (const sts_profile *profile); +sts_profile *sts_profile_deserialize (const char *serialized); + +G_END_DECLS + +#endif