GNUnet  0.10.x
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 #include "gnunet_fs_service.h"
85 #include "gnunet_signatures.h"
86 #include "fs_api.h"
87 #include <unitypes.h>
88 #include <unicase.h>
89 #include <uniconv.h>
90 #include <unistr.h>
91 #include <unistdio.h>
92 
93 
94 
103 int
105  struct GNUNET_HashCode *key)
106 {
107  switch (uri->type)
108  {
109  case GNUNET_FS_URI_CHK:
110  *key = uri->data.chk.chk.query;
111  return GNUNET_OK;
112  case GNUNET_FS_URI_SKS:
113  GNUNET_CRYPTO_hash (uri->data.sks.identifier,
114  strlen (uri->data.sks.identifier),
115  key);
116  return GNUNET_OK;
117  case GNUNET_FS_URI_KSK:
118  if (uri->data.ksk.keywordCount > 0)
119  {
120  GNUNET_CRYPTO_hash (uri->data.ksk.keywords[0],
121  strlen (uri->data.ksk.keywords[0]),
122  key);
123  return GNUNET_OK;
124  }
125  else
126  {
127  memset (key, 0, sizeof (struct GNUNET_HashCode));
128  return GNUNET_SYSERR;
129  }
130  break;
131  case GNUNET_FS_URI_LOC:
132  GNUNET_CRYPTO_hash (&uri->data.loc.fi,
133  sizeof (struct FileIdentifier) +
134  sizeof (struct GNUNET_PeerIdentity),
135  key);
136  return GNUNET_OK;
137  default:
138  memset (key, 0, sizeof (struct GNUNET_HashCode));
139  return GNUNET_SYSERR;
140  }
141 }
142 
143 
151 char *
153 {
154  size_t n;
155  char *ret;
156  unsigned int i;
157  const char *keyword;
158  char **keywords;
159  unsigned int keywordCount;
160 
161  if ((NULL == uri) || (GNUNET_FS_URI_KSK != uri->type))
162  {
163  GNUNET_break (0);
164  return NULL;
165  }
166  keywords = uri->data.ksk.keywords;
167  keywordCount = uri->data.ksk.keywordCount;
168  n = keywordCount + 1;
169  for (i = 0; i < keywordCount; i++)
170  {
171  keyword = keywords[i];
172  n += strlen (keyword) - 1;
173  if (NULL != strstr (&keyword[1], " "))
174  n += 2;
175  if (keyword[0] == '+')
176  n++;
177  }
178  ret = GNUNET_malloc (n);
179  strcpy (ret, "");
180  for (i = 0; i < keywordCount; i++)
181  {
182  keyword = keywords[i];
183  if (NULL != strstr (&keyword[1], " "))
184  {
185  strcat (ret, "\"");
186  if (keyword[0] == '+')
187  strcat (ret, keyword);
188  else
189  strcat (ret, &keyword[1]);
190  strcat (ret, "\"");
191  }
192  else
193  {
194  if (keyword[0] == '+')
195  strcat (ret, keyword);
196  else
197  strcat (ret, &keyword[1]);
198  }
199  strcat (ret, " ");
200  }
201  return ret;
202 }
203 
204 
215 static char *
216 percent_decode_keyword (const char *in,
217  char **emsg)
218 {
219  char *out;
220  char *ret;
221  unsigned int rpos;
222  unsigned int wpos;
223  unsigned int hx;
224 
225  out = GNUNET_strdup (in);
226  rpos = 0;
227  wpos = 0;
228  while (out[rpos] != '\0')
229  {
230  if (out[rpos] == '%')
231  {
232  if (1 != SSCANF (&out[rpos + 1], "%2X", &hx))
233  {
234  GNUNET_free (out);
235  *emsg = GNUNET_strdup (_(/* xgettext:no-c-format */
236  "Malformed KSK URI (`%' must be followed by HEX number)"));
237  return NULL;
238  }
239  rpos += 3;
240  if (hx == '"')
241  continue; /* skip double quote */
242  out[wpos++] = (char) hx;
243  }
244  else
245  {
246  out[wpos++] = out[rpos++];
247  }
248  }
249  out[wpos] = '\0';
250  if (out[0] == '+')
251  {
252  ret = GNUNET_strdup (out);
253  }
254  else
255  {
256  /* need to prefix with space */
257  ret = GNUNET_malloc (strlen (out) + 2);
258  strcpy (ret, " ");
259  strcat (ret, out);
260  }
261  GNUNET_free (out);
262  return ret;
263 }
264 
265 #define GNUNET_FS_URI_KSK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX
266 
274 static struct GNUNET_FS_Uri *
275 uri_ksk_parse (const char *s,
276  char **emsg)
277 {
278  struct GNUNET_FS_Uri *ret;
279  char **keywords;
280  unsigned int pos;
281  int max;
282  int iret;
283  int i;
284  size_t slen;
285  char *dup;
286  int saw_quote;
287 
288  slen = strlen (s);
289  pos = strlen (GNUNET_FS_URI_KSK_PREFIX);
290  if ((slen <= pos) || (0 != strncmp (s, GNUNET_FS_URI_KSK_PREFIX, pos)))
291  return NULL; /* not KSK URI */
292  if ((s[slen - 1] == '+') || (s[pos] == '+'))
293  {
294  *emsg =
295  GNUNET_strdup (_("Malformed KSK URI (must not begin or end with `+')"));
296  return NULL;
297  }
298  max = 1;
299  saw_quote = 0;
300  for (i = pos; i < slen; i++)
301  {
302  if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
303  {
304  saw_quote = (saw_quote + 1) % 2;
305  i += 3;
306  continue;
307  }
308  if ((s[i] == '+') && (saw_quote == 0))
309  {
310  max++;
311  if (s[i - 1] == '+')
312  {
313  *emsg = GNUNET_strdup (_("Malformed KSK URI (`++' not allowed)"));
314  return NULL;
315  }
316  }
317  }
318  if (saw_quote == 1)
319  {
320  *emsg = GNUNET_strdup (_("Malformed KSK URI (quotes not balanced)"));
321  return NULL;
322  }
323  iret = max;
324  dup = GNUNET_strdup (s);
325  keywords = GNUNET_new_array (max,
326  char *);
327  for (i = slen - 1; i >= (int) pos; i--)
328  {
329  if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
330  {
331  saw_quote = (saw_quote + 1) % 2;
332  continue;
333  }
334  if ((dup[i] == '+') && (saw_quote == 0))
335  {
336  keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg);
337  if (NULL == keywords[max])
338  goto CLEANUP;
339  dup[i] = '\0';
340  }
341  }
342  keywords[--max] = percent_decode_keyword (&dup[pos], emsg);
343  if (NULL == keywords[max])
344  goto CLEANUP;
345  GNUNET_assert (0 == max);
346  GNUNET_free (dup);
347  ret = GNUNET_new (struct GNUNET_FS_Uri);
348  ret->type = GNUNET_FS_URI_KSK;
349  ret->data.ksk.keywordCount = iret;
350  ret->data.ksk.keywords = keywords;
351  return ret;
352 CLEANUP:
353  for (i = 0; i < max; i++)
354  GNUNET_free_non_null (keywords[i]);
355  GNUNET_free (keywords);
356  GNUNET_free (dup);
357  return NULL;
358 }
359 
360 
361 #define GNUNET_FS_URI_SKS_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX
362 
370 static struct GNUNET_FS_Uri *
371 uri_sks_parse (const char *s,
372  char **emsg)
373 {
374  struct GNUNET_FS_Uri *ret;
376  size_t pos;
377  char *end;
378 
379  pos = strlen (GNUNET_FS_URI_SKS_PREFIX);
380  if ((strlen (s) <= pos) || (0 != strncmp (s, GNUNET_FS_URI_SKS_PREFIX, pos)))
381  return NULL; /* not an SKS URI */
382  end = strchr (&s[pos], '/');
383  if ( (NULL == end) ||
384  (GNUNET_OK !=
386  end - &s[pos],
387  &ns,
388  sizeof (ns))) )
389  {
390  *emsg = GNUNET_strdup (_("Malformed SKS URI (wrong syntax)"));
391  return NULL; /* malformed */
392  }
393  end++; /* skip over '/' */
394  ret = GNUNET_new (struct GNUNET_FS_Uri);
395  ret->type = GNUNET_FS_URI_SKS;
396  ret->data.sks.ns = ns;
397  ret->data.sks.identifier = GNUNET_strdup (end);
398  return ret;
399 }
400 
401 #define GNUNET_FS_URI_CHK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX
402 
403 
411 static struct GNUNET_FS_Uri *
412 uri_chk_parse (const char *s,
413  char **emsg)
414 {
415  struct GNUNET_FS_Uri *ret;
416  struct FileIdentifier fi;
417  unsigned int pos;
418  unsigned long long flen;
419  size_t slen;
420  char h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
421  char h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
422 
423  slen = strlen (s);
424  pos = strlen (GNUNET_FS_URI_CHK_PREFIX);
425  if ((slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
426  (0 != strncmp (s, GNUNET_FS_URI_CHK_PREFIX, pos)))
427  return NULL; /* not a CHK URI */
428  if ((s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
429  (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.'))
430  {
431  *emsg = GNUNET_strdup (_("Malformed CHK URI (wrong syntax)"));
432  return NULL;
433  }
434  GNUNET_memcpy (h1, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
435  h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
436  GNUNET_memcpy (h2, &s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)],
437  sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
438  h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
439 
440  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &fi.chk.key)) ||
442  (1 !=
443  SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
444  "%llu", &flen)))
445  {
446  *emsg = GNUNET_strdup (_("Malformed CHK URI (failed to decode CHK)"));
447  return NULL;
448  }
449  fi.file_length = GNUNET_htonll (flen);
450  ret = GNUNET_new (struct GNUNET_FS_Uri);
451  ret->type = GNUNET_FS_URI_CHK;
452  ret->data.chk = fi;
453  return ret;
454 }
455 
456 
464 {
469 
474 
479 
484 
485 };
487 
488 
489 #define GNUNET_FS_URI_LOC_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX
490 
491 #define SIGNATURE_ASCII_LENGTH 103
492 
501 static struct GNUNET_FS_Uri *
502 uri_loc_parse (const char *s,
503  char **emsg)
504 {
505  struct GNUNET_FS_Uri *uri;
506  char h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
507  char h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
508  unsigned int pos;
509  unsigned int npos;
510  unsigned long long exptime;
511  unsigned long long flen;
512  struct GNUNET_TIME_Absolute et;
513  struct GNUNET_CRYPTO_EddsaSignature sig;
514  struct LocUriAssembly ass;
515  size_t slen;
516 
517  slen = strlen (s);
518  pos = strlen (GNUNET_FS_URI_LOC_PREFIX);
519  if ((slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
520  (0 != strncmp (s, GNUNET_FS_URI_LOC_PREFIX, pos)))
521  return NULL; /* not a LOC URI */
522  if ((s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
523  (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.'))
524  {
525  *emsg = GNUNET_strdup (_("LOC URI malformed (wrong syntax)"));
526  return NULL;
527  }
528  GNUNET_memcpy (h1, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
529  h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
530  GNUNET_memcpy (h2, &s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)],
531  sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
532  h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
533 
534  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &ass.fi.chk.key)) ||
536  (1 !=
537  SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
538  "%llu", &flen)))
539  {
540  *emsg = GNUNET_strdup (_("LOC URI malformed (no CHK)"));
541  return NULL;
542  }
543  ass.fi.file_length = GNUNET_htonll (flen);
544 
545  npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2;
546  while ((s[npos] != '\0') && (s[npos] != '.'))
547  npos++;
548  if (s[npos] == '\0')
549  {
550  *emsg = GNUNET_strdup (_("LOC URI malformed (missing LOC)"));
551  goto ERR;
552  }
553  npos++;
554  if ( (strlen (&s[npos]) <= GNUNET_CRYPTO_PKEY_ASCII_LENGTH + 1) ||
555  ('.' != s[npos+GNUNET_CRYPTO_PKEY_ASCII_LENGTH]) )
556  {
557  *emsg =
558  GNUNET_strdup (_("LOC URI malformed (wrong syntax for public key)"));
559  }
560  if (GNUNET_OK !=
563  &ass.peer.public_key))
564  {
565  *emsg =
566  GNUNET_strdup (_("LOC URI malformed (could not decode public key)"));
567  goto ERR;
568  }
570  if (s[npos++] != '.')
571  {
572  *emsg = GNUNET_strdup (_("LOC URI malformed (could not find signature)"));
573  goto ERR;
574  }
575  if ( (strlen (&s[npos]) <= SIGNATURE_ASCII_LENGTH + 1) ||
576  ('.' != s[npos + SIGNATURE_ASCII_LENGTH]) )
577  {
578  *emsg = GNUNET_strdup (_("LOC URI malformed (wrong syntax for signature)"));
579  goto ERR;
580  }
581  if (GNUNET_OK !=
584  &sig,
585  sizeof (struct GNUNET_CRYPTO_EddsaSignature)))
586  {
587  *emsg = GNUNET_strdup (_("LOC URI malformed (could not decode signature)"));
588  goto ERR;
589  }
590  npos += SIGNATURE_ASCII_LENGTH;
591  if (s[npos++] != '.')
592  {
593  *emsg = GNUNET_strdup (_("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.purpose, &sig, &ass.peer.public_key))
609  {
610  *emsg =
611  GNUNET_strdup (_("LOC URI malformed (signature failed validation)"));
612  goto ERR;
613  }
614  uri = GNUNET_new (struct GNUNET_FS_Uri);
615  uri->type = GNUNET_FS_URI_LOC;
616  uri->data.loc.fi = ass.fi;
617  uri->data.loc.peer = ass.peer;
618  uri->data.loc.expirationTime = et;
619  uri->data.loc.contentSignature = sig;
620 
621  return uri;
622 ERR:
623  return NULL;
624 }
625 
626 
634 struct GNUNET_FS_Uri *
636  char **emsg)
637 {
638  struct GNUNET_FS_Uri *ret;
639  char *msg;
640 
641  if (NULL == uri)
642  {
643  GNUNET_break (0);
644  if (NULL != emsg)
645  *emsg = GNUNET_strdup (_("invalid argument"));
646  return NULL;
647  }
648  if (NULL == emsg)
649  emsg = &msg;
650  *emsg = NULL;
651  if ((NULL != (ret = uri_chk_parse (uri, emsg))) ||
652  (NULL != (ret = uri_ksk_parse (uri, emsg))) ||
653  (NULL != (ret = uri_sks_parse (uri, emsg))) ||
654  (NULL != (ret = uri_loc_parse (uri, emsg))))
655  return ret;
656  if (NULL == *emsg)
657  *emsg = GNUNET_strdup (_("Unrecognized URI type"));
658  if (emsg == &msg)
659  GNUNET_free (msg);
660  return NULL;
661 }
662 
663 
669 void
671 {
672  unsigned int i;
673 
674  switch (uri->type)
675  {
676  case GNUNET_FS_URI_KSK:
677  for (i = 0; i < uri->data.ksk.keywordCount; i++)
678  GNUNET_free (uri->data.ksk.keywords[i]);
679  GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, 0);
680  break;
681  case GNUNET_FS_URI_SKS:
682  GNUNET_free (uri->data.sks.identifier);
683  break;
684  case GNUNET_FS_URI_LOC:
685  break;
686  default:
687  /* do nothing */
688  break;
689  }
690  GNUNET_free (uri);
691 }
692 
693 
700 unsigned int
702 {
703  if (uri->type != GNUNET_FS_URI_KSK)
704  return 0;
705  return uri->data.ksk.keywordCount;
706 }
707 
708 
718 int
721  void *iterator_cls)
722 {
723  unsigned int i;
724  char *keyword;
725 
726  if (uri->type != GNUNET_FS_URI_KSK)
727  return -1;
728  if (NULL == iterator)
729  return uri->data.ksk.keywordCount;
730  for (i = 0; i < uri->data.ksk.keywordCount; i++)
731  {
732  keyword = uri->data.ksk.keywords[i];
733  /* first character of keyword indicates
734  * if it is mandatory or not */
735  if (GNUNET_OK != iterator (iterator_cls, &keyword[1], keyword[0] == '+'))
736  return i;
737  }
738  return i;
739 }
740 
741 
750 void
752  const char *keyword,
753  int is_mandatory)
754 {
755  unsigned int i;
756  const char *old;
757  char *n;
758 
760  for (i = 0; i < uri->data.ksk.keywordCount; i++)
761  {
762  old = uri->data.ksk.keywords[i];
763  if (0 == strcmp (&old[1], keyword))
764  return;
765  }
766  GNUNET_asprintf (&n, is_mandatory ? "+%s" : " %s", keyword);
767  GNUNET_array_append (uri->data.ksk.keywords, uri->data.ksk.keywordCount, n);
768 }
769 
770 
778 void
780  const char *keyword)
781 {
782  unsigned int i;
783  char *old;
784 
786  for (i = 0; i < uri->data.ksk.keywordCount; i++)
787  {
788  old = uri->data.ksk.keywords[i];
789  if (0 == strcmp (&old[1], keyword))
790  {
791  uri->data.ksk.keywords[i] =
792  uri->data.ksk.keywords[uri->data.ksk.keywordCount - 1];
793  GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount,
794  uri->data.ksk.keywordCount - 1);
795  GNUNET_free (old);
796  return;
797  }
798  }
799 }
800 
801 
809 int
811  struct GNUNET_PeerIdentity *peer)
812 {
813  if (uri->type != GNUNET_FS_URI_LOC)
814  return GNUNET_SYSERR;
815  *peer = uri->data.loc.peer;
816  return GNUNET_OK;
817 }
818 
819 
828 {
830  return uri->data.loc.expirationTime;
831 }
832 
833 
840 struct GNUNET_FS_Uri *
842 {
843  struct GNUNET_FS_Uri *ret;
844 
845  if (uri->type != GNUNET_FS_URI_LOC)
846  return NULL;
847  ret = GNUNET_new (struct GNUNET_FS_Uri);
848  ret->type = GNUNET_FS_URI_CHK;
849  ret->data.chk = uri->data.loc.fi;
850  return ret;
851 }
852 
853 
866 struct GNUNET_FS_Uri *
867 GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *base_uri,
868  const struct GNUNET_CRYPTO_EddsaPrivateKey *sign_key,
869  struct GNUNET_TIME_Absolute expiration_time)
870 {
871  struct GNUNET_FS_Uri *uri;
872  struct GNUNET_CRYPTO_EddsaPublicKey my_public_key;
873  struct LocUriAssembly ass;
874  struct GNUNET_TIME_Absolute et;
875 
876  if (GNUNET_FS_URI_CHK != base_uri->type)
877  return NULL;
878  /* we round expiration time to full seconds for SKS URIs */
879  et.abs_value_us = (expiration_time.abs_value_us / 1000000LL) * 1000000LL;
881  &my_public_key);
882  ass.purpose.size = htonl (sizeof (struct LocUriAssembly));
885  ass.fi = base_uri->data.chk;
886  ass.peer.public_key = my_public_key;
887  uri = GNUNET_new (struct GNUNET_FS_Uri);
888  uri->type = GNUNET_FS_URI_LOC;
889  uri->data.loc.fi = base_uri->data.chk;
890  uri->data.loc.expirationTime = et;
891  uri->data.loc.peer.public_key = my_public_key;
893  GNUNET_CRYPTO_eddsa_sign (sign_key,
894  &ass.purpose,
895  &uri->data.loc.contentSignature));
896  return uri;
897 }
898 
899 
907 struct 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 
930 struct 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,
955  char *);
956  for (i = 0; i < u1->data.ksk.keywordCount; i++)
957  kl[i] = GNUNET_strdup (u1->data.ksk.keywords[i]);
958  for (i = 0; i < u2->data.ksk.keywordCount; i++)
959  {
960  kp = u2->data.ksk.keywords[i];
961  found = 0;
962  for (j = 0; j < u1->data.ksk.keywordCount; j++)
963  if (0 == strcmp (kp + 1, kl[j] + 1))
964  {
965  found = 1;
966  if (kp[0] == '+')
967  kl[j][0] = '+';
968  break;
969  }
970  if (0 == found)
971  kl[kc++] = GNUNET_strdup (kp);
972  }
973  ret = GNUNET_new (struct GNUNET_FS_Uri);
974  ret->type = GNUNET_FS_URI_KSK;
975  ret->data.ksk.keywordCount = kc;
976  ret->data.ksk.keywords = kl;
977  return ret;
978 }
979 
980 
987 struct GNUNET_FS_Uri *
989 {
990  struct GNUNET_FS_Uri *ret;
991  unsigned int i;
992 
993  if (uri == NULL)
994  return NULL;
995  ret = GNUNET_new (struct GNUNET_FS_Uri);
996  GNUNET_memcpy (ret, uri, sizeof (struct GNUNET_FS_Uri));
997  switch (ret->type)
998  {
999  case GNUNET_FS_URI_KSK:
1000  if (ret->data.ksk.keywordCount >=
1001  GNUNET_MAX_MALLOC_CHECKED / sizeof (char *))
1002  {
1003  GNUNET_break (0);
1004  GNUNET_free (ret);
1005  return NULL;
1006  }
1007  if (ret->data.ksk.keywordCount > 0)
1008  {
1009  ret->data.ksk.keywords
1010  = GNUNET_new_array (ret->data.ksk.keywordCount,
1011  char *);
1012  for (i = 0; i < ret->data.ksk.keywordCount; i++)
1013  ret->data.ksk.keywords[i] = GNUNET_strdup (uri->data.ksk.keywords[i]);
1014  }
1015  else
1016  ret->data.ksk.keywords = NULL; /* just to be sure */
1017  break;
1018  case GNUNET_FS_URI_SKS:
1019  ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier);
1020  break;
1021  case GNUNET_FS_URI_LOC:
1022  break;
1023  default:
1024  break;
1025  }
1026  return ret;
1027 }
1028 
1029 
1047 struct GNUNET_FS_Uri *
1049  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,
1098  char *);
1099  num_Words = 0;
1100  inWord = 0;
1101  pos = searchString;
1102  while ('\0' != *pos)
1103  {
1104  if ((saw_quote == 0) && (isspace ((unsigned char) *pos)))
1105  {
1106  inWord = 0;
1107  *pos = '\0';
1108  }
1109  else if (0 == inWord)
1110  {
1111  keywordarr[num_Words] = pos;
1112  inWord = 1;
1113  ++num_Words;
1114  }
1115  if ('"' == *pos)
1116  saw_quote = (saw_quote + 1) % 2;
1117  pos++;
1118  }
1119  uri =
1121  (const char **) keywordarr);
1122  GNUNET_free (keywordarr);
1123  GNUNET_free (searchString);
1124  return uri;
1125 }
1126 
1127 
1145 struct GNUNET_FS_Uri *
1147  const char **argv)
1148 {
1149  unsigned int i;
1150  struct GNUNET_FS_Uri *uri;
1151  const char *keyword;
1152  char *val;
1153  const char *r;
1154  char *w;
1155  char *emsg;
1156 
1157  if (argc == 0)
1158  return NULL;
1159  /* allow URI to be given as one and only keyword and
1160  * handle accordingly */
1161  emsg = NULL;
1162  if ((argc == 1) && (strlen (argv[0]) > strlen (GNUNET_FS_URI_PREFIX)) &&
1163  (0 ==
1164  strncmp (argv[0], GNUNET_FS_URI_PREFIX, strlen (GNUNET_FS_URI_PREFIX)))
1165  && (NULL != (uri = GNUNET_FS_uri_parse (argv[0], &emsg))))
1166  return uri;
1167  GNUNET_free_non_null (emsg);
1168  uri = GNUNET_new (struct GNUNET_FS_Uri);
1169  uri->type = GNUNET_FS_URI_KSK;
1170  uri->data.ksk.keywordCount = argc;
1171  uri->data.ksk.keywords = GNUNET_new_array (argc,
1172  char *);
1173  for (i = 0; i < argc; i++)
1174  {
1175  keyword = argv[i];
1176  if (keyword[0] == '+')
1177  val = GNUNET_strdup (keyword);
1178  else
1179  GNUNET_asprintf (&val, " %s", keyword);
1180  r = val;
1181  w = val;
1182  while ('\0' != *r)
1183  {
1184  if ('"' == *r)
1185  r++;
1186  else
1187  *(w++) = *(r++);
1188  }
1189  *w = '\0';
1190  uri->data.ksk.keywords[i] = val;
1191  }
1192  return uri;
1193 }
1194 
1195 
1203 int
1205  const struct GNUNET_FS_Uri *u2)
1206 {
1207  int ret;
1208  unsigned int i;
1209  unsigned int j;
1210 
1211  GNUNET_assert (u1 != NULL);
1212  GNUNET_assert (u2 != NULL);
1213  if (u1->type != u2->type)
1214  return GNUNET_NO;
1215  switch (u1->type)
1216  {
1217  case GNUNET_FS_URI_CHK:
1218  if (0 ==
1219  memcmp (&u1->data.chk, &u2->data.chk, sizeof (struct FileIdentifier)))
1220  return GNUNET_YES;
1221  return GNUNET_NO;
1222  case GNUNET_FS_URI_SKS:
1223  if ((0 ==
1224  memcmp (&u1->data.sks.ns, &u2->data.sks.ns,
1225  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) &&
1226  (0 == strcmp (u1->data.sks.identifier, u2->data.sks.identifier)))
1227 
1228  return GNUNET_YES;
1229  return GNUNET_NO;
1230  case GNUNET_FS_URI_KSK:
1231  if (u1->data.ksk.keywordCount != u2->data.ksk.keywordCount)
1232  return GNUNET_NO;
1233  for (i = 0; i < u1->data.ksk.keywordCount; i++)
1234  {
1235  ret = GNUNET_NO;
1236  for (j = 0; j < u2->data.ksk.keywordCount; j++)
1237  {
1238  if (0 == strcmp (u1->data.ksk.keywords[i], u2->data.ksk.keywords[j]))
1239  {
1240  ret = GNUNET_YES;
1241  break;
1242  }
1243  }
1244  if (ret == GNUNET_NO)
1245  return GNUNET_NO;
1246  }
1247  return GNUNET_YES;
1248  case GNUNET_FS_URI_LOC:
1249  if (memcmp
1250  (&u1->data.loc, &u2->data.loc,
1251  sizeof (struct FileIdentifier) +
1252  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) +
1253  sizeof (struct GNUNET_TIME_Absolute) + sizeof (unsigned short) +
1254  sizeof (unsigned short)) != 0)
1255  return GNUNET_NO;
1256  return GNUNET_YES;
1257  default:
1258  return GNUNET_NO;
1259  }
1260 }
1261 
1262 
1269 int
1271 {
1272  return uri->type == GNUNET_FS_URI_SKS;
1273 }
1274 
1275 
1284 int
1287 {
1288  if (!GNUNET_FS_uri_test_sks (uri))
1289  {
1290  GNUNET_break (0);
1291  return GNUNET_SYSERR;
1292  }
1293  *pseudonym = uri->data.sks.ns;
1294  return GNUNET_OK;
1295 }
1296 
1297 
1304 char *
1306 {
1307  if (!GNUNET_FS_uri_test_sks (uri))
1308  {
1309  GNUNET_break (0);
1310  return NULL;
1311  }
1312  return GNUNET_strdup (uri->data.sks.identifier);
1313 }
1314 
1315 
1322 int
1324 {
1325 #if EXTRA_CHECKS
1326  unsigned int i;
1327 
1328  if (uri->type == GNUNET_FS_URI_KSK)
1329  {
1330  for (i=0;i < uri->data.ksk.keywordCount; i++)
1331  GNUNET_assert (uri->data.ksk.keywords[i] != NULL);
1332  }
1333 #endif
1334  return uri->type == GNUNET_FS_URI_KSK;
1335 }
1336 
1337 
1344 int
1346 {
1347  return uri->type == GNUNET_FS_URI_CHK;
1348 }
1349 
1350 
1358 uint64_t
1360 {
1361  switch (uri->type)
1362  {
1363  case GNUNET_FS_URI_CHK:
1364  return GNUNET_ntohll (uri->data.chk.file_length);
1365  case GNUNET_FS_URI_LOC:
1366  return GNUNET_ntohll (uri->data.loc.fi.file_length);
1367  default:
1368  GNUNET_assert (0);
1369  }
1370  return 0; /* unreachable */
1371 }
1372 
1373 
1380 int
1382 {
1383  return uri->type == GNUNET_FS_URI_LOC;
1384 }
1385 
1386 
1396 static void
1398  char **array,
1399  int index)
1400 {
1401  char *nkword;
1402 
1403  GNUNET_asprintf (&nkword,
1404  " %s", /* space to mark as 'non mandatory' */
1405  s);
1406  array[index] = nkword;
1407 }
1408 
1409 
1419 static int
1420 find_duplicate (const char *s,
1421  const char **array,
1422  int array_length)
1423 {
1424  int j;
1425 
1426  for (j = array_length - 1; j >= 0; j--)
1427  if (0 == strcmp (&array[j][1], s))
1428  return GNUNET_YES;
1429  return GNUNET_NO;
1430 }
1431 
1432 
1436 static char *
1438  const char *data,
1439  size_t data_len)
1440 {
1441  uint8_t *free_str = NULL;
1442  uint8_t *str_to_normalize = (uint8_t *) data;
1443  uint8_t *normalized;
1444  size_t r_len;
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
1455  }
1456  if (format == EXTRACTOR_METAFORMAT_C_STRING)
1457  {
1458  free_str = u8_strconv_from_encoding (data, locale_charset (), iconveh_escape_sequence);
1459  if (free_str == NULL)
1460  return NULL;
1461  }
1462 
1463  normalized = u8_tolower (str_to_normalize, strlen ((char *) str_to_normalize), NULL, UNINORM_NFD, NULL, &r_len);
1464  /* free_str is allocated by libunistring internally, use free() */
1465  if (free_str != NULL)
1466  free (free_str);
1467  if (normalized != NULL)
1468  {
1469  /* u8_tolower allocates a non-NULL-terminated string! */
1470  free_str = GNUNET_malloc (r_len + 1);
1471  GNUNET_memcpy (free_str, normalized, r_len);
1472  free_str[r_len] = '\0';
1473  free (normalized);
1474  normalized = free_str;
1475  }
1476  return (char *) normalized;
1477 }
1478 
1479 
1484 static size_t
1485 u8_strcount (const uint8_t *s)
1486 {
1487  size_t count;
1488  ucs4_t c;
1489  GNUNET_assert (s != NULL);
1490  if (s[0] == 0)
1491  return 0;
1492  for (count = 0; s != NULL; count++)
1493  s = u8_next (&c, s);
1494  return count - 1;
1495 }
1496 
1497 
1514 static int
1516  char **array,
1517  int index)
1518 {
1519  int count = 0;
1520  char *open_paren;
1521  char *close_paren;
1522  char *ss;
1523  char tmp;
1524 
1525  if (NULL == s)
1526  return 0;
1527  ss = GNUNET_strdup (s);
1528  open_paren = ss - 1;
1529  while (NULL != (open_paren = strpbrk (open_paren + 1, "[{(")))
1530  {
1531  int match = 0;
1532 
1533  close_paren = strpbrk (open_paren + 1, "]})");
1534  if (NULL == close_paren)
1535  continue;
1536  switch (open_paren[0])
1537  {
1538  case '[':
1539  if (']' == close_paren[0])
1540  match = 1;
1541  break;
1542  case '{':
1543  if ('}' == close_paren[0])
1544  match = 1;
1545  break;
1546  case '(':
1547  if (')' == close_paren[0])
1548  match = 1;
1549  break;
1550  default:
1551  break;
1552  }
1553  if (match && (close_paren - open_paren > 1))
1554  {
1555  tmp = close_paren[0];
1556  close_paren[0] = '\0';
1557  /* Keywords must be at least 3 characters long */
1558  if (u8_strcount ((const uint8_t *) &open_paren[1]) <= 2)
1559  {
1560  close_paren[0] = tmp;
1561  continue;
1562  }
1563  if (NULL != array)
1564  {
1565  char *normalized;
1566  if (GNUNET_NO == find_duplicate ((const char *) &open_paren[1],
1567  (const char **) array, index + count))
1568  {
1569  insert_non_mandatory_keyword ((const char *) &open_paren[1], array,
1570  index + count);
1571  count++;
1572  }
1574  &open_paren[1], close_paren - &open_paren[1]);
1575  if (normalized != NULL)
1576  {
1577  if (GNUNET_NO == find_duplicate ((const char *) normalized,
1578  (const char **) array, index + count))
1579  {
1580  insert_non_mandatory_keyword ((const char *) normalized, array,
1581  index + count);
1582  count++;
1583  }
1584  GNUNET_free (normalized);
1585  }
1586  }
1587  else
1588  count++;
1589  close_paren[0] = tmp;
1590  }
1591  }
1592  GNUNET_free (ss);
1593  return count;
1594 }
1595 
1596 
1600 #define TOKENS "_. /-!?#&+@\"\'\\;:,()[]{}$<>|"
1601 
1616 static int
1618  char **array,
1619  int index)
1620 {
1621  char *p;
1622  char *ss;
1623  int seps = 0;
1624 
1625  ss = GNUNET_strdup (s);
1626  for (p = strtok (ss, TOKENS); p != NULL; p = strtok (NULL, TOKENS))
1627  {
1628  /* Keywords must be at least 3 characters long */
1629  if (u8_strcount ((const uint8_t *) p) <= 2)
1630  continue;
1631  if (NULL != array)
1632  {
1633  char *normalized;
1634  if (GNUNET_NO == find_duplicate (p, (const char **) array, index + seps))
1635  {
1636  insert_non_mandatory_keyword (p, array,
1637  index + seps);
1638  seps++;
1639  }
1641  p, strlen (p));
1642  if (normalized != NULL)
1643  {
1644  if (GNUNET_NO == find_duplicate ((const char *) normalized,
1645  (const char **) array, index + seps))
1646  {
1647  insert_non_mandatory_keyword ((const char *) normalized, array,
1648  index + seps);
1649  seps++;
1650  }
1651  GNUNET_free (normalized);
1652  }
1653  }
1654  else
1655  seps++;
1656  }
1657  GNUNET_free (ss);
1658  return seps;
1659 }
1660 #undef TOKENS
1661 
1662 
1680 static int
1681 gather_uri_data (void *cls, const char *plugin_name,
1682  enum EXTRACTOR_MetaType type,
1683  enum EXTRACTOR_MetaFormat format,
1684  const char *data_mime_type,
1685  const char *data,
1686  size_t data_len)
1687 {
1688  struct GNUNET_FS_Uri *uri = cls;
1689  char *normalized_data;
1690  const char *sep;
1691 
1692  if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1693  (format != EXTRACTOR_METAFORMAT_C_STRING))
1694  return 0;
1695  /* Keywords must be at least 3 characters long
1696  * If given non-utf8 string it will, most likely, find it to be invalid,
1697  * and will return the length of its valid part, skipping the keyword.
1698  * If it does - fix the extractor, not this check!
1699  */
1700  if (u8_strcount ((const uint8_t *) data) <= 2)
1701  return 0;
1702  if ( (EXTRACTOR_METATYPE_MIMETYPE == type) &&
1703  (NULL != (sep = memchr (data, '/', data_len))) &&
1704  (sep != data) )
1705  {
1706  char *xtra;
1707 
1708  GNUNET_asprintf (&xtra,
1709  "mimetype:%.*s",
1710  (int) (sep - data),
1711  data);
1712  if (! find_duplicate (xtra,
1713  (const char **) uri->data.ksk.keywords,
1714  uri->data.ksk.keywordCount))
1715  {
1717  uri->data.ksk.keywords,
1718  uri->data.ksk.keywordCount);
1719  uri->data.ksk.keywordCount++;
1720  }
1721  GNUNET_free (xtra);
1722  }
1723 
1724  normalized_data = normalize_metadata (format, data, data_len);
1725  if (! find_duplicate (data,
1726  (const char **) uri->data.ksk.keywords,
1727  uri->data.ksk.keywordCount))
1728  {
1730  uri->data.ksk.keywords, uri->data.ksk.keywordCount);
1731  uri->data.ksk.keywordCount++;
1732  }
1733  if (NULL != normalized_data)
1734  {
1735  if (! find_duplicate (normalized_data,
1736  (const char **) uri->data.ksk.keywords,
1737  uri->data.ksk.keywordCount))
1738  {
1739  insert_non_mandatory_keyword (normalized_data,
1740  uri->data.ksk.keywords, uri->data.ksk.keywordCount);
1741  uri->data.ksk.keywordCount++;
1742  }
1743  GNUNET_free (normalized_data);
1744  }
1745  return 0;
1746 }
1747 
1748 
1757 struct GNUNET_FS_Uri *
1759 {
1760  struct GNUNET_FS_Uri *ret;
1761  char *filename;
1762  char *full_name = NULL;
1763  char *ss;
1764  int ent;
1765  int tok_keywords = 0;
1766  int paren_keywords = 0;
1767 
1768  if (NULL == md)
1769  return NULL;
1770  ret = GNUNET_new (struct GNUNET_FS_Uri);
1771  ret->type = GNUNET_FS_URI_KSK;
1772  ent = GNUNET_CONTAINER_meta_data_iterate (md, NULL, NULL);
1773  if (ent > 0)
1774  {
1777  if (NULL != full_name)
1778  {
1779  filename = full_name;
1780  while (NULL != (ss = strstr (filename, DIR_SEPARATOR_STR)))
1781  filename = ss + 1;
1782  tok_keywords = get_keywords_from_tokens (filename, NULL, 0);
1783  paren_keywords = get_keywords_from_parens (filename, NULL, 0);
1784  }
1785  /* x3 because there might be a normalized variant of every keyword,
1786  plus theoretically one more for mime... */
1787  ret->data.ksk.keywords
1788  = GNUNET_new_array ((ent + tok_keywords + paren_keywords) * 3,
1789  char *);
1791  }
1792  if (tok_keywords > 0)
1793  ret->data.ksk.keywordCount += get_keywords_from_tokens (filename,
1794  ret->data.ksk.keywords,
1795  ret->data.ksk.keywordCount);
1796  if (paren_keywords > 0)
1797  ret->data.ksk.keywordCount += get_keywords_from_parens (filename,
1798  ret->data.ksk.keywords,
1799  ret->data.ksk.keywordCount);
1800  if (ent > 0)
1801  GNUNET_free_non_null (full_name);
1802  return ret;
1803 }
1804 
1805 
1810 static int
1812 {
1813  return (!
1814  ((isalnum ((unsigned char) c)) || (c == '-') || (c == '_') ||
1815  (c == '.') || (c == '~')));
1816 }
1817 
1818 
1825 static char *
1827 {
1828  char **keywords;
1829  unsigned int keywordCount;
1830  size_t n;
1831  char *ret;
1832  unsigned int i;
1833  unsigned int j;
1834  unsigned int wpos;
1835  size_t slen;
1836  const char *keyword;
1837 
1838  if (uri->type != GNUNET_FS_URI_KSK)
1839  return NULL;
1840  keywords = uri->data.ksk.keywords;
1841  keywordCount = uri->data.ksk.keywordCount;
1842  n = keywordCount + strlen (GNUNET_FS_URI_PREFIX) +
1843  strlen (GNUNET_FS_URI_KSK_INFIX) + 1;
1844  for (i = 0; i < keywordCount; i++)
1845  {
1846  keyword = keywords[i];
1847  slen = strlen (keyword);
1848  n += slen;
1849  for (j = 0; j < slen; j++)
1850  {
1851  if ((j == 0) && (keyword[j] == ' '))
1852  {
1853  n--;
1854  continue; /* skip leading space */
1855  }
1856  if (needs_percent (keyword[j]))
1857  n += 2; /* will use %-encoding */
1858  }
1859  }
1860  ret = GNUNET_malloc (n);
1861  strcpy (ret, GNUNET_FS_URI_PREFIX);
1862  strcat (ret, GNUNET_FS_URI_KSK_INFIX);
1863  wpos = strlen (ret);
1864  for (i = 0; i < keywordCount; i++)
1865  {
1866  keyword = keywords[i];
1867  slen = strlen (keyword);
1868  for (j = 0; j < slen; j++)
1869  {
1870  if ((j == 0) && (keyword[j] == ' '))
1871  continue; /* skip leading space */
1872  if (needs_percent (keyword[j]))
1873  {
1874  sprintf (&ret[wpos], "%%%02X", (unsigned char) keyword[j]);
1875  wpos += 3;
1876  }
1877  else
1878  {
1879  ret[wpos++] = keyword[j];
1880  }
1881  }
1882  if (i != keywordCount - 1)
1883  ret[wpos++] = '+';
1884  }
1885  return ret;
1886 }
1887 
1888 
1895 static char *
1897 {
1898  char *ret;
1899  char buf[1024];
1900 
1901  if (GNUNET_FS_URI_SKS != uri->type)
1902  return NULL;
1903  ret = GNUNET_STRINGS_data_to_string (&uri->data.sks.ns,
1904  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
1905  buf,
1906  sizeof (buf));
1907  GNUNET_assert (NULL != ret);
1908  ret[0] = '\0';
1909  GNUNET_asprintf (&ret, "%s%s%s/%s", GNUNET_FS_URI_PREFIX,
1911  uri->data.sks.identifier);
1912  return ret;
1913 }
1914 
1915 
1922 static char *
1924 {
1925  const struct FileIdentifier *fi;
1926  char *ret;
1927  struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1928  struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1929 
1930  if (uri->type != GNUNET_FS_URI_CHK)
1931  return NULL;
1932  fi = &uri->data.chk;
1933  GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash);
1934  GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash);
1935 
1936  GNUNET_asprintf (&ret, "%s%s%s.%s.%llu", GNUNET_FS_URI_PREFIX,
1937  GNUNET_FS_URI_CHK_INFIX, (const char *) &keyhash,
1938  (const char *) &queryhash, GNUNET_ntohll (fi->file_length));
1939  return ret;
1940 }
1941 
1942 
1949 static char *
1951 {
1952  char *ret;
1953  struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1954  struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1955  char *peer_id;
1956  char peer_sig[SIGNATURE_ASCII_LENGTH + 1];
1957 
1958  GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.key, &keyhash);
1959  GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.query, &queryhash);
1960  peer_id =
1962  GNUNET_assert (NULL !=
1964  sizeof (struct GNUNET_CRYPTO_EddsaSignature),
1965  peer_sig,
1966  sizeof (peer_sig)));
1967  GNUNET_asprintf (&ret,
1968  "%s%s%s.%s.%llu.%s.%s.%llu", GNUNET_FS_URI_PREFIX,
1969  GNUNET_FS_URI_LOC_INFIX, (const char *) &keyhash,
1970  (const char *) &queryhash,
1971  (unsigned long long) GNUNET_ntohll (uri->data.loc.
1972  fi.file_length),
1973  peer_id,
1974  peer_sig,
1975  (unsigned long long) uri->data.loc.expirationTime.abs_value_us / 1000000LL);
1976  GNUNET_free (peer_id);
1977  return ret;
1978 }
1979 
1980 
1987 char *
1989 {
1990  if (uri == NULL)
1991  {
1992  GNUNET_break (0);
1993  return NULL;
1994  }
1995  switch (uri->type)
1996  {
1997  case GNUNET_FS_URI_KSK:
1998  return uri_ksk_to_string (uri);
1999  case GNUNET_FS_URI_SKS:
2000  return uri_sks_to_string (uri);
2001  case GNUNET_FS_URI_CHK:
2002  return uri_chk_to_string (uri);
2003  case GNUNET_FS_URI_LOC:
2004  return uri_loc_to_string (uri);
2005  default:
2006  GNUNET_break (0);
2007  return NULL;
2008  }
2009 }
2010 
2011 /* end of fs_uri.c */
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:810
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
#define GNUNET_FS_URI_KSK_PREFIX
Definition: fs_uri.c:265
#define GNUNET_FS_URI_SKS_INFIX
int GNUNET_FS_uri_test_ksk(const struct GNUNET_FS_Uri *uri)
Is this a keyword URI?
Definition: fs_uri.c:1323
struct ContentHashKey chk
Query and key of the top GNUNET_EC_IBlock.
Definition: fs_api.h:104
EXTRACTOR_MetaFormat
Format in which the extracted meta data is presented.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_PeerIdentity peer
Peer offering the file.
Definition: fs_uri.c:483
struct FileIdentifier chk
Information needed to retrieve a file (content-hash-key plus file size).
Definition: fs_api.h:215
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:827
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
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:1146
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:867
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:751
static char * uri_chk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a CHK URI to a string.
Definition: fs_uri.c:1923
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
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:635
static struct GNUNET_FS_Uri * uri_loc_parse(const char *s, char **emsg)
Parse a LOC URI.
Definition: fs_uri.c:502
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:1485
static void insert_non_mandatory_keyword(const char *s, char **array, int index)
Add a keyword as non-mandatory (with &#39; &#39;-prefix) to the given keyword list at offset &#39;index&#39;...
Definition: fs_uri.c:1397
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_TIME_AbsoluteNBO exptime
Expiration time of the offer.
Definition: fs_uri.c:473
int(* GNUNET_FS_KeywordIterator)(void *cls, const char *keyword, int is_mandatory)
Iterator over keywords.
static char * uri_ksk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a KSK URI to a string.
Definition: fs_uri.c:1826
static struct GNUNET_FS_Uri * uri_ksk_parse(const char *s, char **emsg)
Parse a KSK URI.
Definition: fs_uri.c:275
int GNUNET_CRYPTO_eddsa_sign(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:989
Keyword search key (query with keywords).
Definition: fs_api.h:156
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:216
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
0-terminated, UTF-8 encoded string.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:1617
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:152
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
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:1204
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static char * uri_sks_to_string(const struct GNUNET_FS_Uri *uri)
Convert SKS URI to a string.
Definition: fs_uri.c:1896
struct GNUNET_PeerIdentity peer
Identity of the peer sharing the file.
Definition: fs_api.h:123
int GNUNET_FS_uri_test_sks(const struct GNUNET_FS_Uri *uri)
Is this a namespace URI?
Definition: fs_uri.c:1270
EXTRACTOR_MetaType
Enumeration defining various sources of keywords.
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:1285
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
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
uint64_t abs_value_us
The actual value.
struct GNUNET_FS_Uri * GNUNET_FS_uri_dup(const struct GNUNET_FS_Uri *uri)
Duplicate URI.
Definition: fs_uri.c:988
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
char * GNUNET_CONTAINER_meta_data_get_first_by_types(const struct GNUNET_CONTAINER_MetaData *md,...)
Get the first matching MD entry of the given types.
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:104
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
int GNUNET_FS_uri_test_loc(const struct GNUNET_FS_Uri *uri)
Is this a location URI?
Definition: fs_uri.c:1381
char * GNUNET_FS_uri_to_string(const struct GNUNET_FS_Uri *uri)
Convert a URI to a UTF-8 String.
Definition: fs_uri.c:1988
static struct GNUNET_FS_Uri * uri_sks_parse(const char *s, char **emsg)
Parse an SKS URI.
Definition: fs_uri.c:371
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 &#39;+&#39;-mandatory prefix ...
Definition: fs_uri.c:1420
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
#define GNUNET_CRYPTO_PKEY_ASCII_LENGTH
How many characters (without 0-terminator) are our ASCII-encoded public keys (ECDSA/EDDSA/ECDHE).
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
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:719
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
Meta data to associate with a file, directory or namespace.
#define GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT
Signature by which a peer affirms that it is providing a certain bit of content (used in LOCation URI...
char ** keywords
Keywords start with a &#39;+&#39; if they are mandatory (in which case the &#39;+&#39; is NOT part of the keyword) an...
Definition: fs_api.h:188
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
What is being signed (rest of this struct).
Definition: fs_uri.c:468
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_memcpy(dst, src, n)
int GNUNET_CRYPTO_eddsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:1116
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
struct GNUNET_FS_Uri::@16::@17 ksk
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:367
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:1681
struct GNUNET_HashCode query
Hash of the encrypted content, used for querying.
Definition: fs.h:63
union GNUNET_FS_Uri::@16 data
#define GNUNET_FS_URI_CHK_INFIX
static char buf[2048]
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static char * filename
complete information needed to download a file.
Definition: fs_api.h:93
static char * plugin_name
Solver plugin name as string.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
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:1515
void GNUNET_FS_uri_destroy(struct GNUNET_FS_Uri *uri)
Free URI.
Definition: fs_uri.c:670
A 512-bit hashcode.
unsigned int keywordCount
Size of the keywords array.
Definition: fs_api.h:193
int GNUNET_FS_uri_test_chk(const struct GNUNET_FS_Uri *uri)
Is this a file (or directory) URI?
Definition: fs_uri.c:1345
#define TOKENS
Where to break up keywords.
Definition: fs_uri.c:1600
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
Content-hash-key (simple file).
Definition: fs_api.h:146
struct FileIdentifier fi
File being offered.
Definition: fs_uri.c:478
struct GNUNET_HashCode key
The key used in the DHT.
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:69
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static struct GNUNET_FS_Uri * uri_chk_parse(const char *s, char **emsg)
Parse a CHK URI.
Definition: fs_uri.c:412
#define GNUNET_FS_URI_SKS_PREFIX
Definition: fs_uri.c:361
struct GNUNET_TIME_Absolute expirationTime
Time when this location URI expires.
Definition: fs_api.h:128
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
enum GNUNET_FS_UriType type
Type of the URI.
Definition: fs_api.h:173
#define GNUNET_FS_URI_KSK_INFIX
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
an ECC signature using EdDSA.
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:272
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:1048
0-terminated ASCII encoding of a struct GNUNET_HashCode.
Signed key space (file in namespace).
Definition: fs_api.h:151
struct GNUNET_HashCode key
Hash of the original content, used for encryption.
Definition: fs.h:58
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_meta_data(const struct GNUNET_CONTAINER_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:1758
Private ECC key encoded for transmission.
int 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:501
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
struct GNUNET_FS_Uri::@16::@18 sks
The identity of the host (wraps the signing key of the peer).
#define SSCANF
Definition: plibc.h:691
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:1359
shared definitions for the FS library
A Universal Resource Identifier (URI), opaque.
Definition: fs_api.h:168
#define GNUNET_FS_URI_PREFIX
uint64_t file_length
Total size of the file in bytes.
Definition: fs_api.h:99
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
struct GNUNET_CRYPTO_EddsaSignature contentSignature
Signature over the GNUNET_EC_FileIdentifier, peer identity and expiration time.
Definition: fs_api.h:134
struct FileIdentifier fi
Information about the shared file.
Definition: fs_api.h:118
int GNUNET_CONTAINER_meta_data_iterate(const struct GNUNET_CONTAINER_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls)
Iterate over MD entries.
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:841
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:701
Location (chk with identity of hosting peer).
Definition: fs_api.h:161
struct Location loc
Information needed to retrieve a file including signed location (identity of a peer) of the content...
Definition: fs_api.h:221
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
static int needs_percent(char c)
In URI-encoding, does the given character need to be encoded using %-encoding?
Definition: fs_uri.c:1811
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
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:1305
static char * normalize_metadata(enum EXTRACTOR_MetaFormat format, const char *data, size_t data_len)
FIXME: comment.
Definition: fs_uri.c:1437
#define SIGNATURE_ASCII_LENGTH
Definition: fs_uri.c:491
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:779
#define DIR_SEPARATOR_STR
Definition: plibc.h:632
#define GNUNET_FS_URI_LOC_PREFIX
Definition: fs_uri.c:489
#define GNUNET_FS_URI_LOC_INFIX
#define GNUNET_FS_URI_CHK_PREFIX
Definition: fs_uri.c:401
uint32_t data
The data value.
static char * uri_loc_to_string(const struct GNUNET_FS_Uri *uri)
Convert a LOC URI to a string.
Definition: fs_uri.c:1950
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:654
#define GNUNET_CRYPTO_hash_from_string(enc, result)
Convert ASCII encoding back to struct GNUNET_HashCode
#define GNUNET_malloc(size)
Wrapper around malloc.
int 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:1021
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:924
Structure that defines how the contents of a location URI must be assembled in memory to create or ve...
Definition: fs_uri.c:463
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
static char * pseudonym
Command-line option identifying the pseudonym to use for the publication.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...