-/**
- * Closure for match_full_data.
- */
-struct MatchDataContext
-{
- /**
- * CHK we are looking for.
- */
- const struct ContentHashKey *chk;
-
- /**
- * Download we're processing.
- */
- struct GNUNET_FS_DownloadContext *dc;
-
- /**
- * Request details.
- */
- struct DownloadRequest *sm;
-
- /**
- * Overall offset in the file.
- */
- uint64_t offset;
-
- /**
- * Desired length of the block.
- */
- size_t len;
-
- /**
- * Flag set to GNUNET_YES on success.
- */
- int done;
-};
-
-/**
- * Type of a function that libextractor calls for each
- * meta data item found.
- *
- * @param cls closure (user-defined)
- * @param plugin_name name of the plugin that produced this value;
- * special values can be used (i.e. '<zlib>' for zlib being
- * used in the main libextractor library and yielding
- * meta data).
- * @param type libextractor-type describing the meta data
- * @param format basic format information about data
- * @param data_mime_type mime-type of data (not of the original file);
- * can be NULL (if mime-type is not known)
- * @param data actual meta-data found
- * @param data_len number of bytes in data
- * @return 0 to continue extracting, 1 to abort
- */
-static int
-match_full_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)
-{
- struct MatchDataContext *mdc = cls;
- GNUNET_HashCode key;
-
- if (type == EXTRACTOR_METATYPE_GNUNET_FULL_DATA)
- {
- if ( (mdc->offset > data_len) ||
- (mdc->offset + mdc->len > data_len) )
- return 1;
- GNUNET_CRYPTO_hash (&data[mdc->offset],
- mdc->len,
- &key);
- if (0 != memcmp (&key,
- &mdc->chk->key,
- sizeof (GNUNET_HashCode)))
- {
- GNUNET_break_op (0);
- return 1;
- }
- /* match found! */
- if (GNUNET_OK !=
- encrypt_existing_match (mdc->dc,
- mdc->chk,
- mdc->sm,
- &data[mdc->offset],
- mdc->len,
- 0,
- GNUNET_YES))
- {
- GNUNET_break_op (0);
- return 1;
- }
- mdc->done = GNUNET_YES;
- return 1;
- }
- return 0;
-}
-
-
-/**
- * Schedule the download of the specified block in the tree.
- *
- * @param dc overall download this block belongs to
- * @param chk content-hash-key of the block
- * @param offset offset of the block in the file
- * (for IBlocks, the offset is the lowest
- * offset of any DBlock in the subtree under
- * the IBlock)
- * @param depth depth of the block, 0 is the root of the tree
- */
-static void
-schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
- const struct ContentHashKey *chk,
- uint64_t offset,
- unsigned int depth)
-{
- struct DownloadRequest *sm;
- uint64_t total;
- uint64_t off;
- size_t len;
- char block[DBLOCK_SIZE];
- GNUNET_HashCode key;
- struct MatchDataContext mdc;
- struct GNUNET_DISK_FileHandle *fh;
-
- total = GNUNET_ntohll (dc->uri->data.chk.file_length);
- len = GNUNET_FS_tree_calculate_block_size (total,
- dc->treedepth,
- offset,
- depth);
- off = compute_disk_offset (total,
- offset,
- depth,
- dc->treedepth);
- sm = GNUNET_malloc (sizeof (struct DownloadRequest));
- sm->chk = *chk;
- sm->offset = offset;
- sm->depth = depth;
- sm->is_pending = GNUNET_YES;
- sm->next = dc->pending;
- dc->pending = sm;
- GNUNET_CONTAINER_multihashmap_put (dc->active,
- &chk->query,
- sm,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- if ( (dc->tried_full_data == GNUNET_NO) &&
- (depth == 0) )
- {
- mdc.dc = dc;
- mdc.sm = sm;
- mdc.chk = chk;
- mdc.offset = offset;
- mdc.len = len;
- mdc.done = GNUNET_NO;
- GNUNET_CONTAINER_meta_data_iterate (dc->meta,
- &match_full_data,
- &mdc);
- if (mdc.done == GNUNET_YES)
- return;
- dc->tried_full_data = GNUNET_YES;
- }
-#if DEBUG_DOWNLOAD
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Scheduling download at offset %llu and depth %u for `%s'\n",
- (unsigned long long) offset,
- depth,
- GNUNET_h2s (&chk->query));
-#endif
- fh = NULL;
- if ( (dc->old_file_size > off) &&
- (dc->filename != NULL) )
- fh = GNUNET_DISK_file_open (dc->filename,
- GNUNET_DISK_OPEN_READ,
- GNUNET_DISK_PERM_NONE);
- if ( (fh != NULL) &&
- (off ==
- GNUNET_DISK_file_seek (fh,
- off,
- GNUNET_DISK_SEEK_SET) ) &&
- (len ==
- GNUNET_DISK_file_read (fh,
- block,
- len)) )
- {
- GNUNET_CRYPTO_hash (block, len, &key);
- if ( (0 == memcmp (&key,
- &chk->key,
- sizeof (GNUNET_HashCode))) &&
- (GNUNET_OK ==
- encrypt_existing_match (dc,
- chk,
- sm,
- block,
- len,
- depth,
- GNUNET_NO)) )
- {
- GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh));
- return;
- }
- }
- if (fh != NULL)
- GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh));
- if (depth < dc->treedepth)
- {
- // FIXME: try if we could
- // reconstitute this IBLOCK
- // from the existing blocks on disk (can wait)
- // (read block(s), encode, compare with
- // query; if matches, simply return)
- }
-
- if ( (dc->th == NULL) &&
- (dc->client != NULL) )
- {
-#if DEBUG_DOWNLOAD
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Asking for transmission to FS service\n");
-#endif
- dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client,
- sizeof (struct SearchMessage),
- GNUNET_CONSTANTS_SERVICE_TIMEOUT,
- GNUNET_NO,
- &transmit_download_request,
- dc);
- }
- else
- {
-#if DEBUG_DOWNLOAD
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmission request not issued (%p %p)\n",
- dc->th,
- dc->client);
-#endif
-
- }
-
-}
-
-
-
-/**
- * Suggest a filename based on given metadata.
- *
- * @param md given meta data
- * @return NULL if meta data is useless for suggesting a filename
- */
-char *
-GNUNET_FS_meta_data_suggest_filename (const struct GNUNET_CONTAINER_MetaData *md)
-{
- static const char *mimeMap[][2] = {
- {"application/bz2", ".bz2"},
- {"application/gnunet-directory", ".gnd"},
- {"application/java", ".class"},
- {"application/msword", ".doc"},
- {"application/ogg", ".ogg"},
- {"application/pdf", ".pdf"},
- {"application/pgp-keys", ".key"},
- {"application/pgp-signature", ".pgp"},
- {"application/postscript", ".ps"},
- {"application/rar", ".rar"},
- {"application/rtf", ".rtf"},
- {"application/xml", ".xml"},
- {"application/x-debian-package", ".deb"},
- {"application/x-dvi", ".dvi"},
- {"applixation/x-flac", ".flac"},
- {"applixation/x-gzip", ".gz"},
- {"application/x-java-archive", ".jar"},
- {"application/x-java-vm", ".class"},
- {"application/x-python-code", ".pyc"},
- {"application/x-redhat-package-manager", ".rpm"},
- {"application/x-rpm", ".rpm"},
- {"application/x-tar", ".tar"},
- {"application/x-tex-pk", ".pk"},
- {"application/x-texinfo", ".texinfo"},
- {"application/x-xcf", ".xcf"},
- {"application/x-xfig", ".xfig"},
- {"application/zip", ".zip"},
-
- {"audio/midi", ".midi"},
- {"audio/mpeg", ".mp3"},
- {"audio/real", ".rm"},
- {"audio/x-wav", ".wav"},
-
- {"image/gif", ".gif"},
- {"image/jpeg", ".jpg"},
- {"image/pcx", ".pcx"},
- {"image/png", ".png"},
- {"image/tiff", ".tiff"},
- {"image/x-ms-bmp", ".bmp"},
- {"image/x-xpixmap", ".xpm"},
-
- {"text/css", ".css"},
- {"text/html", ".html"},
- {"text/plain", ".txt"},
- {"text/rtf", ".rtf"},
- {"text/x-c++hdr", ".h++"},
- {"text/x-c++src", ".c++"},
- {"text/x-chdr", ".h"},
- {"text/x-csrc", ".c"},
- {"text/x-java", ".java"},
- {"text/x-moc", ".moc"},
- {"text/x-pascal", ".pas"},
- {"text/x-perl", ".pl"},
- {"text/x-python", ".py"},
- {"text/x-tex", ".tex"},
-
- {"video/avi", ".avi"},
- {"video/mpeg", ".mpeg"},
- {"video/quicktime", ".qt"},
- {"video/real", ".rm"},
- {"video/x-msvideo", ".avi"},
- {NULL, NULL},
- };
- char *ret;
- unsigned int i;
- char *mime;
- char *base;
- const char *ext;
-
- ret = GNUNET_CONTAINER_meta_data_get_by_type (md,
- EXTRACTOR_METATYPE_FILENAME);
- if (ret != NULL)
- return ret;
- ext = NULL;
- mime = GNUNET_CONTAINER_meta_data_get_by_type (md,
- EXTRACTOR_METATYPE_MIMETYPE);
- if (mime != NULL)
- {
- i = 0;
- while ( (mimeMap[i][0] != NULL) &&
- (0 != strcmp (mime, mimeMap[i][0])))
- i++;
- if (mimeMap[i][1] == NULL)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG |
- GNUNET_ERROR_TYPE_BULK,
- _("Did not find mime type `%s' in extension list.\n"),
- mime);
- else
- ext = mimeMap[i][1];
- GNUNET_free (mime);
- }
- base = GNUNET_CONTAINER_meta_data_get_first_by_types (md,
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METATYPE_BOOK_TITLE,
- EXTRACTOR_METATYPE_ORIGINAL_TITLE,
- EXTRACTOR_METATYPE_PACKAGE_NAME,
- EXTRACTOR_METATYPE_URL,
- EXTRACTOR_METATYPE_URI,
- EXTRACTOR_METATYPE_DESCRIPTION,
- EXTRACTOR_METATYPE_ISRC,
- EXTRACTOR_METATYPE_JOURNAL_NAME,
- EXTRACTOR_METATYPE_AUTHOR_NAME,
- EXTRACTOR_METATYPE_SUBJECT,
- EXTRACTOR_METATYPE_ALBUM,
- EXTRACTOR_METATYPE_ARTIST,
- EXTRACTOR_METATYPE_KEYWORDS,
- EXTRACTOR_METATYPE_COMMENT,
- EXTRACTOR_METATYPE_UNKNOWN,
- -1);
- if ( (base == NULL) &&
- (ext == NULL) )
- return NULL;
- if (base == NULL)
- return GNUNET_strdup (ext);
- if (ext == NULL)
- return base;
- GNUNET_asprintf (&ret,
- "%s%s",
- base,
- ext);
- GNUNET_free (base);
- return ret;
-}
-
-