libgnunetchat

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

gnunet_chat_uri.c (4305B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2022--2025 GNUnet e.V.
      4 
      5    GNUnet is free software: you can redistribute it and/or modify it
      6    under the terms of the GNU Affero General Public License as published
      7    by the Free Software Foundation, either version 3 of the License,
      8    or (at your option) any later version.
      9 
     10    GNUnet is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    Affero General Public License for more details.
     14 
     15    You should have received a copy of the GNU Affero General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18    SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 /*
     21  * @author Tobias Frisch
     22  * @file gnunet_chat_uri.c
     23  */
     24 
     25 #include "gnunet_chat_uri.h"
     26 #include <gnunet/gnunet_common.h>
     27 #include <gnunet/gnunet_fs_service.h>
     28 
     29 #define _(String) ((const char*) String)
     30 
     31 struct GNUNET_CHAT_Uri*
     32 uri_create_chat (const struct GNUNET_CRYPTO_BlindablePublicKey *zone,
     33 	               const char *label)
     34 {
     35   GNUNET_assert((zone) && (label));
     36 
     37   struct GNUNET_CHAT_Uri *uri = GNUNET_new(struct GNUNET_CHAT_Uri);
     38 
     39   uri->type = GNUNET_CHAT_URI_TYPE_CHAT;
     40 
     41   GNUNET_memcpy(&(uri->chat.zone), zone, sizeof(uri->chat.zone));
     42   uri->chat.label = GNUNET_strdup(label);
     43 
     44   return uri;
     45 }
     46 
     47 struct GNUNET_CHAT_Uri*
     48 uri_create_file (const struct GNUNET_FS_Uri *uri)
     49 {
     50   GNUNET_assert(uri);
     51 
     52   struct GNUNET_CHAT_Uri *chat_uri = GNUNET_new(struct GNUNET_CHAT_Uri);
     53 
     54   chat_uri->type = GNUNET_CHAT_URI_TYPE_FS;
     55   chat_uri->fs.uri = GNUNET_FS_uri_dup(uri);
     56 
     57   return chat_uri;
     58 }
     59 
     60 void
     61 uri_destroy (struct GNUNET_CHAT_Uri *uri)
     62 {
     63   GNUNET_assert(uri);
     64 
     65   switch (uri->type)
     66   {
     67     case GNUNET_CHAT_URI_TYPE_CHAT:
     68       if (uri->chat.label)
     69         GNUNET_free(uri->chat.label);
     70       break;
     71     case GNUNET_CHAT_URI_TYPE_FS:
     72       if (uri->fs.uri)
     73         GNUNET_FS_uri_destroy(uri->fs.uri);
     74       break;
     75     default:
     76       break;
     77   }
     78 
     79   GNUNET_free(uri);
     80 }
     81 
     82 static enum GNUNET_GenericReturnValue
     83 string_starts_with (const char *string,
     84                     const char *prefix,
     85                     size_t *prefix_len)
     86 {
     87   GNUNET_assert((string) && (prefix) && (prefix_len));
     88 
     89   *prefix_len = strlen(prefix);
     90 
     91   return (0 == strncasecmp(
     92     prefix, string, *prefix_len
     93   )? GNUNET_YES : GNUNET_NO);
     94 }
     95 
     96 struct GNUNET_CHAT_Uri*
     97 uri_parse_from_string (const char *string,
     98                        char **emsg)
     99 {
    100   GNUNET_assert(string);
    101 
    102   size_t prefix_len;
    103 
    104   if (GNUNET_YES == string_starts_with(string, GNUNET_CHAT_URI_PREFIX, &prefix_len))
    105   {
    106     struct GNUNET_CRYPTO_BlindablePublicKey zone;
    107 
    108     const char *data = string + prefix_len;
    109     char *end = strchr(data, '.');
    110 
    111     if (!end)
    112     {
    113       if (emsg)
    114         *emsg = GNUNET_strdup (_ ("CHAT URI malformed (zone key missing)"));
    115 
    116       return NULL;
    117     }
    118 
    119     char *zone_data = GNUNET_strndup(data, (size_t) (end - data));
    120 
    121     if (GNUNET_OK != GNUNET_CRYPTO_blindable_public_key_from_string(zone_data, &zone))
    122     {
    123       GNUNET_free(zone_data);
    124 
    125       if (emsg)
    126         *emsg = GNUNET_strdup (_ ("CHAT URI malformed (zone key invalid)"));
    127 
    128       return NULL;
    129     }
    130 
    131     GNUNET_free(zone_data);
    132 
    133     return uri_create_chat(&zone, end + 1);
    134   }
    135   else if (GNUNET_YES == string_starts_with(string, GNUNET_FS_URI_PREFIX, &prefix_len))
    136   {
    137     struct GNUNET_FS_Uri *fs_uri = GNUNET_FS_uri_parse(string, emsg);
    138 
    139     if (!fs_uri)
    140       return NULL;
    141 
    142     struct GNUNET_CHAT_Uri *uri = uri_create_file(fs_uri);
    143     GNUNET_FS_uri_destroy(fs_uri);
    144     return uri;
    145   }
    146   else
    147   {
    148     if (emsg)
    149       *emsg = GNUNET_strdup (_ ("CHAT URI malformed (invalid prefix)"));
    150 
    151     return NULL;
    152   }
    153 }
    154 
    155 char*
    156 uri_to_string (const struct GNUNET_CHAT_Uri *uri)
    157 {
    158   GNUNET_assert(uri);
    159 
    160   switch (uri->type)
    161   {
    162     case GNUNET_CHAT_URI_TYPE_CHAT:
    163     {
    164       char *zone = GNUNET_CRYPTO_blindable_public_key_to_string(&(uri->chat.zone));
    165       char *result;
    166 
    167       GNUNET_asprintf (
    168         &result,
    169         "%s%s.%s",
    170         GNUNET_CHAT_URI_PREFIX,
    171         zone,
    172         uri->chat.label
    173       );
    174       
    175       GNUNET_free(zone);
    176       return result;
    177     }
    178     case GNUNET_CHAT_URI_TYPE_FS:
    179       return GNUNET_FS_uri_to_string(uri->fs.uri);
    180     default:
    181       return NULL;
    182   }
    183 }