GNUnet  0.19.4
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 
95 int
97  struct GNUNET_HashCode *key)
98 {
99  switch (uri->type)
100  {
101  case GNUNET_FS_URI_CHK:
102  *key = uri->data.chk.chk.query;
103  return GNUNET_OK;
104 
105  case GNUNET_FS_URI_SKS:
106  GNUNET_CRYPTO_hash (uri->data.sks.identifier,
107  strlen (uri->data.sks.identifier),
108  key);
109  return GNUNET_OK;
110 
111  case GNUNET_FS_URI_KSK:
112  if (uri->data.ksk.keywordCount > 0)
113  {
114  GNUNET_CRYPTO_hash (uri->data.ksk.keywords[0],
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 
126  case GNUNET_FS_URI_LOC:
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 
147 char *
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 
211 static char *
212 percent_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 
271 static struct GNUNET_FS_Uri *
272 uri_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++)
349  GNUNET_free (keywords[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 
365 static struct GNUNET_FS_Uri *
366 uri_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 
405 static struct GNUNET_FS_Uri *
406 uri_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 
473  struct FileIdentifier fi;
474 
478  struct GNUNET_PeerIdentity peer;
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 
495 static struct GNUNET_FS_Uri *
496 uri_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;
506  struct GNUNET_CRYPTO_EddsaSignature sig;
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  }
589  npos += SIGNATURE_ASCII_LENGTH;
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;
620  uri->data.loc.expirationTime = et;
621  uri->data.loc.contentSignature = sig;
622 
623  return uri;
624  ERR:
625  return NULL;
626 }
627 
628 
636 struct GNUNET_FS_Uri *
637 GNUNET_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;
655  GNUNET_free (msg);
656  if (NULL != (ret = uri_ksk_parse (uri, &msg)))
657  return ret;
658  GNUNET_free (msg);
659  if (NULL != (ret = uri_sks_parse (uri, &msg)))
660  return ret;
661  GNUNET_free (msg);
662  if (NULL != (ret = uri_loc_parse (uri, &msg)))
663  return ret;
664  GNUNET_free (msg);
665  if (NULL != emsg)
666  *emsg = GNUNET_strdup (_ ("Unrecognized URI type"));
667  return NULL;
668 }
669 
670 
676 void
678 {
679  unsigned int i;
680 
681  switch (uri->type)
682  {
683  case GNUNET_FS_URI_KSK:
684  for (i = 0; i < uri->data.ksk.keywordCount; i++)
685  GNUNET_free (uri->data.ksk.keywords[i]);
686  GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, 0);
687  break;
688 
689  case GNUNET_FS_URI_SKS:
690  GNUNET_free (uri->data.sks.identifier);
691  break;
692 
693  case GNUNET_FS_URI_LOC:
694  break;
695 
696  default:
697  /* do nothing */
698  break;
699  }
700  GNUNET_free (uri);
701 }
702 
703 
710 unsigned int
712 {
713  if (uri->type != GNUNET_FS_URI_KSK)
714  return 0;
715  return uri->data.ksk.keywordCount;
716 }
717 
718 
719 int
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 
751 void
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);
768  GNUNET_array_append (uri->data.ksk.keywords, uri->data.ksk.keywordCount, n);
769 }
770 
771 
779 void
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] =
793  uri->data.ksk.keywords[uri->data.ksk.keywordCount - 1];
794  GNUNET_array_grow (uri->data.ksk.keywords,
795  uri->data.ksk.keywordCount,
796  uri->data.ksk.keywordCount - 1);
797  GNUNET_free (old);
798  return;
799  }
800  }
801 }
802 
803 
811 int
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 
842 struct 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 
868 struct GNUNET_FS_Uri *
869 GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *base_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;
891  uri->data.loc.expirationTime = et;
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 
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, 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 
986 struct 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  {
998  case GNUNET_FS_URI_KSK:
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 
1048 struct GNUNET_FS_Uri *
1049 GNUNET_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 
1143 struct GNUNET_FS_Uri *
1144 GNUNET_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 
1200 int
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 
1270 int
1272 {
1273  return uri->type == GNUNET_FS_URI_SKS;
1274 }
1275 
1276 
1285 int
1288 {
1289  if (! GNUNET_FS_uri_test_sks (uri))
1290  {
1291  GNUNET_break (0);
1292  return GNUNET_SYSERR;
1293  }
1294  *pseudonym = uri->data.sks.ns;
1295  return GNUNET_OK;
1296 }
1297 
1298 
1305 char *
1307 {
1308  if (! GNUNET_FS_uri_test_sks (uri))
1309  {
1310  GNUNET_break (0);
1311  return NULL;
1312  }
1313  return GNUNET_strdup (uri->data.sks.identifier);
1314 }
1315 
1316 
1323 int
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 
1345 int
1347 {
1348  return uri->type == GNUNET_FS_URI_CHK;
1349 }
1350 
1351 
1359 uint64_t
1361 {
1362  switch (uri->type)
1363  {
1364  case GNUNET_FS_URI_CHK:
1365  return GNUNET_ntohll (uri->data.chk.file_length);
1366 
1367  case GNUNET_FS_URI_LOC:
1368  return GNUNET_ntohll (uri->data.loc.fi.file_length);
1369 
1370  default:
1371  GNUNET_assert (0);
1372  }
1373  return 0; /* unreachable */
1374 }
1375 
1376 
1383 int
1385 {
1386  return uri->type == GNUNET_FS_URI_LOC;
1387 }
1388 
1389 
1399 static void
1400 insert_non_mandatory_keyword (const char *s, char **array, int index)
1401 {
1402  char *nkword;
1403 
1404  GNUNET_asprintf (&nkword,
1405  " %s", /* space to mark as 'non mandatory' */
1406  s);
1407  array[index] = nkword;
1408 }
1409 
1410 
1420 static int
1421 find_duplicate (const char *s, const char **array, int array_length)
1422 {
1423  int j;
1424 
1425  for (j = array_length - 1; j >= 0; j--)
1426  if (0 == strcmp (&array[j][1], s))
1427  return GNUNET_YES;
1428  return GNUNET_NO;
1429 }
1430 
1431 
1435 static char *
1436 normalize_metadata (enum EXTRACTOR_MetaFormat format,
1437  const char *data,
1438  size_t data_len)
1439 {
1440  uint8_t *free_str = NULL;
1441  uint8_t *str_to_normalize = (uint8_t *) data;
1442  uint8_t *normalized;
1443  size_t r_len;
1444 
1445  if (str_to_normalize == NULL)
1446  return NULL;
1447  /* Don't trust libextractor */
1448  if (format == EXTRACTOR_METAFORMAT_UTF8)
1449  {
1450  free_str = (uint8_t *) u8_check ((const uint8_t *) data, data_len);
1451  if (free_str == NULL)
1452  free_str = NULL;
1453  else
1454  format = EXTRACTOR_METAFORMAT_C_STRING;
1455  }
1456  if (format == EXTRACTOR_METAFORMAT_C_STRING)
1457  {
1458  free_str = u8_strconv_from_encoding (data,
1459  locale_charset (),
1460  iconveh_escape_sequence);
1461  if (free_str == NULL)
1462  return NULL;
1463  }
1464 
1465  normalized = u8_tolower (str_to_normalize,
1466  strlen ((char *) str_to_normalize),
1467  NULL,
1468  UNINORM_NFD,
1469  NULL,
1470  &r_len);
1471  /* free_str is allocated by libunistring internally, use free() */
1472  if (free_str != NULL)
1473  free (free_str);
1474  if (normalized != NULL)
1475  {
1476  /* u8_tolower allocates a non-NULL-terminated string! */
1477  free_str = GNUNET_malloc (r_len + 1);
1478  GNUNET_memcpy (free_str, normalized, r_len);
1479  free_str[r_len] = '\0';
1480  free (normalized);
1481  normalized = free_str;
1482  }
1483  return (char *) normalized;
1484 }
1485 
1486 
1491 static size_t
1492 u8_strcount (const uint8_t *s)
1493 {
1494  size_t count;
1495  ucs4_t c;
1496 
1497  GNUNET_assert (s != NULL);
1498  if (s[0] == 0)
1499  return 0;
1500  for (count = 0; s != NULL; count++)
1501  s = u8_next (&c, s);
1502  return count - 1;
1503 }
1504 
1505 
1522 static int
1523 get_keywords_from_parens (const char *s, char **array, int index)
1524 {
1525  int count = 0;
1526  char *open_paren;
1527  char *close_paren;
1528  char *ss;
1529  char tmp;
1530 
1531  if (NULL == s)
1532  return 0;
1533  ss = GNUNET_strdup (s);
1534  open_paren = ss - 1;
1535  while (NULL != (open_paren = strpbrk (open_paren + 1, "[{(")))
1536  {
1537  int match = 0;
1538 
1539  close_paren = strpbrk (open_paren + 1, "]})");
1540  if (NULL == close_paren)
1541  continue;
1542  switch (open_paren[0])
1543  {
1544  case '[':
1545  if (']' == close_paren[0])
1546  match = 1;
1547  break;
1548 
1549  case '{':
1550  if ('}' == close_paren[0])
1551  match = 1;
1552  break;
1553 
1554  case '(':
1555  if (')' == close_paren[0])
1556  match = 1;
1557  break;
1558 
1559  default:
1560  break;
1561  }
1562  if (match && (close_paren - open_paren > 1))
1563  {
1564  tmp = close_paren[0];
1565  close_paren[0] = '\0';
1566  /* Keywords must be at least 3 characters long */
1567  if (u8_strcount ((const uint8_t *) &open_paren[1]) <= 2)
1568  {
1569  close_paren[0] = tmp;
1570  continue;
1571  }
1572  if (NULL != array)
1573  {
1574  char *normalized;
1575  if (GNUNET_NO == find_duplicate ((const char *) &open_paren[1],
1576  (const char **) array,
1577  index + count))
1578  {
1579  insert_non_mandatory_keyword ((const char *) &open_paren[1],
1580  array,
1581  index + count);
1582  count++;
1583  }
1584  normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8,
1585  &open_paren[1],
1586  close_paren - &open_paren[1]);
1587  if (normalized != NULL)
1588  {
1589  if (GNUNET_NO == find_duplicate ((const char *) normalized,
1590  (const char **) array,
1591  index + count))
1592  {
1593  insert_non_mandatory_keyword ((const char *) normalized,
1594  array,
1595  index + count);
1596  count++;
1597  }
1598  GNUNET_free (normalized);
1599  }
1600  }
1601  else
1602  count++;
1603  close_paren[0] = tmp;
1604  }
1605  }
1606  GNUNET_free (ss);
1607  return count;
1608 }
1609 
1610 
1614 #define TOKENS "_. /-!?#&+@\"\'\\;:,()[]{}$<>|"
1615 
1630 static int
1631 get_keywords_from_tokens (const char *s, char **array, int index)
1632 {
1633  char *p;
1634  char *ss;
1635  int seps = 0;
1636 
1637  ss = GNUNET_strdup (s);
1638  for (p = strtok (ss, TOKENS); p != NULL; p = strtok (NULL, TOKENS))
1639  {
1640  /* Keywords must be at least 3 characters long */
1641  if (u8_strcount ((const uint8_t *) p) <= 2)
1642  continue;
1643  if (NULL != array)
1644  {
1645  char *normalized;
1646  if (GNUNET_NO == find_duplicate (p, (const char **) array, index + seps))
1647  {
1648  insert_non_mandatory_keyword (p, array, index + seps);
1649  seps++;
1650  }
1651  normalized =
1652  normalize_metadata (EXTRACTOR_METAFORMAT_UTF8, p, strlen (p));
1653  if (normalized != NULL)
1654  {
1655  if (GNUNET_NO == find_duplicate ((const char *) normalized,
1656  (const char **) array,
1657  index + seps))
1658  {
1659  insert_non_mandatory_keyword ((const char *) normalized,
1660  array,
1661  index + seps);
1662  seps++;
1663  }
1664  GNUNET_free (normalized);
1665  }
1666  }
1667  else
1668  seps++;
1669  }
1670  GNUNET_free (ss);
1671  return seps;
1672 }
1673 
1674 
1675 #undef TOKENS
1676 
1677 
1695 static int
1696 gather_uri_data (void *cls,
1697  const char *plugin_name,
1698  enum EXTRACTOR_MetaType type,
1699  enum EXTRACTOR_MetaFormat format,
1700  const char *data_mime_type,
1701  const char *data,
1702  size_t data_len)
1703 {
1704  struct GNUNET_FS_Uri *uri = cls;
1705  char *normalized_data;
1706  const char *sep;
1707 
1708  if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1709  (format != EXTRACTOR_METAFORMAT_C_STRING))
1710  return 0;
1711  /* Keywords must be at least 3 characters long
1712  * If given non-utf8 string it will, most likely, find it to be invalid,
1713  * and will return the length of its valid part, skipping the keyword.
1714  * If it does - fix the extractor, not this check!
1715  */if (u8_strcount ((const uint8_t *) data) <= 2)
1716  return 0;
1717  if ((EXTRACTOR_METATYPE_MIMETYPE == type) &&
1718  (NULL != (sep = memchr (data, '/', data_len))) && (sep != data))
1719  {
1720  char *xtra;
1721 
1722  GNUNET_asprintf (&xtra, "mimetype:%.*s", (int) (sep - data), data);
1723  if (! find_duplicate (xtra,
1724  (const char **) uri->data.ksk.keywords,
1725  uri->data.ksk.keywordCount))
1726  {
1728  uri->data.ksk.keywords,
1729  uri->data.ksk.keywordCount);
1730  uri->data.ksk.keywordCount++;
1731  }
1732  GNUNET_free (xtra);
1733  }
1734 
1735  normalized_data = normalize_metadata (format, data, data_len);
1736  if (! find_duplicate (data,
1737  (const char **) uri->data.ksk.keywords,
1738  uri->data.ksk.keywordCount))
1739  {
1741  uri->data.ksk.keywords,
1742  uri->data.ksk.keywordCount);
1743  uri->data.ksk.keywordCount++;
1744  }
1745  if (NULL != normalized_data)
1746  {
1747  if (! find_duplicate (normalized_data,
1748  (const char **) uri->data.ksk.keywords,
1749  uri->data.ksk.keywordCount))
1750  {
1751  insert_non_mandatory_keyword (normalized_data,
1752  uri->data.ksk.keywords,
1753  uri->data.ksk.keywordCount);
1754  uri->data.ksk.keywordCount++;
1755  }
1756  GNUNET_free (normalized_data);
1757  }
1758  return 0;
1759 }
1760 
1761 
1770 struct GNUNET_FS_Uri *
1772  const struct GNUNET_FS_MetaData *md)
1773 {
1774  struct GNUNET_FS_Uri *ret;
1775  char *filename;
1776  char *full_name = NULL;
1777  char *ss;
1778  int ent;
1779  int tok_keywords = 0;
1780  int paren_keywords = 0;
1781 
1782  if (NULL == md)
1783  return NULL;
1784  ret = GNUNET_new (struct GNUNET_FS_Uri);
1785  ret->type = GNUNET_FS_URI_KSK;
1786  ent = GNUNET_FS_meta_data_iterate (md, NULL, NULL);
1787  if (ent > 0)
1788  {
1790  md,
1792  -1);
1793  if (NULL != full_name)
1794  {
1795  filename = full_name;
1796  while (NULL != (ss = strstr (filename, DIR_SEPARATOR_STR)))
1797  filename = ss + 1;
1798  tok_keywords = get_keywords_from_tokens (filename, NULL, 0);
1799  paren_keywords = get_keywords_from_parens (filename, NULL, 0);
1800  }
1801  /* x3 because there might be a normalized variant of every keyword,
1802  plus theoretically one more for mime... */
1803  ret->data.ksk.keywords =
1804  GNUNET_new_array ((ent + tok_keywords + paren_keywords) * 3, char *);
1806  }
1807  if (tok_keywords > 0)
1808  ret->data.ksk.keywordCount +=
1810  ret->data.ksk.keywords,
1811  ret->data.ksk.keywordCount);
1812  if (paren_keywords > 0)
1813  ret->data.ksk.keywordCount +=
1815  ret->data.ksk.keywords,
1816  ret->data.ksk.keywordCount);
1817  if (ent > 0)
1818  GNUNET_free (full_name);
1819  return ret;
1820 }
1821 
1822 
1827 static int
1829 {
1830  return(! ((isalnum ((unsigned char) c)) || (c == '-') || (c == '_') ||
1831  (c == '.') || (c == '~')));
1832 }
1833 
1834 
1841 static char *
1843 {
1844  char **keywords;
1845  unsigned int keywordCount;
1846  size_t n;
1847  char *ret;
1848  unsigned int i;
1849  unsigned int j;
1850  unsigned int wpos;
1851  size_t slen;
1852  const char *keyword;
1853 
1854  if (uri->type != GNUNET_FS_URI_KSK)
1855  return NULL;
1856  keywords = uri->data.ksk.keywords;
1857  keywordCount = uri->data.ksk.keywordCount;
1858  n = keywordCount + strlen (GNUNET_FS_URI_PREFIX)
1859  + strlen (GNUNET_FS_URI_KSK_INFIX) + 1;
1860  for (i = 0; i < keywordCount; i++)
1861  {
1862  keyword = keywords[i];
1863  slen = strlen (keyword);
1864  n += slen;
1865  for (j = 0; j < slen; j++)
1866  {
1867  if ((j == 0) && (keyword[j] == ' '))
1868  {
1869  n--;
1870  continue; /* skip leading space */
1871  }
1872  if (needs_percent (keyword[j]))
1873  n += 2; /* will use %-encoding */
1874  }
1875  }
1876  ret = GNUNET_malloc (n);
1877  strcpy (ret, GNUNET_FS_URI_PREFIX);
1878  strcat (ret, GNUNET_FS_URI_KSK_INFIX);
1879  wpos = strlen (ret);
1880  for (i = 0; i < keywordCount; i++)
1881  {
1882  keyword = keywords[i];
1883  slen = strlen (keyword);
1884  for (j = 0; j < slen; j++)
1885  {
1886  if ((j == 0) && (keyword[j] == ' '))
1887  continue; /* skip leading space */
1888  if (needs_percent (keyword[j]))
1889  {
1890  sprintf (&ret[wpos], "%%%02X", (unsigned char) keyword[j]);
1891  wpos += 3;
1892  }
1893  else
1894  {
1895  ret[wpos++] = keyword[j];
1896  }
1897  }
1898  if (i != keywordCount - 1)
1899  ret[wpos++] = '+';
1900  }
1901  return ret;
1902 }
1903 
1904 
1911 static char *
1913 {
1914  char *ret;
1915  char buf[1024];
1916 
1917  if (GNUNET_FS_URI_SKS != uri->type)
1918  return NULL;
1919  ret =
1921  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
1922  buf,
1923  sizeof(buf));
1924  GNUNET_assert (NULL != ret);
1925  ret[0] = '\0';
1926  GNUNET_asprintf (&ret,
1927  "%s%s%s/%s",
1930  buf,
1931  uri->data.sks.identifier);
1932  return ret;
1933 }
1934 
1935 
1942 static char *
1944 {
1945  const struct FileIdentifier *fi;
1946  char *ret;
1947  struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1948  struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1949 
1950  if (uri->type != GNUNET_FS_URI_CHK)
1951  return NULL;
1952  fi = &uri->data.chk;
1953  GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash);
1954  GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash);
1955 
1956  GNUNET_asprintf (&ret,
1957  "%s%s%s.%s.%llu",
1960  (const char *) &keyhash,
1961  (const char *) &queryhash,
1962  (unsigned long long) GNUNET_ntohll (fi->file_length));
1963  return ret;
1964 }
1965 
1966 
1973 static char *
1975 {
1976  char *ret;
1977  struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
1978  struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
1979  char *peer_id;
1980  char peer_sig[SIGNATURE_ASCII_LENGTH + 1];
1981 
1982  GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.key, &keyhash);
1983  GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.query, &queryhash);
1984  peer_id =
1986  GNUNET_assert (
1987  NULL !=
1989  sizeof(struct GNUNET_CRYPTO_EddsaSignature),
1990  peer_sig,
1991  sizeof(peer_sig)));
1992  GNUNET_asprintf (&ret,
1993  "%s%s%s.%s.%llu.%s.%s.%llu",
1996  (const char *) &keyhash,
1997  (const char *) &queryhash,
1998  (unsigned long long) GNUNET_ntohll (
2000  peer_id,
2001  peer_sig,
2002  (unsigned long long)
2004  / 1000000LL);
2005  GNUNET_free (peer_id);
2006  return ret;
2007 }
2008 
2009 
2016 char *
2018 {
2019  if (uri == NULL)
2020  {
2021  GNUNET_break (0);
2022  return NULL;
2023  }
2024  switch (uri->type)
2025  {
2026  case GNUNET_FS_URI_KSK:
2027  return uri_ksk_to_string (uri);
2028 
2029  case GNUNET_FS_URI_SKS:
2030  return uri_sks_to_string (uri);
2031 
2032  case GNUNET_FS_URI_CHK:
2033  return uri_chk_to_string (uri);
2034 
2035  case GNUNET_FS_URI_LOC:
2036  return uri_loc_to_string (uri);
2037 
2038  default:
2039  GNUNET_break (0);
2040  return NULL;
2041  }
2042 }
2043 
2044 
2045 /* end of fs_uri.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#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...
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 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
static void insert_non_mandatory_keyword(const char *s, char **array, int index)
Add a keyword as non-mandatory (with ' '-prefix) to the given keyword list at offset 'index'.
Definition: fs_uri.c:1400
static size_t u8_strcount(const uint8_t *s)
Counts the number of UTF-8 characters (not bytes) in the string, returns that count.
Definition: fs_uri.c:1492
static int gather_uri_data(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len)
Function called on each value in the meta data.
Definition: fs_uri.c:1696
static int needs_percent(char c)
In URI-encoding, does the given character need to be encoded using %-encoding?
Definition: fs_uri.c:1828
static char * normalize_metadata(enum EXTRACTOR_MetaFormat format, const char *data, size_t data_len)
FIXME: comment.
Definition: fs_uri.c:1436
static struct GNUNET_FS_Uri * uri_chk_parse(const char *s, char **emsg)
Parse a CHK URI.
Definition: fs_uri.c:406
static char * uri_sks_to_string(const struct GNUNET_FS_Uri *uri)
Convert SKS URI to a string.
Definition: fs_uri.c:1912
static char * uri_ksk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a KSK URI to a string.
Definition: fs_uri.c:1842
#define GNUNET_FS_URI_SKS_PREFIX
Definition: fs_uri.c:356
static int get_keywords_from_parens(const char *s, char **array, int index)
Break the filename up by matching [], () and {} pairs to make keywords.
Definition: fs_uri.c:1523
#define TOKENS
Where to break up keywords.
Definition: fs_uri.c:1614
#define SIGNATURE_ASCII_LENGTH
Definition: fs_uri.c:485
static char * uri_chk_to_string(const struct GNUNET_FS_Uri *uri)
Convert a CHK URI to a string.
Definition: fs_uri.c:1943
static struct GNUNET_FS_Uri * uri_loc_parse(const char *s, char **emsg)
Parse a LOC URI.
Definition: fs_uri.c:496
#define GNUNET_FS_URI_KSK_PREFIX
Definition: fs_uri.c:262
static int get_keywords_from_tokens(const char *s, char **array, int index)
Break the filename up by TOKENS to make keywords.
Definition: fs_uri.c:1631
#define GNUNET_FS_URI_CHK_PREFIX
Definition: fs_uri.c:395
static struct GNUNET_FS_Uri * uri_ksk_parse(const char *s, char **emsg)
Parse a KSK URI.
Definition: fs_uri.c:272
static struct GNUNET_FS_Uri * uri_sks_parse(const char *s, char **emsg)
Parse an SKS URI.
Definition: fs_uri.c:366
static int find_duplicate(const char *s, const char **array, int array_length)
Test if the given keyword s is already present in the given array, ignoring the '+'-mandatory prefix ...
Definition: fs_uri.c:1421
static char * uri_loc_to_string(const struct GNUNET_FS_Uri *uri)
Convert a LOC URI to a string.
Definition: fs_uri.c:1974
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
Definition: gnunet-abd.c:41
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
uint32_t data
The data value.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static char * pseudonym
Command-line option identifying the pseudonym to use for the publication.
static char * plugin_name
Name of our plugin.
static char buf[2048]
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:197
#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.
#define EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME
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_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
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
int(* GNUNET_FS_KeywordIterator)(void *cls, const char *keyword, int is_mandatory)
Iterator over keywords.
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
#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
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
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
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
int GNUNET_FS_uri_test_loc(const struct GNUNET_FS_Uri *uri)
Is this a location URI?
Definition: fs_uri.c:1384
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
char * GNUNET_FS_uri_to_string(const struct GNUNET_FS_Uri *uri)
Convert a URI to a UTF-8 String.
Definition: fs_uri.c:2017
#define GNUNET_FS_URI_PREFIX
#define GNUNET_FS_URI_LOC_INFIX
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_dup(const struct GNUNET_FS_Uri *uri)
Duplicate URI.
Definition: fs_uri.c:987
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
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
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
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_ksk_create_from_meta_data(const struct GNUNET_FS_MetaData *md)
Construct a keyword-URI from meta-data (take all entries in the meta-data and construct one large key...
Definition: fs_uri.c:1771
int GNUNET_FS_uri_to_key(const struct GNUNET_FS_Uri *uri, struct GNUNET_HashCode *key)
Get a unique key from a URI.
Definition: fs_uri.c:96
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
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
#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:251
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:357
#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:422
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:460
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:708
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:788
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
#define max(x, y)
#define DIR_SEPARATOR_STR
Definition: platform.h:165
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
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:96
A Universal Resource Identifier (URI), opaque.
Definition: fs_api.h:167
struct GNUNET_FS_Uri::@13::@14 ksk
union GNUNET_FS_Uri::@13 data
struct GNUNET_FS_Uri::@13::@15 sks
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
enum GNUNET_FS_UriType type
Type of the URI.
Definition: fs_api.h:171
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
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
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.