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 }