📄 uri.c
字号:
GNUNET_free (dup); return GNUNET_SYSERR; } GNUNET_free (dup); fi->file_length = GNUNET_htonll (fi->file_length); return GNUNET_OK;}/** * Parses an URI that identifies a location (and file). * Also verifies validity of the location URI. * * @param uri an uri string * @param loc where to store the location * @return GNUNET_OK on success, GNUNET_SYSERR if this is not a file URI */static intparseLocationURI (struct GNUNET_GE_Context *ectx, const char *uri, Location * loc){ unsigned int pos; unsigned int npos; int ret; size_t slen; char *dup; char *addr; GNUNET_GE_ASSERT (ectx, uri != NULL); addr = NULL; slen = strlen (uri); pos = strlen (GNUNET_ECRS_URI_PREFIX); if (0 != strncmp (uri, GNUNET_ECRS_URI_PREFIX, pos)) return GNUNET_SYSERR; if (0 != strncmp (&uri[pos], GNUNET_ECRS_LOCATION_INFIX, strlen (GNUNET_ECRS_LOCATION_INFIX))) return GNUNET_SYSERR; pos += strlen (GNUNET_ECRS_LOCATION_INFIX); if ((slen < pos + 2 * sizeof (GNUNET_EncName) + 1) || (uri[pos + sizeof (GNUNET_EncName) - 1] != '.') || (uri[pos + sizeof (GNUNET_EncName) * 2 - 1] != '.')) return GNUNET_SYSERR; dup = GNUNET_strdup (uri); dup[pos + sizeof (GNUNET_EncName) - 1] = '\0'; dup[pos + sizeof (GNUNET_EncName) * 2 - 1] = '\0'; npos = pos + sizeof (GNUNET_EncName) * 2; while ((uri[npos] != '\0') && (uri[npos] != '.')) npos++; if (dup[npos] == '\0') goto ERR; dup[npos++] = '\0'; if ((GNUNET_OK != GNUNET_enc_to_hash (&dup[pos], &loc->fi.chk.key)) || (GNUNET_OK != GNUNET_enc_to_hash (&dup[pos + sizeof (GNUNET_EncName)], &loc->fi.chk.query)) || (1 != SSCANF (&dup[pos + sizeof (GNUNET_EncName) * 2], "%llu", &loc->fi.file_length))) goto ERR; loc->fi.file_length = GNUNET_htonll (loc->fi.file_length); ret = enc2bin (&dup[npos], &loc->peer, sizeof (GNUNET_RSA_PublicKey)); if (ret == -1) goto ERR; npos += ret; if (dup[npos++] != '.') goto ERR; ret = enc2bin (&dup[npos], &loc->contentSignature, sizeof (GNUNET_RSA_Signature)); if (ret == -1) goto ERR; npos += ret; if (dup[npos++] != '.') goto ERR; if (1 != SSCANF (&dup[npos], "%u", &loc->expirationTime)) goto ERR; /* Finally: verify sigs! */ if (GNUNET_OK != GNUNET_RSA_verify (&loc->fi, sizeof (GNUNET_EC_FileIdentifier) + sizeof (GNUNET_PeerIdentity) + sizeof (GNUNET_Int32Time), &loc->contentSignature, &loc->peer)) goto ERR; GNUNET_free (dup); return GNUNET_OK;ERR: GNUNET_free (dup); GNUNET_free_non_null (addr); return GNUNET_SYSERR;}/** * Convert a UTF-8 String to a URI. */URI *GNUNET_ECRS_string_to_uri (struct GNUNET_GE_Context * ectx, const char *uri){ URI *ret; int len; ret = GNUNET_malloc (sizeof (URI)); if (GNUNET_OK == parseFileURI (ectx, uri, &ret->data.fi)) { ret->type = chk; return ret; } if (GNUNET_OK == parseSubspaceURI (ectx, uri, &ret->data.sks.namespace, &ret->data.sks.identifier)) { ret->type = sks; return ret; } if (GNUNET_OK == parseLocationURI (ectx, uri, &ret->data.loc)) { ret->type = loc; return ret; } len = parseKeywordURI (ectx, uri, &ret->data.ksk.keywords); if (len < 0) { GNUNET_free (ret); return NULL; } ret->type = ksk; ret->data.ksk.keywordCount = len; return ret;}/** * Free URI. */voidGNUNET_ECRS_uri_destroy (struct GNUNET_ECRS_URI *uri){ int i; GNUNET_GE_ASSERT (NULL, uri != NULL); switch (uri->type) { case ksk: for (i = 0; i < uri->data.ksk.keywordCount; i++) GNUNET_free (uri->data.ksk.keywords[i]); GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, 0); break; case sks: GNUNET_free (uri->data.sks.identifier); break; case loc: break; default: /* do nothing */ break; } GNUNET_free (uri);}/** * Is this a namespace URI? */intGNUNET_ECRS_uri_test_sks (const struct GNUNET_ECRS_URI *uri){ return uri->type == sks;}/** * Get the (globally unique) ID of the namespace * from the given namespace URI. * * @return GNUNET_OK on success */intGNUNET_ECRS_uri_get_namespace_from_sks (const struct GNUNET_ECRS_URI *uri, GNUNET_HashCode * id){ if (!GNUNET_ECRS_uri_test_sks (uri)) { GNUNET_GE_BREAK (NULL, 0); return GNUNET_SYSERR; } *id = uri->data.sks.namespace; return GNUNET_OK;}/** * Get the content identifier of an SKS URI. * * @return NULL on error */char *GNUNET_ECRS_uri_get_content_id_from_sks (const struct GNUNET_ECRS_URI *uri){ if (!GNUNET_ECRS_uri_test_sks (uri)) { GNUNET_GE_BREAK (NULL, 0); return NULL; } return GNUNET_strdup (uri->data.sks.identifier);}/** * Is this a keyword URI? */intGNUNET_ECRS_uri_test_ksk (const struct GNUNET_ECRS_URI *uri){#if EXTRA_CHECKS int i; if (uri->type == ksk) { for (i = uri->data.ksk.keywordCount - 1; i >= 0; i--) GNUNET_GE_ASSERT (NULL, uri->data.ksk.keywords[i] != NULL); }#endif return uri->type == ksk;}/** * How many keywords are ANDed in this keyword URI? * @return 0 if this is not a keyword URI */unsigned intGNUNET_ECRS_uri_get_keyword_count_from_ksk (const struct GNUNET_ECRS_URI *uri){ if (uri->type != ksk) return 0; return uri->data.ksk.keywordCount;}/** * Iterate over all keywords in this keyword URI? * @return -1 if this is not a keyword URI, otherwise number of * keywords iterated over until iterator aborted */intGNUNET_ECRS_uri_get_keywords_from_ksk (const struct GNUNET_ECRS_URI *uri, GNUNET_ECRS_KeywordIterator iterator, void *cls){ unsigned int i; char *keyword; if (uri->type != ksk) return -1; if (iterator == NULL) return uri->data.ksk.keywordCount; for (i = 0; i < uri->data.ksk.keywordCount; i++) { keyword = uri->data.ksk.keywords[i]; /* first character of keyword indicates if it is mandatory or not */ if (GNUNET_OK != iterator (&keyword[1], keyword[0] == '+', cls)) return i; } return i;}/** * Is this a file (or directory) URI? */intGNUNET_ECRS_uri_test_chk (const struct GNUNET_ECRS_URI *uri){ return uri->type == chk;}/** * Is this a location URI? (DHT specific!) */intGNUNET_ECRS_uri_test_loc (const struct GNUNET_ECRS_URI *uri){ return uri->type == loc;}/** * What is the size of the file that this URI * refers to? */unsigned long longGNUNET_ECRS_uri_get_file_size (const struct GNUNET_ECRS_URI *uri){ switch (uri->type) { case chk: return GNUNET_ntohll (uri->data.fi.file_length); case loc: return GNUNET_ntohll (uri->data.loc.fi.file_length); default: GNUNET_GE_ASSERT (NULL, 0); } return 0; /* unreachable */}/** * Duplicate URI. */URI *GNUNET_ECRS_uri_duplicate (const URI * uri){ struct GNUNET_ECRS_URI *ret; int i; ret = GNUNET_malloc (sizeof (URI)); memcpy (ret, uri, sizeof (URI)); switch (ret->type) { case ksk: if (ret->data.ksk.keywordCount > 0) { ret->data.ksk.keywords = GNUNET_malloc (ret->data.ksk.keywordCount * sizeof (char *)); for (i = 0; i < ret->data.ksk.keywordCount; i++) ret->data.ksk.keywords[i] = GNUNET_strdup (uri->data.ksk.keywords[i]); } else ret->data.ksk.keywords = NULL; /* just to be sure */ break; case sks: ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier); break; case loc: break; default: break; } return ret;}/** * Expand a keyword-URI by duplicating all keywords, * adding the current date (YYYY-MM-DD) after each * keyword. */URI *GNUNET_ECRS_uri_expand_keywords_with_date (const URI * uri){ URI *ret; int i; char *key; char *kd; struct tm t; time_t now; unsigned int keywordCount; GNUNET_GE_ASSERT (NULL, uri->type == ksk); time (&now);#ifdef HAVE_GMTIME_R gmtime_r (&now, &t);#else t = *gmtime (&now);#endif ret = GNUNET_malloc (sizeof (URI)); ret->type = ksk; keywordCount = uri->data.ksk.keywordCount; ret->data.ksk.keywordCount = 2 * keywordCount; if (keywordCount > 0) { ret->data.ksk.keywords = GNUNET_malloc (sizeof (char *) * keywordCount * 2); for (i = 0; i < keywordCount; i++) { key = uri->data.ksk.keywords[i]; GNUNET_GE_ASSERT (NULL, key != NULL); ret->data.ksk.keywords[2 * i] = GNUNET_strdup (key); kd = GNUNET_malloc (strlen (key) + 13); memset (kd, 0, strlen (key) + 13); strcpy (kd, key); strftime (&kd[strlen (key)], 13, "-%Y-%m-%d", &t); ret->data.ksk.keywords[2 * i + 1] = kd; } } else ret->data.ksk.keywords = NULL; return ret;}static intgather_uri_data (EXTRACTOR_KeywordType type, const char *data, void *cls){ URI *uri = cls; char *nkword; int j; for (j = uri->data.ksk.keywordCount - 1; j >= 0; j--) if (0 == strcmp (&uri->data.ksk.keywords[j][1], data)) return GNUNET_OK; nkword = GNUNET_malloc (strlen (data) + 2); strcpy (nkword, " "); /* not mandatory */ strcat (nkword, data); uri->data.ksk.keywords[uri->data.ksk.keywordCount++] = nkword; return GNUNET_OK;}/** * Construct a keyword-URI from meta-data (take all entries * in the meta-data and construct one large keyword URI * that lists all keywords that can be found in the meta-data). */URI *GNUNET_meta_data_to_uri (const struct GNUNET_MetaData * md){ URI *ret; if (md == NULL) return NULL; ret = GNUNET_malloc (sizeof (URI)); ret->type = ksk; ret->data.ksk.keywordCount = 0; ret->data.ksk.keywords = NULL; ret->data.ksk.keywords = GNUNET_malloc (sizeof (char *) * GNUNET_meta_data_get_contents (md, NULL, NULL)); GNUNET_meta_data_get_contents (md, &gather_uri_data, ret); return ret;}/** * Are these two URIs equal? */intGNUNET_ECRS_uri_test_equal (const struct GNUNET_ECRS_URI *uri1, const struct GNUNET_ECRS_URI *uri2){ int ret; int i; int j; GNUNET_GE_ASSERT (NULL, uri1 != NULL); GNUNET_GE_ASSERT (NULL, uri2 != NULL); if (uri1->type != uri2->type) return GNUNET_NO; switch (uri1->type) { case chk: if (0 == memcmp (&uri1->data.fi, &uri2->data.fi, sizeof (GNUNET_EC_FileIdentifier))) return GNUNET_YES; return GNUNET_NO; case sks: if ((0 == memcmp (&uri1->data.sks.namespace, &uri2->data.sks.namespace, sizeof (GNUNET_HashCode))) && (0 == strcmp (uri1->data.sks.identifier, uri2->data.sks.identifier))) return GNUNET_YES; return GNUNET_NO; case ksk: if (uri1->data.ksk.keywordCount != uri2->data.ksk.keywordCount) return GNUNET_NO; for (i = 0; i < uri1->data.ksk.keywordCount; i++) { ret = GNUNET_NO; for (j = 0; j < uri2->data.ksk.keywordCount; j++) { if (0 == strcmp (uri1->data.ksk.keywords[i], uri2->data.ksk.keywords[j])) { ret = GNUNET_YES; break; } } if (ret == GNUNET_NO) return GNUNET_NO; } return GNUNET_YES; case loc: if (memcmp (&uri1->data.loc, &uri2->data.loc, sizeof (GNUNET_EC_FileIdentifier) + sizeof (GNUNET_RSA_PublicKey) + sizeof (GNUNET_Int32Time) + sizeof (unsigned short) + sizeof (unsigned short)) != 0) return GNUNET_NO; return GNUNET_YES; default: return GNUNET_NO; }}/** * Obtain the identity of the peer offering the data * @return -1 if this is not a location URI, otherwise GNUNET_OK */intGNUNET_ECRS_uri_get_peer_identity_from_loc (const struct GNUNET_ECRS_URI *uri, GNUNET_PeerIdentity * peer){ if (uri->type != loc) return -1; GNUNET_hash (&uri->data.loc.peer, sizeof (GNUNET_RSA_PublicKey), &peer->hashPubKey); return GNUNET_OK;}/** * Obtain the URI of the content itself. * * @return NULL if argument is not a location URI */struct GNUNET_ECRS_URI *GNUNET_ECRS_uri_get_content_uri_from_loc (const struct GNUNET_ECRS_URI *uri){ struct GNUNET_ECRS_URI *ret; if (uri->type != loc) return NULL; ret = GNUNET_malloc (sizeof (struct GNUNET_ECRS_URI)); ret->type = chk; ret->data.fi = uri->data.loc.fi; return ret;}/** * Construct a location URI. * * @param baseURI content offered by the sender * @param sender identity of the peer with the content * @param expiration_time how long will the content be offered? * @param proto transport protocol to reach the peer * @param sas sender address size (for HELLO) * @param address sas bytes of address information * @param signer function to call for obtaining * RSA signatures for "sender". * @return the location URI */struct GNUNET_ECRS_URI *GNUNET_ECRS_location_to_uri (const struct GNUNET_ECRS_URI *baseUri, const GNUNET_RSA_PublicKey * sender, GNUNET_Int32Time expirationTime, GNUNET_ECRS_SignFunction signer, void *signer_cls){ struct GNUNET_ECRS_URI *uri; if (baseUri->type != chk) return NULL; uri = GNUNET_malloc (sizeof (struct GNUNET_ECRS_URI)); uri->type = loc; uri->data.loc.fi = baseUri->data.fi; uri->data.loc.peer = *sender; uri->data.loc.expirationTime = expirationTime; signer (signer_cls, sizeof (GNUNET_EC_FileIdentifier) + sizeof (GNUNET_PeerIdentity) + sizeof (GNUNET_Int32Time), &uri->data.loc.fi, &uri->data.loc.contentSignature); return uri;}/* end of uri.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -