libgnunetchat

library for GNUnet Messenger
Log | Files | Refs | README | LICENSE

commit 4d3a143438e87fb7ec5a6f2e35455270360db6cc
parent b98c7a5f62717b666d9bdaee812d2baf25d63d55
Author: Jacki <jacki@thejackimonster.de>
Date:   Wed, 17 Apr 2024 17:56:08 +0200

Support FS uri parsing

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Minclude/gnunet/gnunet_chat_lib.h | 2+-
Msrc/gnunet_chat_lib.c | 64++++++++++------------------------------------------------------
Msrc/gnunet_chat_lib_intern.c | 5+++--
Msrc/gnunet_chat_lobby_intern.c | 4++--
Msrc/gnunet_chat_uri.c | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/gnunet_chat_uri.h | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
6 files changed, 214 insertions(+), 69 deletions(-)

diff --git a/include/gnunet/gnunet_chat_lib.h b/include/gnunet/gnunet_chat_lib.h @@ -598,7 +598,7 @@ GNUNET_CHAT_get_shared_attributes (struct GNUNET_CHAT_Handle *handle, * * @param[in] uri UTF-8 string to parse * @param[out] emsg Where to store the parser error message (if any) - * @return NULL on error + * @return URI on success, NULL on error */ struct GNUNET_CHAT_Uri* GNUNET_CHAT_uri_parse (const char *uri, diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c @@ -626,44 +626,7 @@ GNUNET_CHAT_uri_parse (const char *uri, if (!uri) return NULL; - const size_t prefix_len = strlen(GNUNET_CHAT_URI_PREFIX); - - if (0 != strncasecmp(GNUNET_CHAT_URI_PREFIX, uri, prefix_len)) - { - if (emsg) - *emsg = GNUNET_strdup (_ ("CHAT URI malformed (invalid prefix)")); - - return NULL; - } - - struct GNUNET_CRYPTO_PublicKey zone; - - const char *data = uri + prefix_len; - char *end = strchr(data, '.'); - - if (!end) - { - if (emsg) - *emsg = GNUNET_strdup (_ ("CHAT URI malformed (zone key missing)")); - - return NULL; - } - - char *zone_data = GNUNET_strndup(data, (size_t) (end - data)); - - if (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string(zone_data, &zone)) - { - GNUNET_free(zone_data); - - if (emsg) - *emsg = GNUNET_strdup (_ ("CHAT URI malformed (zone key invalid)")); - - return NULL; - } - - GNUNET_free(zone_data); - - return uri_create(&zone, end + 1); + return uri_parse_from_string(uri, emsg); } @@ -675,18 +638,7 @@ GNUNET_CHAT_uri_to_string (const struct GNUNET_CHAT_Uri *uri) if (!uri) return NULL; - char *key_string = GNUNET_CRYPTO_public_key_to_string(&(uri->zone)); - - char *string; - GNUNET_asprintf ( - &string, - "gnunet://chat/%s.%s", - key_string, - uri->label - ); - - GNUNET_free(key_string); - return string; + return uri_to_string(uri); } @@ -768,7 +720,8 @@ GNUNET_CHAT_lobby_join (struct GNUNET_CHAT_Handle *handle, { GNUNET_CHAT_VERSION_ASSERT(); - if ((!handle) || (handle->destruction) || (!uri) || (!(handle->gns))) + if ((!handle) || (handle->destruction) || (!(handle->gns)) || + (!uri) || (GNUNET_CHAT_URI_TYPE_CHAT != uri->type)) return; struct GNUNET_CHAT_UriLookups *lookups = GNUNET_new( @@ -776,12 +729,15 @@ GNUNET_CHAT_lobby_join (struct GNUNET_CHAT_Handle *handle, ); lookups->handle = handle; - lookups->uri = uri_create(&(uri->zone), uri->label); + lookups->uri = uri_create_chat( + &(uri->chat.zone), + uri->chat.label + ); lookups->request = GNUNET_GNS_lookup( handle->gns, - lookups->uri->label, - &(uri->zone), + lookups->uri->chat.label, + &(uri->chat.zone), GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY, GNUNET_GNS_LO_DEFAULT, cb_lobby_lookup, diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c @@ -97,12 +97,13 @@ cb_lobby_lookup (void *cls, struct GNUNET_CHAT_UriLookups *lookups = (struct GNUNET_CHAT_UriLookups*) cls; - if ((!(lookups->handle)) || (!(lookups->uri))) + if ((!(lookups->handle)) || (!(lookups->uri)) || + (GNUNET_CHAT_URI_TYPE_CHAT != lookups->uri->type)) goto drop_lookup; struct GNUNET_CHAT_Context *context = handle_process_records( lookups->handle, - lookups->uri->label, + lookups->uri->chat.label, count, data ); diff --git a/src/gnunet_chat_lobby_intern.c b/src/gnunet_chat_lobby_intern.c @@ -115,13 +115,13 @@ cont_lobby_identity_create (void *cls, char *label; util_get_context_label(lobby->context->type, key, &label); - lobby->uri = uri_create(&public_zone, label); + lobby->uri = uri_create_chat(&public_zone, label); GNUNET_free(label); lobby->query = GNUNET_NAMESTORE_record_set_store( lobby->handle->namestore, zone, - lobby->uri->label, + lobby->uri->chat.label, 1, data, cont_lobby_write_records, diff --git a/src/gnunet_chat_uri.c b/src/gnunet_chat_uri.c @@ -23,29 +23,161 @@ */ #include "gnunet_chat_uri.h" +#include <gnunet/gnunet_common.h> +#include <gnunet/gnunet_fs_service.h> + +#define _(String) ((const char*) String) struct GNUNET_CHAT_Uri* -uri_create (const struct GNUNET_CRYPTO_PublicKey *zone, - const char *label) +uri_create_chat (const struct GNUNET_CRYPTO_PublicKey *zone, + const char *label) { GNUNET_assert((zone) && (label)); struct GNUNET_CHAT_Uri *uri = GNUNET_new(struct GNUNET_CHAT_Uri); - GNUNET_memcpy(&(uri->zone), zone, sizeof(uri->zone)); + uri->type = GNUNET_CHAT_URI_TYPE_CHAT; - uri->label = GNUNET_strdup(label); + GNUNET_memcpy(&(uri->chat.zone), zone, sizeof(uri->chat.zone)); + uri->chat.label = GNUNET_strdup(label); return uri; } +struct GNUNET_CHAT_Uri* +uri_create_file (const struct GNUNET_FS_Uri *uri) +{ + GNUNET_assert(uri); + + struct GNUNET_CHAT_Uri *chat_uri = GNUNET_new(struct GNUNET_CHAT_Uri); + + chat_uri->type = GNUNET_CHAT_URI_TYPE_FS; + chat_uri->fs.uri = GNUNET_FS_uri_dup(uri); + + return chat_uri; +} + void uri_destroy (struct GNUNET_CHAT_Uri *uri) { GNUNET_assert(uri); - if (uri->label) - GNUNET_free(uri->label); + switch (uri->type) + { + case GNUNET_CHAT_URI_TYPE_CHAT: + if (uri->chat.label) + GNUNET_free(uri->chat.label); + break; + case GNUNET_CHAT_URI_TYPE_FS: + if (uri->fs.uri) + GNUNET_FS_uri_destroy(uri->fs.uri); + break; + default: + break; + } GNUNET_free(uri); } + +static enum GNUNET_GenericReturnValue +string_starts_with (const char *string, + const char *prefix, + size_t *prefix_len) +{ + GNUNET_assert((string) && (prefix) && (prefix_len)); + + *prefix_len = strlen(prefix); + + return (0 == strncasecmp( + prefix, string, *prefix_len + )? GNUNET_YES : GNUNET_NO); +} + +struct GNUNET_CHAT_Uri* +uri_parse_from_string (const char *string, + char **emsg) +{ + GNUNET_assert(string); + + size_t prefix_len; + + if (GNUNET_YES == string_starts_with(string, GNUNET_CHAT_URI_PREFIX, &prefix_len)) + { + struct GNUNET_CRYPTO_PublicKey zone; + + const char *data = string + prefix_len; + char *end = strchr(data, '.'); + + if (!end) + { + if (emsg) + *emsg = GNUNET_strdup (_ ("CHAT URI malformed (zone key missing)")); + + return NULL; + } + + char *zone_data = GNUNET_strndup(data, (size_t) (end - data)); + + if (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string(zone_data, &zone)) + { + GNUNET_free(zone_data); + + if (emsg) + *emsg = GNUNET_strdup (_ ("CHAT URI malformed (zone key invalid)")); + + return NULL; + } + + GNUNET_free(zone_data); + + return uri_create_chat(&zone, end + 1); + } + else if (GNUNET_YES == string_starts_with(string, GNUNET_FS_URI_PREFIX, &prefix_len)) + { + struct GNUNET_FS_Uri *fs_uri = GNUNET_FS_uri_parse(string, emsg); + + if (!fs_uri) + return NULL; + + struct GNUNET_CHAT_Uri *uri = uri_create_file(fs_uri); + GNUNET_FS_uri_destroy(fs_uri); + return uri; + } + else + { + if (emsg) + *emsg = GNUNET_strdup (_ ("CHAT URI malformed (invalid prefix)")); + + return NULL; + } +} + +char* +uri_to_string (const struct GNUNET_CHAT_Uri *uri) +{ + GNUNET_assert(uri); + + switch (uri->type) + { + case GNUNET_CHAT_URI_TYPE_CHAT: + { + char *tmp = GNUNET_CRYPTO_public_key_to_string(&(uri->chat.zone)); + char *result; + + GNUNET_asprintf ( + &result, + "%s%s.%s", + GNUNET_CHAT_URI_PREFIX, + tmp, + uri->chat.label + ); + + GNUNET_free(tmp); + return result; + } + case GNUNET_CHAT_URI_TYPE_FS: + return GNUNET_FS_uri_to_string(uri->fs.uri); + default: + return NULL; + } +} diff --git a/src/gnunet_chat_uri.h b/src/gnunet_chat_uri.h @@ -25,27 +25,61 @@ #ifndef GNUNET_CHAT_URI_H_ #define GNUNET_CHAT_URI_H_ +#include <gnunet/gnunet_fs_service.h> #include <gnunet/gnunet_util_lib.h> #include "gnunet_chat_util.h" -struct GNUNET_CHAT_Uri +enum GNUNET_CHAT_UriType +{ + GNUNET_CHAT_URI_TYPE_CHAT = 1, + GNUNET_CHAT_URI_TYPE_FS = 2, + + GNUNET_CHAT_URI_TYPE_UNKNOWN = 0 +}; + +struct GNUNET_CHAT_UriChat { struct GNUNET_CRYPTO_PublicKey zone; char *label; }; +struct GNUNET_CHAT_UriFile +{ + struct GNUNET_FS_Uri *uri; +}; + +struct GNUNET_CHAT_Uri +{ + enum GNUNET_CHAT_UriType type; + + union { + struct GNUNET_CHAT_UriChat chat; + struct GNUNET_CHAT_UriFile fs; + }; +}; + /** * Creates a chat uri with a selected key as <i>zone</i> - * and a <i>label</i>. + * and a <i>label</i> of type #GNUNET_CHAT_URI_TYPE_CHAT. * * @param[in] zone URI zone * @param[in] label URI label * @return New chat uri */ struct GNUNET_CHAT_Uri* -uri_create (const struct GNUNET_CRYPTO_PublicKey *zone, - const char *label); +uri_create_chat (const struct GNUNET_CRYPTO_PublicKey *zone, + const char *label); + +/** + * Creates a chat uri from a selected FS <i>uri</i> + * setting the type to #GNUNET_CHAT_URI_TYPE_FS. + * + * @param[in] uri FS URI + * @return New chat uri + */ +struct GNUNET_CHAT_Uri* +uri_create_file (const struct GNUNET_FS_Uri *uri); /** * Destroys a chat <i>uri</i> and frees its memory. @@ -55,4 +89,26 @@ uri_create (const struct GNUNET_CRYPTO_PublicKey *zone, void uri_destroy (struct GNUNET_CHAT_Uri *uri); +/** + * Parses an UTF-8 string to a chat URI which will + * be newly allocated. + * + * @param[in] string UTF-8 string to parse + * @param[out] emsg Where to store the parser error message (if any) + * @return URI on success, NULL on error + */ +struct GNUNET_CHAT_Uri* +uri_parse_from_string (const char *string, + char **emsg); + +/** + * Returns an allocated UTF-8 string representing + * a given chat <i>uri</i>. + * + * @param[in] uri Chat uri + * @return The UTF-8 string representing the URI + */ +char* +uri_to_string (const struct GNUNET_CHAT_Uri *uri); + #endif /* GNUNET_CHAT_URI_H_ */