GNUnet 0.21.0
fs_uri.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2003--2014 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
83#include "platform.h"
84
85#include "gnunet_fs_service.h"
86#include "gnunet_signatures.h"
87#include "fs_api.h"
88#include <unitypes.h>
89#include <unicase.h>
90#include <uniconv.h>
91#include <unistr.h>
92#include <unistdio.h>
93
94
95int
97 struct GNUNET_HashCode *key)
98{
99 switch (uri->type)
100 {
102 *key = uri->data.chk.chk.query;
103 return GNUNET_OK;
104
107 strlen (uri->data.sks.identifier),
108 key);
109 return GNUNET_OK;
110
112 if (uri->data.ksk.keywordCount > 0)
113 {
115 strlen (uri->data.ksk.keywords[0]),
116 key);
117 return GNUNET_OK;
118 }
119 else
120 {
121 memset (key, 0, sizeof(struct GNUNET_HashCode));
122 return GNUNET_SYSERR;
123 }
124 break;
125
128 sizeof(struct FileIdentifier)
129 + sizeof(struct GNUNET_PeerIdentity),
130 key);
131 return GNUNET_OK;
132
133 default:
134 memset (key, 0, sizeof(struct GNUNET_HashCode));
135 return GNUNET_SYSERR;
136 }
137}
138
139
147char *
149{
150 size_t n;
151 char *ret;
152 unsigned int i;
153 const char *keyword;
154 char **keywords;
155 unsigned int keywordCount;
156
157 if ((NULL == uri) || (GNUNET_FS_URI_KSK != uri->type))
158 {
159 GNUNET_break (0);
160 return NULL;
161 }
162 keywords = uri->data.ksk.keywords;
163 keywordCount = uri->data.ksk.keywordCount;
164 n = keywordCount + 1;
165 for (i = 0; i < keywordCount; i++)
166 {
167 keyword = keywords[i];
168 n += strlen (keyword) - 1;
169 if (NULL != strstr (&keyword[1], " "))
170 n += 2;
171 if (keyword[0] == '+')
172 n++;
173 }
174 ret = GNUNET_malloc (n);
175 strcpy (ret, "");
176 for (i = 0; i < keywordCount; i++)
177 {
178 keyword = keywords[i];
179 if (NULL != strstr (&keyword[1], " "))
180 {
181 strcat (ret, "\"");
182 if (keyword[0] == '+')
183 strcat (ret, keyword);
184 else
185 strcat (ret, &keyword[1]);
186 strcat (ret, "\"");
187 }
188 else
189 {
190 if (keyword[0] == '+')
191 strcat (ret, keyword);
192 else
193 strcat (ret, &keyword[1]);
194 }
195 strcat (ret, " ");
196 }
197 return ret;
198}
199
200
211static char *
212percent_decode_keyword (const char *in, char **emsg)
213{
214 char *out;
215 char *ret;
216 unsigned int rpos;
217 unsigned int wpos;
218 unsigned int hx;
219
220 out = GNUNET_strdup (in);
221 rpos = 0;
222 wpos = 0;
223 while (out[rpos] != '\0')
224 {
225 if (out[rpos] == '%')
226 {
227 if (1 != sscanf (&out[rpos + 1], "%2X", &hx))
228 {
229 GNUNET_free (out);
230 *emsg = GNUNET_strdup (
231 _ ( /* xgettext:no-c-format */
232 "Malformed KSK URI (`%' must be followed by HEX number)"));
233 return NULL;
234 }
235 rpos += 3;
236 if (hx == '"')
237 continue; /* skip double quote */
238 out[wpos++] = (char) hx;
239 }
240 else
241 {
242 out[wpos++] = out[rpos++];
243 }
244 }
245 out[wpos] = '\0';
246 if (out[0] == '+')
247 {
248 ret = GNUNET_strdup (out);
249 }
250 else
251 {
252 /* need to prefix with space */
253 ret = GNUNET_malloc (strlen (out) + 2);
254 strcpy (ret, " ");
255 strcat (ret, out);
256 }
257 GNUNET_free (out);
258 return ret;
259}
260
261
262#define GNUNET_FS_URI_KSK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX
263
271static struct GNUNET_FS_Uri *
272uri_ksk_parse (const char *s, char **emsg)
273{
274 struct GNUNET_FS_Uri *ret;
275 char **keywords;
276 unsigned int pos;
277 int max;
278 int iret;
279 int i;
280 size_t slen;
281 char *dup;
282 int saw_quote;
283
284 slen = strlen (s);
285 pos = strlen (GNUNET_FS_URI_KSK_PREFIX);
286 if ((slen <= pos) || (0 != strncmp (s, GNUNET_FS_URI_KSK_PREFIX, pos)))
287 return NULL; /* not KSK URI */
288 if ((s[slen - 1] == '+') || (s[pos] == '+'))
289 {
290 *emsg =
291 GNUNET_strdup (_ ("Malformed KSK URI (must not begin or end with `+')"));
292 return NULL;
293 }
294 max = 1;
295 saw_quote = 0;
296 for (i = pos; i < slen; i++)
297 {
298 if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
299 {
300 saw_quote = (saw_quote + 1) % 2;
301 i += 3;
302 continue;
303 }
304 if ((s[i] == '+') && (saw_quote == 0))
305 {
306 max++;
307 if (s[i - 1] == '+')
308 {
309 *emsg = GNUNET_strdup (_ ("Malformed KSK URI (`++' not allowed)"));
310 return NULL;
311 }
312 }
313 }
314 if (saw_quote == 1)
315 {
316 *emsg = GNUNET_strdup (_ ("Malformed KSK URI (quotes not balanced)"));
317 return NULL;
318 }
319 iret = max;
320 dup = GNUNET_strdup (s);
321 keywords = GNUNET_new_array (max, char *);
322 for (i = slen - 1; i >= (int) pos; i--)
323 {
324 if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
325 {
326 saw_quote = (saw_quote + 1) % 2;
327 continue;
328 }
329 if ((dup[i] == '+') && (saw_quote == 0))
330 {
331 keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg);
332 if (NULL == keywords[max])
333 goto CLEANUP;
334 dup[i] = '\0';
335 }
336 }
337 keywords[--max] = percent_decode_keyword (&dup[pos], emsg);
338 if (NULL == keywords[max])
339 goto CLEANUP;
340 GNUNET_assert (0 == max);
341 GNUNET_free (dup);
342 ret = GNUNET_new (struct GNUNET_FS_Uri);
343 ret->type = GNUNET_FS_URI_KSK;
344 ret->data.ksk.keywordCount = iret;
345 ret->data.ksk.keywords = keywords;
346 return ret;
347 CLEANUP:
348 for (i = 0; i < max; i++)
351 GNUNET_free (dup);
352 return NULL;
353}
354
355
356#define GNUNET_FS_URI_SKS_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX
357
365static struct GNUNET_FS_Uri *
366uri_sks_parse (const char *s, char **emsg)
367{
368 struct GNUNET_FS_Uri *ret;
370 size_t pos;
371 char *end;
372
373 pos = strlen (GNUNET_FS_URI_SKS_PREFIX);
374 if ((strlen (s) <= pos) || (0 != strncmp (s, GNUNET_FS_URI_SKS_PREFIX, pos)))
375 return NULL; /* not an SKS URI */
376 end = strchr (&s[pos], '/');
377 if ((NULL == end) ||
379 end - &s[pos],
380 &ns,
381 sizeof(ns))))
382 {
383 *emsg = GNUNET_strdup (_ ("Malformed SKS URI (wrong syntax)"));
384 return NULL; /* malformed */
385 }
386 end++; /* skip over '/' */
387 ret = GNUNET_new (struct GNUNET_FS_Uri);
388 ret->type = GNUNET_FS_URI_SKS;
389 ret->data.sks.ns = ns;
390 ret->data.sks.identifier = GNUNET_strdup (end);
391 return ret;
392}
393
394
395#define GNUNET_FS_URI_CHK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX
396
397
405static struct GNUNET_FS_Uri *
406uri_chk_parse (const char *s, char **emsg)
407{
408 struct GNUNET_FS_Uri *ret;
409 struct FileIdentifier fi;
410 unsigned int pos;
411 unsigned long long flen;
412 size_t slen;
413 char h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
414 char h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
415
416 slen = strlen (s);
417 pos = strlen (GNUNET_FS_URI_CHK_PREFIX);
418 if ((slen < pos + 2 * sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
419 (0 != strncmp (s, GNUNET_FS_URI_CHK_PREFIX, pos)))
420 return NULL; /* not a CHK URI */
421 if ((s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
422 (s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.'))
423 {
424 *emsg = GNUNET_strdup (_ ("Malformed CHK URI (wrong syntax)"));
425 return NULL;
426 }
427 GNUNET_memcpy (h1, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
428 h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
429 GNUNET_memcpy (h2,
430 &s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)],
431 sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
432 h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
433
434 if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &fi.chk.key)) ||
436 (1 !=
437 sscanf (&s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
438 "%llu",
439 &flen)))
440 {
441 *emsg = GNUNET_strdup (_ ("Malformed CHK URI (failed to decode CHK)"));
442 return NULL;
443 }
444 fi.file_length = GNUNET_htonll (flen);
445 ret = GNUNET_new (struct GNUNET_FS_Uri);
446 ret->type = GNUNET_FS_URI_CHK;
447 ret->data.chk = fi;
448 return ret;
449}
450
451
459{
464
469
474
479};
481
482
483#define GNUNET_FS_URI_LOC_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX
484
485#define SIGNATURE_ASCII_LENGTH 103
486
495static struct GNUNET_FS_Uri *
496uri_loc_parse (const char *s, char **emsg)
497{
498 struct GNUNET_FS_Uri *uri;
499 char h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
500 char h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
501 unsigned int pos;
502 unsigned int npos;
503 unsigned long long exptime;
504 unsigned long long flen;
505 struct GNUNET_TIME_Absolute et;
507 struct LocUriAssembly ass;
508 size_t slen;
509
510 slen = strlen (s);
511 pos = strlen (GNUNET_FS_URI_LOC_PREFIX);
512 if ((slen < pos + 2 * sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
513 (0 != strncmp (s, GNUNET_FS_URI_LOC_PREFIX, pos)))
514 return NULL; /* not a LOC URI */
515 if ((s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
516 (s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.'))
517 {
518 *emsg = GNUNET_strdup (_ ("LOC URI malformed (wrong syntax)"));
519 return NULL;
520 }
521 GNUNET_memcpy (h1, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
522 h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
523 GNUNET_memcpy (h2,
524 &s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)],
525 sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
526 h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
527
528 if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &ass.fi.chk.key)) ||
530 (1 !=
531 sscanf (&s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
532 "%llu",
533 &flen)))
534 {
535 *emsg = GNUNET_strdup (_ ("LOC URI malformed (no CHK)"));
536 return NULL;
537 }
538 ass.fi.file_length = GNUNET_htonll (flen);
539
540 npos = pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded) * 2;
541 while ((s[npos] != '\0') && (s[npos] != '.'))
542 npos++;
543 if (s[npos] == '\0')
544 {
545 *emsg = GNUNET_strdup (_ ("LOC URI malformed (missing LOC)"));
546 goto ERR;
547 }
548 npos++;
549 if ((strlen (&s[npos]) <= GNUNET_CRYPTO_PKEY_ASCII_LENGTH + 1) ||
550 ('.' != s[npos + GNUNET_CRYPTO_PKEY_ASCII_LENGTH]))
551 {
552 *emsg =
553 GNUNET_strdup (_ ("LOC URI malformed (wrong syntax for public key)"));
554 }
555 if (
556 GNUNET_OK !=
559 &ass.peer.public_key))
560 {
561 *emsg =
562 GNUNET_strdup (_ ("LOC URI malformed (could not decode public key)"));
563 goto ERR;
564 }
566 if (s[npos++] != '.')
567 {
568 *emsg = GNUNET_strdup (_ ("LOC URI malformed (could not find signature)"));
569 goto ERR;
570 }
571 if ((strlen (&s[npos]) <= SIGNATURE_ASCII_LENGTH + 1) ||
572 ('.' != s[npos + SIGNATURE_ASCII_LENGTH]))
573 {
574 *emsg =
575 GNUNET_strdup (_ ("LOC URI malformed (wrong syntax for signature)"));
576 goto ERR;
577 }
578 if (GNUNET_OK !=
581 &sig,
582 sizeof(
584 {
585 *emsg =
586 GNUNET_strdup (_ ("LOC URI malformed (could not decode signature)"));
587 goto ERR;
588 }
590 if (s[npos++] != '.')
591 {
592 *emsg = GNUNET_strdup (
593 _ ("LOC URI malformed (wrong syntax for expiration time)"));
594 goto ERR;
595 }
596 if (1 != sscanf (&s[npos], "%llu", &exptime))
597 {
598 *emsg =
599 GNUNET_strdup (_ ("LOC URI malformed (could not parse expiration time)"));
600 goto ERR;
601 }
602 ass.purpose.size = htonl (sizeof(struct LocUriAssembly));
604 et.abs_value_us = exptime * 1000LL * 1000LL;
606 if (GNUNET_OK !=
608 &ass,
609 &sig,
610 &ass.peer.public_key))
611 {
612 *emsg =
613 GNUNET_strdup (_ ("LOC URI malformed (signature failed validation)"));
614 goto ERR;
615 }
616 uri = GNUNET_new (struct GNUNET_FS_Uri);
618 uri->data.loc.fi = ass.fi;
619 uri->data.loc.peer = ass.peer;
622
623 return uri;
624 ERR:
625 return NULL;
626}
627
628
636struct GNUNET_FS_Uri *
637GNUNET_FS_uri_parse (const char *uri, char **emsg)
638{
639 struct GNUNET_FS_Uri *ret;
640 char *msg;
641
642 if (NULL == uri)
643 {
644 GNUNET_break (0);
645 if (NULL != emsg)
646 *emsg = GNUNET_strdup (_ ("invalid argument"));
647 return NULL;
648 }
652 msg = NULL;
653 if (NULL != (ret = uri_chk_parse (uri, &msg)))
654 return ret;
656 if (NULL != (ret = uri_ksk_parse (uri, &msg)))
657 return ret;
659 if (NULL != (ret = uri_sks_parse (uri, &msg)))
660 return ret;
662 if (NULL != (ret = uri_loc_parse (uri, &msg)))
663 return ret;
665 if (NULL != emsg)
666 *emsg = GNUNET_strdup (_ ("Unrecognized URI type"));
667 return NULL;
668}
669
670
676void
678{
679 unsigned int i;
680
681 switch (uri->type)
682 {
684 for (i = 0; i < uri->data.ksk.keywordCount; i++)
687 break;
688
691 break;
692
694 break;
695
696 default:
697 /* do nothing */
698 break;
699 }
701}
702
703
710unsigned int
712{
713 if (uri->type != GNUNET_FS_URI_KSK)
714 return 0;
715 return uri->data.ksk.keywordCount;
716}
717
718
719int
722 void *iterator_cls)
723{
724 unsigned int i;
725 char *keyword;
726
727 if (uri->type != GNUNET_FS_URI_KSK)
728 return -1;
729 if (NULL == iterator)
730 return uri->data.ksk.keywordCount;
731 for (i = 0; i < uri->data.ksk.keywordCount; i++)
732 {
733 keyword = uri->data.ksk.keywords[i];
734 /* first character of keyword indicates
735 * if it is mandatory or not */
736 if (GNUNET_OK != iterator (iterator_cls, &keyword[1],(keyword[0] == '+') ))
737 return i;
738 }
739 return i;
740}
741
742
751void
753 const char *keyword,
754 int is_mandatory)
755{
756 unsigned int i;
757 const char *old;
758 char *n;
759
761 for (i = 0; i < uri->data.ksk.keywordCount; i++)
762 {
763 old = uri->data.ksk.keywords[i];
764 if (0 == strcmp (&old[1], keyword))
765 return;
766 }
767 GNUNET_asprintf (&n, is_mandatory ? "+%s" : " %s", keyword);
769}
770
771
779void
781 const char *keyword)
782{
783 unsigned int i;
784 char *old;
785
787 for (i = 0; i < uri->data.ksk.keywordCount; i++)
788 {
789 old = uri->data.ksk.keywords[i];
790 if (0 == strcmp (&old[1], keyword))
791 {
792 uri->data.ksk.keywords[i] =
796 uri->data.ksk.keywordCount - 1);
797 GNUNET_free (old);
798 return;
799 }
800 }
801}
802
803
811int
813 struct GNUNET_PeerIdentity *peer)
814{
815 if (uri->type != GNUNET_FS_URI_LOC)
816 return GNUNET_SYSERR;
817 *peer = uri->data.loc.peer;
818 return GNUNET_OK;
819}
820
821
830{
832 return uri->data.loc.expirationTime;
833}
834
835
842struct GNUNET_FS_Uri *
844{
845 struct GNUNET_FS_Uri *ret;
846
847 if (uri->type != GNUNET_FS_URI_LOC)
848 return NULL;
849 ret = GNUNET_new (struct GNUNET_FS_Uri);
850 ret->type = GNUNET_FS_URI_CHK;
851 ret->data.chk = uri->data.loc.fi;
852 return ret;
853}
854
855
868struct GNUNET_FS_Uri *
870 const struct GNUNET_CRYPTO_EddsaPrivateKey *sign_key,
871 struct GNUNET_TIME_Absolute expiration_time)
872{
873 struct GNUNET_FS_Uri *uri;
874 struct GNUNET_CRYPTO_EddsaPublicKey my_public_key;
875 struct LocUriAssembly ass;
876 struct GNUNET_TIME_Absolute et;
877
878 if (GNUNET_FS_URI_CHK != base_uri->type)
879 return NULL;
880 /* we round expiration time to full seconds for SKS URIs */
881 et.abs_value_us = (expiration_time.abs_value_us / 1000000LL) * 1000000LL;
882 GNUNET_CRYPTO_eddsa_key_get_public (sign_key, &my_public_key);
883 ass.purpose.size = htonl (sizeof(struct LocUriAssembly));
886 ass.fi = base_uri->data.chk;
887 ass.peer.public_key = my_public_key;
888 uri = GNUNET_new (struct GNUNET_FS_Uri);
890 uri->data.loc.fi = base_uri->data.chk;
892 uri->data.loc.peer.public_key = my_public_key;
893 GNUNET_CRYPTO_eddsa_sign (sign_key,
894 &ass,
896 return uri;
897}
898
899
907struct GNUNET_FS_Uri *
909 const char *id)
910{
911 struct GNUNET_FS_Uri *ns_uri;
912
913 ns_uri = GNUNET_new (struct GNUNET_FS_Uri);
914 ns_uri->type = GNUNET_FS_URI_SKS;
915 ns_uri->data.sks.ns = *ns;
916 ns_uri->data.sks.identifier = GNUNET_strdup (id);
917 return ns_uri;
918}
919
920
930struct GNUNET_FS_Uri *
932 const struct GNUNET_FS_Uri *u2)
933{
934 struct GNUNET_FS_Uri *ret;
935 unsigned int kc;
936 unsigned int i;
937 unsigned int j;
938 int found;
939 const char *kp;
940 char **kl;
941
942 if ((u1 == NULL) && (u2 == NULL))
943 return NULL;
944 if (u1 == NULL)
945 return GNUNET_FS_uri_dup (u2);
946 if (u2 == NULL)
947 return GNUNET_FS_uri_dup (u1);
948 if ((u1->type != GNUNET_FS_URI_KSK) || (u2->type != GNUNET_FS_URI_KSK))
949 {
950 GNUNET_break (0);
951 return NULL;
952 }
953 kc = u1->data.ksk.keywordCount;
954 kl = GNUNET_new_array (kc + u2->data.ksk.keywordCount, char *);
955 for (i = 0; i < u1->data.ksk.keywordCount; i++)
956 kl[i] = GNUNET_strdup (u1->data.ksk.keywords[i]);
957 for (i = 0; i < u2->data.ksk.keywordCount; i++)
958 {
959 kp = u2->data.ksk.keywords[i];
960 found = 0;
961 for (j = 0; j < u1->data.ksk.keywordCount; j++)
962 if (0 == strcmp (kp + 1, kl[j] + 1))
963 {
964 found = 1;
965 if (kp[0] == '+')
966 kl[j][0] = '+';
967 break;
968 }
969 if (0 == found)
970 kl[kc++] = GNUNET_strdup (kp);
971 }
972 ret = GNUNET_new (struct GNUNET_FS_Uri);
973 ret->type = GNUNET_FS_URI_KSK;
974 ret->data.ksk.keywordCount = kc;
975 ret->data.ksk.keywords = kl;
976 return ret;
977}
978
979
986struct GNUNET_FS_Uri *
988{
989 struct GNUNET_FS_Uri *ret;
990 unsigned int i;
991
992 if (uri == NULL)
993 return NULL;
994 ret = GNUNET_new (struct GNUNET_FS_Uri);
995 GNUNET_memcpy (ret, uri, sizeof(struct GNUNET_FS_Uri));
996 switch (ret->type)
997 {
999 if (ret->data.ksk.keywordCount >=
1000 GNUNET_MAX_MALLOC_CHECKED / sizeof(char *))
1001 {
1002 GNUNET_break (0);
1003 GNUNET_free (ret);
1004 return NULL;
1005 }
1006 if (ret->data.ksk.keywordCount > 0)
1007 {
1008 ret->data.ksk.keywords =
1009 GNUNET_new_array (ret->data.ksk.keywordCount, char *);
1010 for (i = 0; i < ret->data.ksk.keywordCount; i++)
1011 ret->data.ksk.keywords[i] = GNUNET_strdup (uri->data.ksk.keywords[i]);
1012 }
1013 else
1014 ret->data.ksk.keywords = NULL; /* just to be sure */
1015 break;
1016
1017 case GNUNET_FS_URI_SKS:
1018 ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier);
1019 break;
1020
1021 case GNUNET_FS_URI_LOC:
1022 break;
1023
1024 default:
1025 break;
1026 }
1027 return ret;
1028}
1029
1030
1048struct GNUNET_FS_Uri *
1049GNUNET_FS_uri_ksk_create (const char *keywords, char **emsg)
1050{
1051 char **keywordarr;
1052 unsigned int num_Words;
1053 int inWord;
1054 char *pos;
1055 struct GNUNET_FS_Uri *uri;
1056 char *searchString;
1057 int saw_quote;
1058
1059 if (keywords == NULL)
1060 {
1061 *emsg = GNUNET_strdup (_ ("No keywords specified!\n"));
1062 GNUNET_break (0);
1063 return NULL;
1064 }
1065 searchString = GNUNET_strdup (keywords);
1066 num_Words = 0;
1067 inWord = 0;
1068 saw_quote = 0;
1069 pos = searchString;
1070 while ('\0' != *pos)
1071 {
1072 if ((saw_quote == 0) && (isspace ((unsigned char) *pos)))
1073 {
1074 inWord = 0;
1075 }
1076 else if (0 == inWord)
1077 {
1078 inWord = 1;
1079 ++num_Words;
1080 }
1081 if ('"' == *pos)
1082 saw_quote = (saw_quote + 1) % 2;
1083 pos++;
1084 }
1085 if (num_Words == 0)
1086 {
1087 GNUNET_free (searchString);
1088 *emsg = GNUNET_strdup (_ ("No keywords specified!\n"));
1089 return NULL;
1090 }
1091 if (saw_quote != 0)
1092 {
1093 GNUNET_free (searchString);
1094 *emsg = GNUNET_strdup (_ ("Number of double-quotes not balanced!\n"));
1095 return NULL;
1096 }
1097 keywordarr = GNUNET_new_array (num_Words, char *);
1098 num_Words = 0;
1099 inWord = 0;
1100 pos = searchString;
1101 while ('\0' != *pos)
1102 {
1103 if ((saw_quote == 0) && (isspace ((unsigned char) *pos)))
1104 {
1105 inWord = 0;
1106 *pos = '\0';
1107 }
1108 else if (0 == inWord)
1109 {
1110 keywordarr[num_Words] = pos;
1111 inWord = 1;
1112 ++num_Words;
1113 }
1114 if ('"' == *pos)
1115 saw_quote = (saw_quote + 1) % 2;
1116 pos++;
1117 }
1118 uri =
1119 GNUNET_FS_uri_ksk_create_from_args (num_Words, (const char **) keywordarr);
1120 GNUNET_free (keywordarr);
1121 GNUNET_free (searchString);
1122 return uri;
1123}
1124
1125
1143struct GNUNET_FS_Uri *
1144GNUNET_FS_uri_ksk_create_from_args (unsigned int argc, const char **argv)
1145{
1146 unsigned int i;
1147 struct GNUNET_FS_Uri *uri;
1148 const char *keyword;
1149 char *val;
1150 const char *r;
1151 char *w;
1152 char *emsg;
1153
1154 if (argc == 0)
1155 return NULL;
1156 /* allow URI to be given as one and only keyword and
1157 * handle accordingly */
1158 emsg = NULL;
1159 if ((argc == 1) && (strlen (argv[0]) > strlen (GNUNET_FS_URI_PREFIX)) &&
1160 (0 == strncmp (argv[0],
1162 strlen (GNUNET_FS_URI_PREFIX))) &&
1163 (NULL != (uri = GNUNET_FS_uri_parse (argv[0], &emsg))))
1164 return uri;
1165 GNUNET_free (emsg);
1166 uri = GNUNET_new (struct GNUNET_FS_Uri);
1168 uri->data.ksk.keywordCount = argc;
1169 uri->data.ksk.keywords = GNUNET_new_array (argc, char *);
1170 for (i = 0; i < argc; i++)
1171 {
1172 keyword = argv[i];
1173 if (keyword[0] == '+')
1174 val = GNUNET_strdup (keyword);
1175 else
1176 GNUNET_asprintf (&val, " %s", keyword);
1177 r = val;
1178 w = val;
1179 while ('\0' != *r)
1180 {
1181 if ('"' == *r)
1182 r++;
1183 else
1184 *(w++) = *(r++);
1185 }
1186 *w = '\0';
1187 uri->data.ksk.keywords[i] = val;
1188 }
1189 return uri;
1190}
1191
1192
1200int
1202 const struct GNUNET_FS_Uri *u2)
1203{
1204 int ret;
1205 unsigned int i;
1206 unsigned int j;
1207
1208 GNUNET_assert (u1 != NULL);
1209 GNUNET_assert (u2 != NULL);
1210 if (u1->type != u2->type)
1211 return GNUNET_NO;
1212 switch (u1->type)
1213 {
1214 case GNUNET_FS_URI_CHK:
1215 if (0 ==
1216 memcmp (&u1->data.chk, &u2->data.chk, sizeof(struct FileIdentifier)))
1217 return GNUNET_YES;
1218 return GNUNET_NO;
1219
1220 case GNUNET_FS_URI_SKS:
1221 if ((0 == memcmp (&u1->data.sks.ns,
1222 &u2->data.sks.ns,
1223 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) &&
1224 (0 == strcmp (u1->data.sks.identifier, u2->data.sks.identifier)))
1225
1226 return GNUNET_YES;
1227 return GNUNET_NO;
1228
1229 case GNUNET_FS_URI_KSK:
1230 if (u1->data.ksk.keywordCount != u2->data.ksk.keywordCount)
1231 return GNUNET_NO;
1232 for (i = 0; i < u1->data.ksk.keywordCount; i++)
1233 {
1234 ret = GNUNET_NO;
1235 for (j = 0; j < u2->data.ksk.keywordCount; j++)
1236 {
1237 if (0 == strcmp (u1->data.ksk.keywords[i], u2->data.ksk.keywords[j]))
1238 {
1239 ret = GNUNET_YES;
1240 break;
1241 }
1242 }
1243 if (ret == GNUNET_NO)
1244 return GNUNET_NO;
1245 }
1246 return GNUNET_YES;
1247
1248 case GNUNET_FS_URI_LOC:
1249 if (memcmp (&u1->data.loc,
1250 &u2->data.loc,
1251 sizeof(struct FileIdentifier)
1252 + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)
1253 + sizeof(struct GNUNET_TIME_Absolute)
1254 + sizeof(unsigned short) + sizeof(unsigned short)) != 0)
1255 return GNUNET_NO;
1256 return GNUNET_YES;
1257
1258 default:
1259 return GNUNET_NO;
1260 }
1261}
1262
1263
1270int
1272{
1273 return uri->type == GNUNET_FS_URI_SKS;
1274}
1275
1276
1285int
1288{
1290 {
1291 GNUNET_break (0);
1292 return GNUNET_SYSERR;
1293 }
1294 *pseudonym = uri->data.sks.ns;
1295 return GNUNET_OK;
1296}
1297
1298
1305char *
1307{
1309 {
1310 GNUNET_break (0);
1311 return NULL;
1312 }
1314}
1315
1316
1323int
1325{
1326#if EXTRA_CHECKS
1327 unsigned int i;
1328
1329 if (uri->type == GNUNET_FS_URI_KSK)
1330 {
1331 for (i = 0; i < uri->data.ksk.keywordCount; i++)
1332 GNUNET_assert (uri->data.ksk.keywords[i] != NULL);
1333 }
1334#endif
1335 return uri->type == GNUNET_FS_URI_KSK;
1336}
1337
1338
1345int
1347{
1348 return uri->type == GNUNET_FS_URI_CHK;
1349}
1350
1351
1359uint64_t
1361{
1362 switch (uri->type)
1363 {
1364 case GNUNET_FS_URI_CHK:
1366
1367 case GNUNET_FS_URI_LOC:
1369
1370 default:
1371 GNUNET_assert (0);
1372 }
1373 return 0; /* unreachable */
1374}
1375
1376
1383int
1385{
1386 return uri->type == GNUNET_FS_URI_LOC;
1387}
1388
1389
1399static void
1400insert_non_mandatory_keyword (const char *s, char **array, int index)
1401{
1402 char *nkword;
1403
1404 GNUNET_asprintf (&nkword,
1405 " %s", /* space to mark as 'non mandatory' */
1406 s);
1407 array[index] = nkword;
1408}
1409
1410
1420static int
1421find_duplicate (const char *s, const char **array, int array_length)
1422{
1423 int j;
1424
1425 for (j = array_length - 1; j >= 0; j--)
1426 if (0 == strcmp (&array[j][1], s))
1427 return GNUNET_YES;
1428 return GNUNET_NO;
1429}
1430
1431
1435static char *
1436normalize_metadata (enum EXTRACTOR_MetaFormat format,
1437 const char *data,
1438 size_t data_len)
1439{
1440 uint8_t *free_str = NULL;
1441 uint8_t *str_to_normalize = (uint8_t *) data;
1442 uint8_t *normalized;
1443 size_t r_len;
1444
1445 if (str_to_normalize == NULL)
1446 return NULL;
1447 /* Don't trust libextractor */
1448 if (format == EXTRACTOR_METAFORMAT_UTF8)
1449 {
1450 free_str = (uint8_t *) u8_check ((const uint8_t *) data, data_len);
1451 if (free_str == NULL)
1452 free_str = NULL;
1453 else
1454 format = EXTRACTOR_METAFORMAT_C_STRING;
1455 }
1456 if (format == EXTRACTOR_METAFORMAT_C_STRING)
1457 {
1458 free_str = u8_strconv_from_encoding (data,
1459 locale_charset (),
1460 iconveh_escape_sequence);
1461 if (free_str == NULL)
1462 return NULL;
1463 }
1464
1465 normalized = u8_tolower (str_to_normalize,
1466 strlen ((char *) str_to_normalize),
1467 NULL,
1468 UNINORM_NFD,
1469 NULL,
1470 &r_len);
1471 /* free_str is allocated by libunistring internally, use free() */
1472 if (free_str != NULL)
1473 free (free_str);
1474 if (normalized != NULL)
1475 {
1476 /* u8_tolower allocates a non-NULL-terminated string! */
1477 free_str = GNUNET_malloc (r_len + 1);
1478 GNUNET_memcpy (free_str, normalized, r_len);
1479 free_str[r_len] = '\0';
1480 free (normalized);
1481 normalized = free_str;
1482 }
1483 return (char *) normalized;
1484}
1485
1486
1491static size_t
1492u8_strcount (const uint8_t *s)
1493{
1494 size_t count;
1495 ucs4_t c;
1496
1497 GNUNET_assert (s != NULL);
1498 if (s[0] == 0)
1499 return 0;
1500 for (count = 0; s != NULL; count++)
1501 s = u8_next (&c, s);
1502 return count - 1;
1503}
1504
1505
1522static int
1523get_keywords_from_parens (const char *s, char **array, int index)
1524{
1525 int count = 0;
1526 char *open_paren;
1527 char *close_paren;
1528 char *ss;
1529 char tmp;
1530
1531 if (NULL == s)
1532 return 0;
1533 ss = GNUNET_strdup (s);
1534 open_paren = ss - 1;
1535 while (NULL != (open_paren = strpbrk (open_paren + 1, "[{(")))
1536 {
1537 int match = 0;
1538
1539 close_paren = strpbrk (open_paren + 1, "]})");
1540 if (NULL == close_paren)
1541 continue;
1542 switch (open_paren[0])
1543 {
1544 case '[':
1545 if (']' == close_paren[0])
1546 match = 1;
1547 break;
1548
1549 case '{':
1550 if ('}' == close_paren[0])
1551 match = 1;
1552 break;
1553
1554 case '(':
1555 if (')' == close_paren[0])
1556 match = 1;
1557 break;
1558
1559 default:
1560 break;
1561 }
1562 if (match && (close_paren - open_paren > 1))
1563 {
1564 tmp = close_paren[0];
1565 close_paren[0] = '\0';
1566 /* Keywords must be at least 3 characters long */
1567 if (u8_strcount ((const uint8_t *) &open_paren[1]) <= 2)
1568 {
1569 close_paren[0] = tmp;
1570 continue;
1571 }
1572 if (NULL != array)
1573 {
1574 char *normalized;
1575 if (GNUNET_NO == find_duplicate ((const char *) &open_paren[1],
1576 (const char **) array,
1577 index + count))
1578 {
1579 insert_non_mandatory_keyword ((const char *) &open_paren[1],
1580 array,
1581 index + count);
1582 count++;
1583 }
1584 normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8,
1585 &open_paren[1],
1586 close_paren - &open_paren[1]);
1587 if (normalized != NULL)
1588 {
1589 if (GNUNET_NO == find_duplicate ((const char *) normalized,
1590 (const char **) array,
1591 index + count))
1592 {
1593 insert_non_mandatory_keyword ((const char *) normalized,
1594 array,
1595 index + count);
1596 count++;
1597 }
1598 GNUNET_free (normalized);
1599 }
1600 }
1601 else
1602 count++;
1603 close_paren[0] = tmp;
1604 }
1605 }
1606 GNUNET_free (ss);
1607 return count;
1608}
1609
1610
1614#define TOKENS "_. /-!?#&+@\"\'\\;:,()[]{}$<>|"
1615
1630static int
1631get_keywords_from_tokens (const char *s, char **array, int index)
1632{
1633 char *p;
1634 char *ss;
1635 int seps = 0;
1636
1637 ss = GNUNET_strdup (s);
1638 for (p = strtok (ss, TOKENS); p != NULL; p = strtok (NULL, TOKENS))
1639 {
1640 /* Keywords must be at least 3 characters long */
1641 if (u8_strcount ((const uint8_t *) p) <= 2)
1642 continue;
1643 if (NULL != array)
1644 {
1645 char *normalized;
1646 if (GNUNET_NO == find_duplicate (p, (const char **) array, index + seps))
1647 {
1648 insert_non_mandatory_keyword (p, array, index + seps);
1649 seps++;
1650 }
1651 normalized =
1652 normalize_metadata (EXTRACTOR_METAFORMAT_UTF8, p, strlen (p));
1653 if (normalized != NULL)
1654 {
1655 if (GNUNET_NO == find_duplicate ((const char *) normalized,
1656 (const char **) array,
1657 index + seps))
1658 {
1659 insert_non_mandatory_keyword ((const char *) normalized,
1660 array,
1661 index + seps);
1662 seps++;
1663 }
1664 GNUNET_free (normalized);
1665 }
1666 }
1667 else
1668 seps++;
1669 }
1670 GNUNET_free (ss);
1671 return seps;
1672}
1673
1674
1675#undef TOKENS
1676
1677
1695static int
1697 const char *plugin_name,
1698 enum EXTRACTOR_MetaType type,
1699 enum EXTRACTOR_MetaFormat format,
1700 const char *data_mime_type,
1701 const char *data,
1702 size_t data_len)
1703{
1704 struct GNUNET_FS_Uri *uri = cls;
1705 char *normalized_data;
1706 const char *sep;
1707
1708 if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1709 (format != EXTRACTOR_METAFORMAT_C_STRING))
1710 return 0;
1711 /* Keywords must be at least 3 characters long
1712 * If given non-utf8 string it will, most likely, find it to be invalid,
1713 * and will return the length of its valid part, skipping the keyword.
1714 * If it does - fix the extractor, not this check!
1715 */if (u8_strcount ((const uint8_t *) data) <= 2)
1716 return 0;
1717 if ((EXTRACTOR_METATYPE_MIMETYPE == type) &&
1718 (NULL != (sep = memchr (data, '/', data_len))) && (sep != data))
1719 {
1720 char *xtra;
1721
1722 GNUNET_asprintf (&xtra, "mimetype:%.*s", (int) (sep - data), data);
1723 if (! find_duplicate (xtra,
1724 (const char **) uri->data.ksk.keywords,
1726 {
1731 }
1732 GNUNET_free (xtra);
1733 }
1734
1735 normalized_data = normalize_metadata (format, data, data_len);
1736 if (! find_duplicate (data,
1737 (const char **) uri->data.ksk.keywords,
1739 {
1744 }
1745 if (NULL != normalized_data)
1746 {
1747 if (! find_duplicate (normalized_data,
1748 (const char **) uri->data.ksk.keywords,
1750 {
1751 insert_non_mandatory_keyword (normalized_data,
1755 }
1756 GNUNET_free (normalized_data);
1757 }
1758 return 0;
1759}
1760
1761
1770struct GNUNET_FS_Uri *
1772 const struct GNUNET_FS_MetaData *md)
1773{
1774 struct GNUNET_FS_Uri *ret;
1775 char *filename;
1776 char *full_name = NULL;
1777 char *ss;
1778 int ent;
1779 int tok_keywords = 0;
1780 int paren_keywords = 0;
1781
1782 if (NULL == md)
1783 return NULL;
1784 ret = GNUNET_new (struct GNUNET_FS_Uri);
1785 ret->type = GNUNET_FS_URI_KSK;
1786 ent = GNUNET_FS_meta_data_iterate (md, NULL, NULL);
1787 if (ent > 0)
1788 {
1790 md,
1792 -1);
1793 if (NULL != full_name)
1794 {
1795 filename = full_name;
1796 while (NULL != (ss = strstr (filename, DIR_SEPARATOR_STR)))
1797 filename = ss + 1;
1798 tok_keywords = get_keywords_from_tokens (filename, NULL, 0);
1799 paren_keywords = get_keywords_from_parens (filename, NULL, 0);
1800 }
1801 /* x3 because there might be a normalized variant of every keyword,
1802 plus theoretically one more for mime... */
1803 ret->data.ksk.keywords =
1804 GNUNET_new_array ((ent + tok_keywords + paren_keywords) * 3, char *);
1806 }
1807 if (tok_keywords > 0)
1808 ret->data.ksk.keywordCount +=
1810 ret->data.ksk.keywords,
1811 ret->data.ksk.keywordCount);
1812 if (paren_keywords > 0)
1813 ret->data.ksk.keywordCount +=
1815 ret->data.ksk.keywords,
1816 ret->data.ksk.keywordCount);
1817 if (ent > 0)
1818 GNUNET_free (full_name);
1819 return ret;
1820}
1821
1822
1827static int
1829{
1830 return(! ((isalnum ((unsigned char) c)) || (c == '-') || (c == '_') ||
1831 (c == '.') || (c == '~')));
1832}
1833
1834
1841static char *
1843{
1844 char **keywords;
1845 unsigned int keywordCount;
1846 size_t n;
1847 char *ret;
1848 unsigned int i;
1849 unsigned int j;
1850 unsigned int wpos;
1851 size_t slen;
1852 const char *keyword;
1853
1854 if (uri->type != GNUNET_FS_URI_KSK)
1855 return NULL;
1858 n = keywordCount + strlen (GNUNET_FS_URI_PREFIX)
1859 + strlen (GNUNET_FS_URI_KSK_INFIX) + 1;
1860 for (i = 0; i < keywordCount; i++)
1861 {
1862 keyword = keywords[i];
1863 slen = strlen (keyword);
1864 n += slen;
1865 for (j = 0; j < slen; j++)
1866 {
1867 if ((j == 0) && (keyword[j] == ' '))
1868 {
1869 n--;
1870 continue; /* skip leading space */
1871 }
1872 if (needs_percent (keyword[j]))
1873 n += 2; /* will use %-encoding */
1874 }
1875 }
1876 ret = GNUNET_malloc (n);
1877 strcpy (ret, GNUNET_FS_URI_PREFIX);
1878 strcat (ret, GNUNET_FS_URI_KSK_INFIX);
1879 wpos = strlen (ret);
1880 for (i = 0; i < keywordCount; i++)
1881 {
1882 keyword = keywords[i];
1883 slen = strlen (keyword);
1884 for (j = 0; j < slen; j++)
1885 {
1886 if ((j == 0) && (keyword[j] == ' '))
1887 continue; /* skip leading space */
1888 if (needs_percent (keyword[j]))
1889 {
1890 sprintf (&ret[wpos], "%%%02X", (unsigned char) keyword[j]);
1891 wpos += 3;
1892 }
1893 else
1894 {
1895 ret[wpos++] = keyword[j];
1896 }
1897 }
1898 if (i != keywordCount - 1)
1899 ret[wpos++] = '+';
1900 }
1901 return ret;
1902}
1903
1904
1911static char *
1913{
1914 char *ret;
1915 char buf[1024];
1916
1917 if (GNUNET_FS_URI_SKS != uri->type)
1918 return NULL;
1919 ret =
1921 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
1922 buf,
1923 sizeof(buf));
1924 GNUNET_assert (NULL != ret);
1925 ret[0] = '\0';
1927 "%s%s%s/%s",
1930 buf,
1932 return ret;
1933}
1934
1935
1942static char *
1944{
1945 const struct FileIdentifier *fi;
1946 char *ret;
1947 struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1948 struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1949
1950 if (uri->type != GNUNET_FS_URI_CHK)
1951 return NULL;
1952 fi = &uri->data.chk;
1953 GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash);
1954 GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash);
1955
1957 "%s%s%s.%s.%llu",
1960 (const char *) &keyhash,
1961 (const char *) &queryhash,
1962 (unsigned long long) GNUNET_ntohll (fi->file_length));
1963 return ret;
1964}
1965
1966
1973static char *
1975{
1976 char *ret;
1977 struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1978 struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1979 char *peer_id;
1980 char peer_sig[SIGNATURE_ASCII_LENGTH + 1];
1981
1984 peer_id =
1987 NULL !=
1989 sizeof(struct GNUNET_CRYPTO_EddsaSignature),
1990 peer_sig,
1991 sizeof(peer_sig)));
1993 "%s%s%s.%s.%llu.%s.%s.%llu",
1996 (const char *) &keyhash,
1997 (const char *) &queryhash,
1998 (unsigned long long) GNUNET_ntohll (
2000 peer_id,
2001 peer_sig,
2002 (unsigned long long)
2004 / 1000000LL);
2006 return ret;
2007}
2008
2009
2016char *
2018{
2019 if (uri == NULL)
2020 {
2021 GNUNET_break (0);
2022 return NULL;
2023 }
2024 switch (uri->type)
2025 {
2026 case GNUNET_FS_URI_KSK:
2027 return uri_ksk_to_string (uri);
2028
2029 case GNUNET_FS_URI_SKS:
2030 return uri_sks_to_string (uri);
2031
2032 case GNUNET_FS_URI_CHK:
2033 return uri_chk_to_string (uri);
2034
2035 case GNUNET_FS_URI_LOC:
2036 return uri_loc_to_string (uri);
2037
2038 default:
2039 GNUNET_break (0);
2040 return NULL;
2041 }
2042}
2043
2044
2045/* end of fs_uri.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
shared definitions for the FS library
@ GNUNET_FS_URI_LOC
Location (chk with identity of hosting peer).
Definition: fs_api.h:159
@ GNUNET_FS_URI_CHK
Content-hash-key (simple file).
Definition: fs_api.h:144
@ GNUNET_FS_URI_SKS
Signed key space (file in namespace).
Definition: fs_api.h:149
@ GNUNET_FS_URI_KSK
Keyword search key (query with keywords).
Definition: fs_api.h:154
#define GNUNET_FS_URI_LOC_PREFIX
Definition: fs_uri.c:483
static void insert_non_mandatory_keyword(const char *s, char **array, int index)
Add a keyword as non-mandatory (with ' '-prefix) to the given keyword list at offset 'index'.
Definition: fs_uri.c:1400
static char * uri_chk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a CHK URI to a string.
Definition: fs_uri.c:1943
static char * uri_sks_to_string(const struct GNUNET_FS_Uri *uri)
Convert SKS URI to a string.
Definition: fs_uri.c:1912
static size_t u8_strcount(const uint8_t *s)
Counts the number of UTF-8 characters (not bytes) in the string, returns that count.
Definition: fs_uri.c:1492
static int gather_uri_data(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len)
Function called on each value in the meta data.
Definition: fs_uri.c:1696
static char * uri_loc_to_string(const struct GNUNET_FS_Uri *uri)
Convert a LOC URI to a string.
Definition: fs_uri.c:1974
static int needs_percent(char c)
In URI-encoding, does the given character need to be encoded using %-encoding?
Definition: fs_uri.c:1828
#define GNUNET_FS_URI_SKS_PREFIX
Definition: fs_uri.c:356
static int get_keywords_from_parens(const char *s, char **array, int index)
Break the filename up by matching [], () and {} pairs to make keywords.
Definition: fs_uri.c:1523
static char * percent_decode_keyword(const char *in, char **emsg)
Given a keyword with %-encoding (and possibly quotes to protect spaces), return a copy of the keyword...
Definition: fs_uri.c:212
#define TOKENS
Where to break up keywords.
Definition: fs_uri.c:1614
static struct GNUNET_FS_Uri * uri_sks_parse(const char *s, char **emsg)
Parse an SKS URI.
Definition: fs_uri.c:366
static struct GNUNET_FS_Uri * uri_chk_parse(const char *s, char **emsg)
Parse a CHK URI.
Definition: fs_uri.c:406
#define SIGNATURE_ASCII_LENGTH
Definition: fs_uri.c:485
static struct GNUNET_FS_Uri * uri_ksk_parse(const char *s, char **emsg)
Parse a KSK URI.
Definition: fs_uri.c:272
static char * uri_ksk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a KSK URI to a string.
Definition: fs_uri.c:1842
#define GNUNET_FS_URI_KSK_PREFIX
Definition: fs_uri.c:262
static char * normalize_metadata(enum EXTRACTOR_MetaFormat format, const char *data, size_t data_len)
FIXME: comment.
Definition: fs_uri.c:1436
static struct GNUNET_FS_Uri * uri_loc_parse(const char *s, char **emsg)
Parse a LOC URI.
Definition: fs_uri.c:496
static int get_keywords_from_tokens(const char *s, char **array, int index)
Break the filename up by TOKENS to make keywords.
Definition: fs_uri.c:1631
#define GNUNET_FS_URI_CHK_PREFIX
Definition: fs_uri.c:395
static int find_duplicate(const char *s, const char **array, int array_length)
Test if the given keyword s is already present in the given array, ignoring the '+'-mandatory prefix ...
Definition: fs_uri.c:1421
static int ret
Final status code.
Definition: gnunet-arm.c:94
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static char * pseudonym
Command-line option identifying the pseudonym to use for the publication.
static char * plugin_name
Name of our plugin.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
API for file sharing via GNUnet.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:198
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
struct GNUNET_FS_Uri * GNUNET_FS_uri_dup(const struct GNUNET_FS_Uri *uri)
Duplicate URI.
Definition: fs_uri.c:987
#define EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME
struct GNUNET_TIME_Absolute GNUNET_FS_uri_loc_get_expiration(const struct GNUNET_FS_Uri *uri)
Obtain the expiration of the LOC URI.
Definition: fs_uri.c:829
int(* GNUNET_FS_KeywordIterator)(void *cls, const char *keyword, int is_mandatory)
Iterator over keywords.
#define GNUNET_FS_URI_SKS_INFIX
#define GNUNET_FS_URI_CHK_INFIX
void GNUNET_FS_uri_ksk_remove_keyword(struct GNUNET_FS_Uri *uri, const char *keyword)
Remove the given keyword from the set of keywords represented by the URI.
Definition: fs_uri.c:780
#define GNUNET_FS_URI_KSK_INFIX
char * GNUNET_FS_uri_sks_get_content_id(const struct GNUNET_FS_Uri *uri)
Get the content identifier of an SKS URI.
Definition: fs_uri.c:1306
uint64_t GNUNET_FS_uri_chk_get_file_size(const struct GNUNET_FS_Uri *uri)
What is the size of the file that this URI refers to?
Definition: fs_uri.c:1360
int GNUNET_FS_uri_test_ksk(const struct GNUNET_FS_Uri *uri)
Is this a keyword URI?
Definition: fs_uri.c:1324
struct GNUNET_FS_Uri * GNUNET_FS_uri_loc_create(const struct GNUNET_FS_Uri *base_uri, const struct GNUNET_CRYPTO_EddsaPrivateKey *sign_key, struct GNUNET_TIME_Absolute expiration_time)
Construct a location URI (this peer will be used for the location).
Definition: fs_uri.c:869
struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create(const char *keywords, char **emsg)
Create an FS URI from a single user-supplied string of keywords.
Definition: fs_uri.c:1049
int GNUNET_FS_uri_test_equal(const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2)
Test if two URIs are equal.
Definition: fs_uri.c:1201
int GNUNET_FS_uri_test_loc(const struct GNUNET_FS_Uri *uri)
Is this a location URI?
Definition: fs_uri.c:1384
char * GNUNET_FS_uri_to_string(const struct GNUNET_FS_Uri *uri)
Convert a URI to a UTF-8 String.
Definition: fs_uri.c:2017
struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_args(unsigned int argc, const char **argv)
Create an FS URI from a user-supplied command line of keywords.
Definition: fs_uri.c:1144
#define GNUNET_FS_URI_PREFIX
#define GNUNET_FS_URI_LOC_INFIX
struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_meta_data(const struct GNUNET_FS_MetaData *md)
Construct a keyword-URI from meta-data (take all entries in the meta-data and construct one large key...
Definition: fs_uri.c:1771
int GNUNET_FS_uri_ksk_get_keywords(const struct GNUNET_FS_Uri *uri, GNUNET_FS_KeywordIterator iterator, void *iterator_cls)
Iterate over all keywords in this keyword URI.
Definition: fs_uri.c:720
void GNUNET_FS_uri_destroy(struct GNUNET_FS_Uri *uri)
Free URI.
Definition: fs_uri.c:677
int GNUNET_FS_uri_sks_get_namespace(const struct GNUNET_FS_Uri *uri, struct GNUNET_CRYPTO_EcdsaPublicKey *pseudonym)
Get the ID of a namespace from the given namespace URI.
Definition: fs_uri.c:1286
int GNUNET_FS_uri_test_sks(const struct GNUNET_FS_Uri *uri)
Is this a namespace URI?
Definition: fs_uri.c:1271
struct GNUNET_FS_Uri * GNUNET_FS_uri_sks_create(const struct GNUNET_CRYPTO_EcdsaPublicKey *ns, const char *id)
Create an SKS URI from a namespace ID and an identifier.
Definition: fs_uri.c:908
int GNUNET_FS_uri_test_chk(const struct GNUNET_FS_Uri *uri)
Is this a file (or directory) URI?
Definition: fs_uri.c:1346
unsigned int GNUNET_FS_uri_ksk_get_keyword_count(const struct GNUNET_FS_Uri *uri)
How many keywords are ANDed in this keyword URI?
Definition: fs_uri.c:711
struct GNUNET_FS_Uri * GNUNET_FS_uri_parse(const char *uri, char **emsg)
Convert a UTF-8 String to a URI.
Definition: fs_uri.c:637
char * GNUNET_FS_uri_ksk_to_string_fancy(const struct GNUNET_FS_Uri *uri)
Convert keyword URI to a human readable format (i.e.
Definition: fs_uri.c:148
struct GNUNET_FS_Uri * GNUNET_FS_uri_loc_get_uri(const struct GNUNET_FS_Uri *uri)
Obtain the URI of the content itself.
Definition: fs_uri.c:843
int GNUNET_FS_uri_to_key(const struct GNUNET_FS_Uri *uri, struct GNUNET_HashCode *key)
Get a unique key from a URI.
Definition: fs_uri.c:96
struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_merge(const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2)
Merge the sets of keywords from two KSK URIs.
Definition: fs_uri.c:931
int GNUNET_FS_uri_loc_get_peer_identity(const struct GNUNET_FS_Uri *uri, struct GNUNET_PeerIdentity *peer)
Obtain the identity of the peer offering the data.
Definition: fs_uri.c:812
void GNUNET_FS_uri_ksk_add_keyword(struct GNUNET_FS_Uri *uri, const char *keyword, int is_mandatory)
Add the given keyword to the set of keywords represented by the URI.
Definition: fs_uri.c:752
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CRYPTO_hash_to_enc(const struct GNUNET_HashCode *block, struct GNUNET_CRYPTO_HashAsciiEncoded *result)
Convert hash to ASCII encoding.
Definition: crypto_hash.c:55
#define GNUNET_CRYPTO_hash_from_string(enc, result)
Convert ASCII encoding back to struct GNUNET_HashCode
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_CRYPTO_PKEY_ASCII_LENGTH
How many characters (without 0-terminator) are our ASCII-encoded public keys (ECDSA/EDDSA/ECDHE).
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
char * GNUNET_CRYPTO_eddsa_public_key_to_string(const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:252
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:358
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_FS_meta_data_iterate(const struct GNUNET_FS_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls)
Iterate over MD entries.
Definition: meta_data.c:418
char * GNUNET_FS_meta_data_get_first_by_types(const struct GNUNET_FS_MetaData *md,...)
Get the first matching MD entry of the given types.
Definition: meta_data.c:456
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using CrockfordBase32.
Definition: strings.c:709
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:789
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
#define max(x, y)
#define DIR_SEPARATOR_STR
Definition: platform.h:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT
Signature by which a peer affirms that it is providing a certain bit of content for use in LOCation U...
struct GNUNET_HashCode key
Hash of the original content, used for encryption.
Definition: fs.h:59
struct GNUNET_HashCode query
Hash of the encrypted content, used for querying.
Definition: fs.h:64
complete information needed to download a file.
Definition: fs_api.h:95
struct ContentHashKey chk
Query and key of the top GNUNET_EC_IBlock.
Definition: fs_api.h:104
uint64_t file_length
Total size of the file in bytes.
Definition: fs_api.h:99
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
Private ECC key encoded for transmission.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
0-terminated ASCII encoding of a struct GNUNET_HashCode.
Meta data to associate with a file, directory or namespace.
Definition: meta_data.c:92
A Universal Resource Identifier (URI), opaque.
Definition: fs_api.h:167
char ** keywords
Keywords start with a '+' if they are mandatory (in which case the '+' is NOT part of the keyword) an...
Definition: fs_api.h:186
union GNUNET_FS_Uri::@49 data
struct GNUNET_FS_Uri::@49::@51 sks
enum GNUNET_FS_UriType type
Type of the URI.
Definition: fs_api.h:171
struct GNUNET_FS_Uri::@49::@50 ksk
struct GNUNET_CRYPTO_EcdsaPublicKey ns
Identifier of the namespace.
Definition: fs_api.h:199
struct Location loc
Information needed to retrieve a file including signed location (identity of a peer) of the content.
Definition: fs_api.h:218
unsigned int keywordCount
Size of the keywords array.
Definition: fs_api.h:191
char * identifier
Human-readable identifier chosen for this entry in the namespace.
Definition: fs_api.h:205
struct FileIdentifier chk
Information needed to retrieve a file (content-hash-key plus file size).
Definition: fs_api.h:212
A 512-bit hashcode.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Structure that defines how the contents of a location URI must be assembled in memory to create or ve...
Definition: fs_uri.c:459
struct GNUNET_TIME_AbsoluteNBO exptime
Expiration time of the offer.
Definition: fs_uri.c:468
struct GNUNET_PeerIdentity peer
Peer offering the file.
Definition: fs_uri.c:478
struct FileIdentifier fi
File being offered.
Definition: fs_uri.c:473
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
What is being signed (rest of this struct).
Definition: fs_uri.c:463
struct GNUNET_TIME_Absolute expirationTime
Time when this location URI expires.
Definition: fs_api.h:127
struct GNUNET_CRYPTO_EddsaSignature contentSignature
Signature over the GNUNET_EC_FileIdentifier, peer identity and expiration time.
Definition: fs_api.h:133
struct FileIdentifier fi
Information about the shared file.
Definition: fs_api.h:117
struct GNUNET_PeerIdentity peer
Identity of the peer sharing the file.
Definition: fs_api.h:122