GNUnet 0.22.2
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
1384const struct GNUNET_HashCode*
1386{
1387 if (GNUNET_FS_URI_CHK != uri->type)
1388 GNUNET_assert (0);
1389
1390 return &(uri->data.chk.chk.key);
1391}
1392
1393
1400int
1402{
1403 return uri->type == GNUNET_FS_URI_LOC;
1404}
1405
1406
1416static void
1417insert_non_mandatory_keyword (const char *s, char **array, int index)
1418{
1419 char *nkword;
1420
1421 GNUNET_asprintf (&nkword,
1422 " %s", /* space to mark as 'non mandatory' */
1423 s);
1424 array[index] = nkword;
1425}
1426
1427
1437static int
1438find_duplicate (const char *s, const char **array, int array_length)
1439{
1440 int j;
1441
1442 for (j = array_length - 1; j >= 0; j--)
1443 if (0 == strcmp (&array[j][1], s))
1444 return GNUNET_YES;
1445 return GNUNET_NO;
1446}
1447
1448
1452static char *
1453normalize_metadata (enum EXTRACTOR_MetaFormat format,
1454 const char *data,
1455 size_t data_len)
1456{
1457 uint8_t *free_str = NULL;
1458 uint8_t *str_to_normalize = (uint8_t *) data;
1459 uint8_t *normalized;
1460 size_t r_len;
1461
1462 if (str_to_normalize == NULL)
1463 return NULL;
1464 /* Don't trust libextractor */
1465 if (format == EXTRACTOR_METAFORMAT_UTF8)
1466 {
1467 free_str = (uint8_t *) u8_check ((const uint8_t *) data, data_len);
1468 if (free_str == NULL)
1469 free_str = NULL;
1470 else
1471 format = EXTRACTOR_METAFORMAT_C_STRING;
1472 }
1473 if (format == EXTRACTOR_METAFORMAT_C_STRING)
1474 {
1475 free_str = u8_strconv_from_encoding (data,
1476 locale_charset (),
1477 iconveh_escape_sequence);
1478 if (free_str == NULL)
1479 return NULL;
1480 }
1481
1482 normalized = u8_tolower (str_to_normalize,
1483 strlen ((char *) str_to_normalize),
1484 NULL,
1485 UNINORM_NFD,
1486 NULL,
1487 &r_len);
1488 /* free_str is allocated by libunistring internally, use free() */
1489 if (free_str != NULL)
1490 free (free_str);
1491 if (normalized != NULL)
1492 {
1493 /* u8_tolower allocates a non-NULL-terminated string! */
1494 free_str = GNUNET_malloc (r_len + 1);
1495 GNUNET_memcpy (free_str, normalized, r_len);
1496 free_str[r_len] = '\0';
1497 free (normalized);
1498 normalized = free_str;
1499 }
1500 return (char *) normalized;
1501}
1502
1503
1508static size_t
1509u8_strcount (const uint8_t *s)
1510{
1511 size_t count;
1512 ucs4_t c;
1513
1514 GNUNET_assert (s != NULL);
1515 if (s[0] == 0)
1516 return 0;
1517 for (count = 0; s != NULL; count++)
1518 s = u8_next (&c, s);
1519 return count - 1;
1520}
1521
1522
1539static int
1540get_keywords_from_parens (const char *s, char **array, int index)
1541{
1542 int count = 0;
1543 char *open_paren;
1544 char *close_paren;
1545 char *ss;
1546 char tmp;
1547
1548 if (NULL == s)
1549 return 0;
1550 ss = GNUNET_strdup (s);
1551 open_paren = ss - 1;
1552 while (NULL != (open_paren = strpbrk (open_paren + 1, "[{(")))
1553 {
1554 int match = 0;
1555
1556 close_paren = strpbrk (open_paren + 1, "]})");
1557 if (NULL == close_paren)
1558 continue;
1559 switch (open_paren[0])
1560 {
1561 case '[':
1562 if (']' == close_paren[0])
1563 match = 1;
1564 break;
1565
1566 case '{':
1567 if ('}' == close_paren[0])
1568 match = 1;
1569 break;
1570
1571 case '(':
1572 if (')' == close_paren[0])
1573 match = 1;
1574 break;
1575
1576 default:
1577 break;
1578 }
1579 if (match && (close_paren - open_paren > 1))
1580 {
1581 tmp = close_paren[0];
1582 close_paren[0] = '\0';
1583 /* Keywords must be at least 3 characters long */
1584 if (u8_strcount ((const uint8_t *) &open_paren[1]) <= 2)
1585 {
1586 close_paren[0] = tmp;
1587 continue;
1588 }
1589 if (NULL != array)
1590 {
1591 char *normalized;
1592 if (GNUNET_NO == find_duplicate ((const char *) &open_paren[1],
1593 (const char **) array,
1594 index + count))
1595 {
1596 insert_non_mandatory_keyword ((const char *) &open_paren[1],
1597 array,
1598 index + count);
1599 count++;
1600 }
1601 normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8,
1602 &open_paren[1],
1603 close_paren - &open_paren[1]);
1604 if (normalized != NULL)
1605 {
1606 if (GNUNET_NO == find_duplicate ((const char *) normalized,
1607 (const char **) array,
1608 index + count))
1609 {
1610 insert_non_mandatory_keyword ((const char *) normalized,
1611 array,
1612 index + count);
1613 count++;
1614 }
1615 GNUNET_free (normalized);
1616 }
1617 }
1618 else
1619 count++;
1620 close_paren[0] = tmp;
1621 }
1622 }
1623 GNUNET_free (ss);
1624 return count;
1625}
1626
1627
1631#define TOKENS "_. /-!?#&+@\"\'\\;:,()[]{}$<>|"
1632
1647static int
1648get_keywords_from_tokens (const char *s, char **array, int index)
1649{
1650 char *p;
1651 char *ss;
1652 int seps = 0;
1653
1654 ss = GNUNET_strdup (s);
1655 for (p = strtok (ss, TOKENS); p != NULL; p = strtok (NULL, TOKENS))
1656 {
1657 /* Keywords must be at least 3 characters long */
1658 if (u8_strcount ((const uint8_t *) p) <= 2)
1659 continue;
1660 if (NULL != array)
1661 {
1662 char *normalized;
1663 if (GNUNET_NO == find_duplicate (p, (const char **) array, index + seps))
1664 {
1665 insert_non_mandatory_keyword (p, array, index + seps);
1666 seps++;
1667 }
1668 normalized =
1669 normalize_metadata (EXTRACTOR_METAFORMAT_UTF8, p, strlen (p));
1670 if (normalized != NULL)
1671 {
1672 if (GNUNET_NO == find_duplicate ((const char *) normalized,
1673 (const char **) array,
1674 index + seps))
1675 {
1676 insert_non_mandatory_keyword ((const char *) normalized,
1677 array,
1678 index + seps);
1679 seps++;
1680 }
1681 GNUNET_free (normalized);
1682 }
1683 }
1684 else
1685 seps++;
1686 }
1687 GNUNET_free (ss);
1688 return seps;
1689}
1690
1691
1692#undef TOKENS
1693
1694
1712static int
1714 const char *plugin_name,
1715 enum EXTRACTOR_MetaType type,
1716 enum EXTRACTOR_MetaFormat format,
1717 const char *data_mime_type,
1718 const char *data,
1719 size_t data_len)
1720{
1721 struct GNUNET_FS_Uri *uri = cls;
1722 char *normalized_data;
1723 const char *sep;
1724
1725 if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1726 (format != EXTRACTOR_METAFORMAT_C_STRING))
1727 return 0;
1728 /* Keywords must be at least 3 characters long
1729 * If given non-utf8 string it will, most likely, find it to be invalid,
1730 * and will return the length of its valid part, skipping the keyword.
1731 * If it does - fix the extractor, not this check!
1732 */if (u8_strcount ((const uint8_t *) data) <= 2)
1733 return 0;
1734 if ((EXTRACTOR_METATYPE_MIMETYPE == type) &&
1735 (NULL != (sep = memchr (data, '/', data_len))) && (sep != data))
1736 {
1737 char *xtra;
1738
1739 GNUNET_asprintf (&xtra, "mimetype:%.*s", (int) (sep - data), data);
1740 if (! find_duplicate (xtra,
1741 (const char **) uri->data.ksk.keywords,
1743 {
1748 }
1749 GNUNET_free (xtra);
1750 }
1751
1752 normalized_data = normalize_metadata (format, data, data_len);
1753 if (! find_duplicate (data,
1754 (const char **) uri->data.ksk.keywords,
1756 {
1761 }
1762 if (NULL != normalized_data)
1763 {
1764 if (! find_duplicate (normalized_data,
1765 (const char **) uri->data.ksk.keywords,
1767 {
1768 insert_non_mandatory_keyword (normalized_data,
1772 }
1773 GNUNET_free (normalized_data);
1774 }
1775 return 0;
1776}
1777
1778
1787struct GNUNET_FS_Uri *
1789 const struct GNUNET_FS_MetaData *md)
1790{
1791 struct GNUNET_FS_Uri *ret;
1792 char *filename;
1793 char *full_name = NULL;
1794 char *ss;
1795 int ent;
1796 int tok_keywords = 0;
1797 int paren_keywords = 0;
1798
1799 if (NULL == md)
1800 return NULL;
1801 ret = GNUNET_new (struct GNUNET_FS_Uri);
1802 ret->type = GNUNET_FS_URI_KSK;
1803 ent = GNUNET_FS_meta_data_iterate (md, NULL, NULL);
1804 if (ent > 0)
1805 {
1807 md,
1809 -1);
1810 if (NULL != full_name)
1811 {
1812 filename = full_name;
1813 while (NULL != (ss = strstr (filename, DIR_SEPARATOR_STR)))
1814 filename = ss + 1;
1815 tok_keywords = get_keywords_from_tokens (filename, NULL, 0);
1816 paren_keywords = get_keywords_from_parens (filename, NULL, 0);
1817 }
1818 /* x3 because there might be a normalized variant of every keyword,
1819 plus theoretically one more for mime... */
1820 ret->data.ksk.keywords =
1821 GNUNET_new_array ((ent + tok_keywords + paren_keywords) * 3, char *);
1823 }
1824 if (tok_keywords > 0)
1825 ret->data.ksk.keywordCount +=
1827 ret->data.ksk.keywords,
1828 ret->data.ksk.keywordCount);
1829 if (paren_keywords > 0)
1830 ret->data.ksk.keywordCount +=
1832 ret->data.ksk.keywords,
1833 ret->data.ksk.keywordCount);
1834 if (ent > 0)
1835 GNUNET_free (full_name);
1836 return ret;
1837}
1838
1839
1844static int
1846{
1847 return(! ((isalnum ((unsigned char) c)) || (c == '-') || (c == '_') ||
1848 (c == '.') || (c == '~')));
1849}
1850
1851
1858static char *
1860{
1861 char **keywords;
1862 unsigned int keywordCount;
1863 size_t n;
1864 char *ret;
1865 unsigned int i;
1866 unsigned int j;
1867 unsigned int wpos;
1868 size_t slen;
1869 const char *keyword;
1870
1871 if (uri->type != GNUNET_FS_URI_KSK)
1872 return NULL;
1875 n = keywordCount + strlen (GNUNET_FS_URI_PREFIX)
1876 + strlen (GNUNET_FS_URI_KSK_INFIX) + 1;
1877 for (i = 0; i < keywordCount; i++)
1878 {
1879 keyword = keywords[i];
1880 slen = strlen (keyword);
1881 n += slen;
1882 for (j = 0; j < slen; j++)
1883 {
1884 if ((j == 0) && (keyword[j] == ' '))
1885 {
1886 n--;
1887 continue; /* skip leading space */
1888 }
1889 if (needs_percent (keyword[j]))
1890 n += 2; /* will use %-encoding */
1891 }
1892 }
1893 ret = GNUNET_malloc (n);
1894 strcpy (ret, GNUNET_FS_URI_PREFIX);
1895 strcat (ret, GNUNET_FS_URI_KSK_INFIX);
1896 wpos = strlen (ret);
1897 for (i = 0; i < keywordCount; i++)
1898 {
1899 keyword = keywords[i];
1900 slen = strlen (keyword);
1901 for (j = 0; j < slen; j++)
1902 {
1903 if ((j == 0) && (keyword[j] == ' '))
1904 continue; /* skip leading space */
1905 if (needs_percent (keyword[j]))
1906 {
1907 sprintf (&ret[wpos], "%%%02X", (unsigned char) keyword[j]);
1908 wpos += 3;
1909 }
1910 else
1911 {
1912 ret[wpos++] = keyword[j];
1913 }
1914 }
1915 if (i != keywordCount - 1)
1916 ret[wpos++] = '+';
1917 }
1918 return ret;
1919}
1920
1921
1928static char *
1930{
1931 char *ret;
1932 char buf[1024];
1933
1934 if (GNUNET_FS_URI_SKS != uri->type)
1935 return NULL;
1936 ret =
1938 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
1939 buf,
1940 sizeof(buf));
1941 GNUNET_assert (NULL != ret);
1942 ret[0] = '\0';
1944 "%s%s%s/%s",
1947 buf,
1949 return ret;
1950}
1951
1952
1959static char *
1961{
1962 const struct FileIdentifier *fi;
1963 char *ret;
1964 struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1965 struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1966
1967 if (uri->type != GNUNET_FS_URI_CHK)
1968 return NULL;
1969 fi = &uri->data.chk;
1970 GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash);
1971 GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash);
1972
1974 "%s%s%s.%s.%llu",
1977 (const char *) &keyhash,
1978 (const char *) &queryhash,
1979 (unsigned long long) GNUNET_ntohll (fi->file_length));
1980 return ret;
1981}
1982
1983
1990static char *
1992{
1993 char *ret;
1994 struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1995 struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1996 char *peer_id;
1997 char peer_sig[SIGNATURE_ASCII_LENGTH + 1];
1998
2001 peer_id =
2004 NULL !=
2006 sizeof(struct GNUNET_CRYPTO_EddsaSignature),
2007 peer_sig,
2008 sizeof(peer_sig)));
2010 "%s%s%s.%s.%llu.%s.%s.%llu",
2013 (const char *) &keyhash,
2014 (const char *) &queryhash,
2015 (unsigned long long) GNUNET_ntohll (
2017 peer_id,
2018 peer_sig,
2019 (unsigned long long)
2021 / 1000000LL);
2023 return ret;
2024}
2025
2026
2033char *
2035{
2036 if (uri == NULL)
2037 {
2038 GNUNET_break (0);
2039 return NULL;
2040 }
2041 switch (uri->type)
2042 {
2043 case GNUNET_FS_URI_KSK:
2044 return uri_ksk_to_string (uri);
2045
2046 case GNUNET_FS_URI_SKS:
2047 return uri_sks_to_string (uri);
2048
2049 case GNUNET_FS_URI_CHK:
2050 return uri_chk_to_string (uri);
2051
2052 case GNUNET_FS_URI_LOC:
2053 return uri_loc_to_string (uri);
2054
2055 default:
2056 GNUNET_break (0);
2057 return NULL;
2058 }
2059}
2060
2061
2062/* 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:1417
static char * uri_chk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a CHK URI to a string.
Definition: fs_uri.c:1960
static char * uri_sks_to_string(const struct GNUNET_FS_Uri *uri)
Convert SKS URI to a string.
Definition: fs_uri.c:1929
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:1509
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:1713
static char * uri_loc_to_string(const struct GNUNET_FS_Uri *uri)
Convert a LOC URI to a string.
Definition: fs_uri.c:1991
static int needs_percent(char c)
In URI-encoding, does the given character need to be encoded using %-encoding?
Definition: fs_uri.c:1845
#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:1540
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:1631
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:1859
#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:1453
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:1648
#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:1438
static int ret
Final status code.
Definition: gnunet-arm.c:93
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:33
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
static char * plugin_name
Name of our plugin.
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 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:201
#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:1401
char * GNUNET_FS_uri_to_string(const struct GNUNET_FS_Uri *uri)
Convert a URI to a UTF-8 String.
Definition: fs_uri.c:2034
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:1788
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
const struct GNUNET_HashCode * GNUNET_FS_uri_chk_get_file_hash(const struct GNUNET_FS_Uri *uri)
What is the hash of the original file's content that this URI refers to?
Definition: fs_uri.c:1385
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:255
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:361
#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:732
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:812
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:640
#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