diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-08-22 17:57:31 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-08-22 17:57:31 +0000 |
commit | 2ae973618f3b51fa9bbf5532eaa1352cafc24ecc (patch) | |
tree | ea8bb13a4c7d390f88318b61bc6caf50ea6cf400 /src/fs/fs_uri.c | |
parent | 9a10e9c06a3b08c8ab73edb7d2093a6d452ecc05 (diff) | |
download | gnunet-2ae973618f3b51fa9bbf5532eaa1352cafc24ecc.tar.gz gnunet-2ae973618f3b51fa9bbf5532eaa1352cafc24ecc.zip |
stuff
Diffstat (limited to 'src/fs/fs_uri.c')
-rw-r--r-- | src/fs/fs_uri.c | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c index f2351af1b..8e69a8425 100644 --- a/src/fs/fs_uri.c +++ b/src/fs/fs_uri.c | |||
@@ -26,10 +26,10 @@ | |||
26 | * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER". | 26 | * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER". |
27 | * The specific structure of "IDENTIFIER" depends on the module and | 27 | * The specific structure of "IDENTIFIER" depends on the module and |
28 | * maybe differenciated into additional subcategories if applicable. | 28 | * maybe differenciated into additional subcategories if applicable. |
29 | * This module only deals with ecrs identifiers (MODULE = "ecrs"). | 29 | * This module only deals with fs identifiers (MODULE = "fs"). |
30 | * <p> | 30 | * <p> |
31 | * | 31 | * |
32 | * This module only parses URIs for the AFS module. The ECRS URIs fall | 32 | * This module only parses URIs for the AFS module. The FS URIs fall |
33 | * into four categories, "chk", "sks", "ksk" and "loc". The first three | 33 | * into four categories, "chk", "sks", "ksk" and "loc". The first three |
34 | * categories were named in analogy (!) to Freenet, but they do NOT | 34 | * categories were named in analogy (!) to Freenet, but they do NOT |
35 | * work in exactly the same way. They are very similar from the user's | 35 | * work in exactly the same way. They are very similar from the user's |
@@ -40,7 +40,7 @@ | |||
40 | * <ul><li> | 40 | * <ul><li> |
41 | * | 41 | * |
42 | * First, there are URIs that identify a file. They have the format | 42 | * First, there are URIs that identify a file. They have the format |
43 | * "gnunet://ecrs/chk/HEX1.HEX2.SIZE". These URIs can be used to | 43 | * "gnunet://fs/chk/HEX1.HEX2.SIZE". These URIs can be used to |
44 | * download the file. The description, filename, mime-type and other | 44 | * download the file. The description, filename, mime-type and other |
45 | * meta-data is NOT part of the file-URI since a URI uniquely | 45 | * meta-data is NOT part of the file-URI since a URI uniquely |
46 | * identifies a resource (and the contents of the file would be the | 46 | * identifies a resource (and the contents of the file would be the |
@@ -49,7 +49,7 @@ | |||
49 | * </li><li> | 49 | * </li><li> |
50 | * | 50 | * |
51 | * The second category identifies entries in a namespace. The format | 51 | * The second category identifies entries in a namespace. The format |
52 | * is "gnunet://ecrs/sks/NAMESPACE/IDENTIFIER" where the namespace | 52 | * is "gnunet://fs/sks/NAMESPACE/IDENTIFIER" where the namespace |
53 | * should be given in HEX. Applications may allow using a nickname | 53 | * should be given in HEX. Applications may allow using a nickname |
54 | * for the namespace if the nickname is not ambiguous. The identifier | 54 | * for the namespace if the nickname is not ambiguous. The identifier |
55 | * can be either an ASCII sequence or a HEX-encoding. If the | 55 | * can be either an ASCII sequence or a HEX-encoding. If the |
@@ -59,7 +59,7 @@ | |||
59 | * </li> <li> | 59 | * </li> <li> |
60 | * | 60 | * |
61 | * The third category identifies ordinary searches. The format is | 61 | * The third category identifies ordinary searches. The format is |
62 | * "gnunet://ecrs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax | 62 | * "gnunet://fs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax |
63 | * it is possible to encode searches with the boolean "AND" operator. | 63 | * it is possible to encode searches with the boolean "AND" operator. |
64 | * "+" is used since it indicates a commutative 'and' operation and | 64 | * "+" is used since it indicates a commutative 'and' operation and |
65 | * is unlikely to be used in a keyword by itself. | 65 | * is unlikely to be used in a keyword by itself. |
@@ -67,7 +67,7 @@ | |||
67 | * </li><li> | 67 | * </li><li> |
68 | * | 68 | * |
69 | * The last category identifies a datum on a specific machine. The | 69 | * The last category identifies a datum on a specific machine. The |
70 | * format is "gnunet://ecrs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is | 70 | * format is "gnunet://fs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is |
71 | * the BinName of the public key of the peer storing the datum. The | 71 | * the BinName of the public key of the peer storing the datum. The |
72 | * signature (SIG) certifies that this peer has this content. | 72 | * signature (SIG) certifies that this peer has this content. |
73 | * HEX1, HEX2 and SIZE correspond to a 'chk' URI. | 73 | * HEX1, HEX2 and SIZE correspond to a 'chk' URI. |
@@ -211,6 +211,7 @@ percent_decode_keyword (const char *in, char **emsg) | |||
211 | if (1 != sscanf (&out[rpos + 1], "%2X", &hx)) | 211 | if (1 != sscanf (&out[rpos + 1], "%2X", &hx)) |
212 | { | 212 | { |
213 | GNUNET_free (out); | 213 | GNUNET_free (out); |
214 | *emsg = GNUNET_strdup (_("`%' must be followed by HEX number")); | ||
214 | return NULL; | 215 | return NULL; |
215 | } | 216 | } |
216 | rpos += 3; | 217 | rpos += 3; |
@@ -265,11 +266,14 @@ uri_ksk_parse (const char *s, char **emsg) | |||
265 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX); | 266 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX); |
266 | if ( (slen <= pos) || | 267 | if ( (slen <= pos) || |
267 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX, | 268 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX, |
268 | pos) ) || | 269 | pos) ) ) |
269 | (s[slen - 1] == '+') || | 270 | return NULL; /* not KSK URI */ |
271 | if ( (s[slen - 1] == '+') || | ||
270 | (s[pos] == '+') ) | 272 | (s[pos] == '+') ) |
271 | return NULL; /* no keywords / malformed */ | 273 | { |
272 | 274 | *emsg = GNUNET_strdup (_("Malformed KSK URI (must not begin or end with `+')")); | |
275 | return NULL; | ||
276 | } | ||
273 | max = 1; | 277 | max = 1; |
274 | saw_quote = 0; | 278 | saw_quote = 0; |
275 | for (i = pos; i < slen; i++) | 279 | for (i = pos; i < slen; i++) |
@@ -284,11 +288,17 @@ uri_ksk_parse (const char *s, char **emsg) | |||
284 | { | 288 | { |
285 | max++; | 289 | max++; |
286 | if (s[i - 1] == '+') | 290 | if (s[i - 1] == '+') |
287 | return NULL; /* "++" not allowed */ | 291 | { |
292 | *emsg = GNUNET_strdup (_("`++' not allowed in KSK URI")); | ||
293 | return NULL; | ||
294 | } | ||
288 | } | 295 | } |
289 | } | 296 | } |
290 | if (saw_quote == 1) | 297 | if (saw_quote == 1) |
291 | return NULL; /* quotes not balanced */ | 298 | { |
299 | *emsg = GNUNET_strdup (_("Quotes not balanced in KSK URI")); | ||
300 | return NULL; | ||
301 | } | ||
292 | iret = max; | 302 | iret = max; |
293 | dup = GNUNET_strdup (s); | 303 | dup = GNUNET_strdup (s); |
294 | keywords = GNUNET_malloc (max * sizeof (char *)); | 304 | keywords = GNUNET_malloc (max * sizeof (char *)); |
@@ -304,7 +314,7 @@ uri_ksk_parse (const char *s, char **emsg) | |||
304 | { | 314 | { |
305 | keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg); | 315 | keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg); |
306 | if (NULL == keywords[max]) | 316 | if (NULL == keywords[max]) |
307 | goto CLEANUP; | 317 | goto CLEANUP; |
308 | dup[i] = '\0'; | 318 | dup[i] = '\0'; |
309 | } | 319 | } |
310 | } | 320 | } |
@@ -349,14 +359,21 @@ uri_sks_parse (const char *s, char **emsg) | |||
349 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX); | 359 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX); |
350 | if ( (slen <= pos) || | 360 | if ( (slen <= pos) || |
351 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX, | 361 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX, |
352 | pos) ) || | 362 | pos) ) ) |
353 | (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || | 363 | return NULL; /* not an SKS URI */ |
364 | if ( (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || | ||
354 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/') ) | 365 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/') ) |
355 | return NULL; | 366 | { |
367 | *emsg = GNUNET_strdup (_("Malformed SKS URI")); | ||
368 | return NULL; | ||
369 | } | ||
356 | memcpy (enc, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); | 370 | memcpy (enc, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); |
357 | enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0'; | 371 | enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0'; |
358 | if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace)) | 372 | if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace)) |
359 | return NULL; | 373 | { |
374 | *emsg = GNUNET_strdup (_("Malformed SKS URI")); | ||
375 | return NULL; | ||
376 | } | ||
360 | identifier = GNUNET_strdup (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]); | 377 | identifier = GNUNET_strdup (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]); |
361 | ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); | 378 | ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); |
362 | ret->type = sks; | 379 | ret->type = sks; |
@@ -389,11 +406,14 @@ uri_chk_parse (const char *s, char **emsg) | |||
389 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX); | 406 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX); |
390 | if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || | 407 | if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || |
391 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX, | 408 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX, |
392 | pos) ) || | 409 | pos) ) ) |
393 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || | 410 | return NULL; /* not a CHK URI */ |
411 | if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || | ||
394 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') ) | 412 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') ) |
395 | return NULL; | 413 | { |
396 | 414 | *emsg = GNUNET_strdup (_("Malformed CHK URI")); | |
415 | return NULL; | ||
416 | } | ||
397 | memcpy (h1, | 417 | memcpy (h1, |
398 | &s[pos], | 418 | &s[pos], |
399 | sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); | 419 | sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); |
@@ -410,9 +430,11 @@ uri_chk_parse (const char *s, char **emsg) | |||
410 | (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], | 430 | (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], |
411 | "%llu", | 431 | "%llu", |
412 | &fi.file_length))) | 432 | &fi.file_length))) |
413 | return NULL; | 433 | { |
434 | *emsg = GNUNET_strdup (_("Malformed CHK URI")); | ||
435 | return NULL; | ||
436 | } | ||
414 | fi.file_length = GNUNET_htonll (fi.file_length); | 437 | fi.file_length = GNUNET_htonll (fi.file_length); |
415 | |||
416 | ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); | 438 | ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); |
417 | ret->type = chk; | 439 | ret->type = chk; |
418 | ret->data.chk = fi; | 440 | ret->data.chk = fi; |
@@ -527,18 +549,20 @@ uri_loc_parse (const char *s, char **emsg) | |||
527 | struct LocUriAssembly ass; | 549 | struct LocUriAssembly ass; |
528 | int ret; | 550 | int ret; |
529 | size_t slen; | 551 | size_t slen; |
530 | char *addr; | ||
531 | 552 | ||
532 | GNUNET_assert (s != NULL); | 553 | GNUNET_assert (s != NULL); |
533 | slen = strlen (s); | 554 | slen = strlen (s); |
534 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX); | 555 | pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX); |
535 | if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || | 556 | if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || |
536 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX, | 557 | (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX, |
537 | pos) ) || | 558 | pos) ) ) |
538 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || | 559 | return NULL; /* not an SKS URI */ |
560 | if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || | ||
539 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') ) | 561 | (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') ) |
540 | return NULL; | 562 | { |
541 | 563 | *emsg = GNUNET_strdup (_("SKS URI malformed")); | |
564 | return NULL; | ||
565 | } | ||
542 | memcpy (h1, | 566 | memcpy (h1, |
543 | &s[pos], | 567 | &s[pos], |
544 | sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); | 568 | sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); |
@@ -555,32 +579,54 @@ uri_loc_parse (const char *s, char **emsg) | |||
555 | (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], | 579 | (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], |
556 | "%llu", | 580 | "%llu", |
557 | &ass.fi.file_length)) ) | 581 | &ass.fi.file_length)) ) |
558 | return NULL; | 582 | { |
583 | *emsg = GNUNET_strdup (_("SKS URI malformed")); | ||
584 | return NULL; | ||
585 | } | ||
559 | ass.fi.file_length = GNUNET_htonll (ass.fi.file_length); | 586 | ass.fi.file_length = GNUNET_htonll (ass.fi.file_length); |
560 | 587 | ||
561 | npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2; | 588 | npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2; |
562 | while ((s[npos] != '\0') && (s[npos] != '.')) | 589 | while ((s[npos] != '\0') && (s[npos] != '.')) |
563 | npos++; | 590 | npos++; |
564 | if (s[npos] == '\0') | 591 | if (s[npos] == '\0') |
565 | goto ERR; | 592 | { |
593 | *emsg = GNUNET_strdup (_("SKS URI malformed")); | ||
594 | goto ERR; | ||
595 | } | ||
596 | npos++; | ||
566 | ret = enc2bin (&s[npos], | 597 | ret = enc2bin (&s[npos], |
567 | &ass.peer, | 598 | &ass.peer, |
568 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | 599 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); |
569 | if (ret == -1) | 600 | if (ret == -1) |
570 | goto ERR; | 601 | { |
602 | *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode public key)")); | ||
603 | goto ERR; | ||
604 | } | ||
571 | npos += ret; | 605 | npos += ret; |
572 | if (s[npos++] != '.') | 606 | if (s[npos++] != '.') |
573 | goto ERR; | 607 | { |
608 | *emsg = GNUNET_strdup (_("SKS URI malformed (could not find signature)")); | ||
609 | goto ERR; | ||
610 | } | ||
574 | ret = enc2bin (&s[npos], | 611 | ret = enc2bin (&s[npos], |
575 | &sig, | 612 | &sig, |
576 | sizeof (struct GNUNET_CRYPTO_RsaSignature)); | 613 | sizeof (struct GNUNET_CRYPTO_RsaSignature)); |
577 | if (ret == -1) | 614 | if (ret == -1) |
578 | goto ERR; | 615 | { |
579 | npos += ret; | 616 | *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode signature)")); |
617 | goto ERR; | ||
618 | } | ||
619 | npos += ret; | ||
580 | if (s[npos++] != '.') | 620 | if (s[npos++] != '.') |
581 | goto ERR; | 621 | { |
622 | *emsg = GNUNET_strdup (_("SKS URI malformed")); | ||
623 | goto ERR; | ||
624 | } | ||
582 | if (1 != SSCANF (&s[npos], "%llu", &exptime)) | 625 | if (1 != SSCANF (&s[npos], "%llu", &exptime)) |
583 | goto ERR; | 626 | { |
627 | *emsg = GNUNET_strdup (_("SKS URI malformed (could not parse expiration time)")); | ||
628 | goto ERR; | ||
629 | } | ||
584 | ass.purpose.size = htonl(sizeof(struct LocUriAssembly)); | 630 | ass.purpose.size = htonl(sizeof(struct LocUriAssembly)); |
585 | ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_NAMESPACE_PLACEMENT); | 631 | ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_NAMESPACE_PLACEMENT); |
586 | et.value = exptime; | 632 | et.value = exptime; |
@@ -590,8 +636,10 @@ uri_loc_parse (const char *s, char **emsg) | |||
590 | &ass.purpose, | 636 | &ass.purpose, |
591 | &sig, | 637 | &sig, |
592 | &ass.peer)) | 638 | &ass.peer)) |
593 | goto ERR; | 639 | { |
594 | 640 | *emsg = GNUNET_strdup (_("SKS URI malformed (signature failed validation)")); | |
641 | goto ERR; | ||
642 | } | ||
595 | uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); | 643 | uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); |
596 | uri->type = loc; | 644 | uri->type = loc; |
597 | uri->data.loc.fi = ass.fi; | 645 | uri->data.loc.fi = ass.fi; |
@@ -601,7 +649,6 @@ uri_loc_parse (const char *s, char **emsg) | |||
601 | 649 | ||
602 | return uri; | 650 | return uri; |
603 | ERR: | 651 | ERR: |
604 | GNUNET_free_non_null (addr); | ||
605 | return NULL; | 652 | return NULL; |
606 | } | 653 | } |
607 | 654 | ||
@@ -618,12 +665,20 @@ GNUNET_FS_uri_parse (const char *uri, | |||
618 | char **emsg) | 665 | char **emsg) |
619 | { | 666 | { |
620 | struct GNUNET_FS_Uri *ret; | 667 | struct GNUNET_FS_Uri *ret; |
668 | char *msg; | ||
621 | 669 | ||
670 | if (NULL == emsg) | ||
671 | emsg = &msg; | ||
672 | *emsg = NULL; | ||
622 | if ( (NULL != (ret = uri_chk_parse (uri, emsg))) || | 673 | if ( (NULL != (ret = uri_chk_parse (uri, emsg))) || |
623 | (NULL != (ret = uri_ksk_parse (uri, emsg))) || | 674 | (NULL != (ret = uri_ksk_parse (uri, emsg))) || |
624 | (NULL != (ret = uri_sks_parse (uri, emsg))) || | 675 | (NULL != (ret = uri_sks_parse (uri, emsg))) || |
625 | (NULL != (ret = uri_loc_parse (uri, emsg))) ) | 676 | (NULL != (ret = uri_loc_parse (uri, emsg))) ) |
626 | return ret; | 677 | return ret; |
678 | if (NULL == *emsg) | ||
679 | *emsg = GNUNET_strdup (_("Unrecognized URI type")); | ||
680 | if (emsg == &msg) | ||
681 | GNUNET_free (msg); | ||
627 | return NULL; | 682 | return NULL; |
628 | } | 683 | } |
629 | 684 | ||