2 This file is part of GNUnet.
3 (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/container_meta_data.c
23 * @brief Storing of meta data
24 * @author Christian Grothoff
28 #include "gnunet_common.h"
29 #include "gnunet_container_lib.h"
30 #include "gnunet_strings_lib.h"
31 #include "gnunet_time_lib.h"
32 #include <extractor.h>
41 * This is a linked list.
43 struct MetaItem *next;
46 * Name of the extracting plugin.
56 * The actual meta data.
61 * Number of bytes in 'data'.
66 * Type of the meta data.
68 enum EXTRACTOR_MetaType type;
71 * Format of the meta data.
73 enum EXTRACTOR_MetaFormat format;
78 * Meta data to associate with a file, directory or namespace.
80 struct GNUNET_CONTAINER_MetaData
83 * Linked list of the meta data items.
85 struct MetaItem *items;
88 * Complete serialized and compressed buffer of the items.
89 * NULL if we have not computed that buffer yet.
94 * Number of bytes in 'sbuf'. 0 if the buffer is stale.
99 * Number of items in the linked list.
101 unsigned int item_count;
107 * Create a fresh struct CONTAINER_MetaData token.
109 * @return empty meta-data container
111 struct GNUNET_CONTAINER_MetaData *
112 GNUNET_CONTAINER_meta_data_create ()
114 return GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MetaData));
119 * Free meta data item.
121 * @param item item to free
124 meta_item_free (struct MetaItem *item)
126 GNUNET_free_non_null (item->plugin_name);
127 GNUNET_free_non_null (item->mime_type);
128 GNUNET_free_non_null (item->data);
134 * The meta data has changed, invalidate its serialization
137 * @param md meta data that changed
140 invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md)
142 if (md->sbuf == NULL)
144 GNUNET_free (md->sbuf);
153 * @param md what to free
156 GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md)
158 struct MetaItem *item;
162 while (NULL != (item = md->items))
164 md->items = item->next;
165 meta_item_free (item);
167 GNUNET_free_non_null (md->sbuf);
173 * Test if two MDs are equal. We consider them equal if
174 * the meta types, formats and content match (we do not
175 * include the mime types and plugins names in this
178 * @param md1 first value to check
179 * @param md2 other value to check
180 * @return GNUNET_YES if they are equal
183 GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
185 const struct GNUNET_CONTAINER_MetaData
194 if (md1->item_count != md2->item_count)
204 if ( (i->type == j->type) &&
205 (i->format == j->format) &&
206 (i->data_size == j->data_size) &&
207 (0 == memcmp (i->data,
216 if (found == GNUNET_NO)
225 * Extend metadata. Note that the list of meta data items is
226 * sorted by size (largest first).
228 * @param md metadata to extend
229 * @param plugin_name name of the plugin that produced this value;
230 * special values can be used (i.e. '<zlib>' for zlib being
231 * used in the main libextractor library and yielding
233 * @param type libextractor-type describing the meta data
234 * @param format basic format information about data
235 * @param data_mime_type mime-type of data (not of the original file);
236 * can be NULL (if mime-type is not known)
237 * @param data actual meta-data found
238 * @param data_len number of bytes in data
239 * @return GNUNET_OK on success, GNUNET_SYSERR if this entry already exists
240 * data_mime_type and plugin_name are not considered for "exists" checks
243 GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
244 const char *plugin_name,
245 enum EXTRACTOR_MetaType type,
246 enum EXTRACTOR_MetaFormat format,
247 const char *data_mime_type,
251 struct MetaItem *prev;
252 struct MetaItem *pos;
260 if (pos->data_size < data_len)
262 if ( (pos->type == type) &&
263 (pos->format == format) &&
264 (pos->data_size == data_len) &&
265 (0 == memcmp (pos->data,
269 if ( (pos->mime_type == NULL) &&
270 (data_mime_type != NULL) )
272 pos->mime_type = GNUNET_strdup (data_mime_type);
273 invalidate_sbuf (md);
275 return GNUNET_SYSERR;
281 i = GNUNET_malloc (sizeof (struct MetaItem));
284 i->data_size = data_len;
290 i->mime_type = (data_mime_type == NULL) ? NULL : GNUNET_strdup (data_mime_type);
291 i->plugin_name = (plugin_name == NULL) ? NULL : GNUNET_strdup (plugin_name);
292 i->data = GNUNET_malloc (data_len);
293 memcpy (i->data, data, data_len);
294 /* change OS native dir separators to unix '/' and others to '_' */
295 if (type == EXTRACTOR_METATYPE_FILENAME)
298 while ( (*p != '\0') &&
299 (p < i->data + data_len) )
301 if (*p == DIR_SEPARATOR)
308 invalidate_sbuf (md);
314 * Merge given meta data.
316 * @param cls the 'struct GNUNET_CONTAINER_MetaData' to merge into
317 * @param plugin_name name of the plugin that produced this value;
318 * special values can be used (i.e. '<zlib>' for zlib being
319 * used in the main libextractor library and yielding
321 * @param type libextractor-type describing the meta data
322 * @param format basic format information about data
323 * @param data_mime_type mime-type of data (not of the original file);
324 * can be NULL (if mime-type is not known)
325 * @param data actual meta-data found
326 * @param data_len number of bytes in data
327 * @return 0 (to continue)
330 merge_helper(void *cls,
331 const char *plugin_name,
332 enum EXTRACTOR_MetaType type,
333 enum EXTRACTOR_MetaFormat format,
334 const char *data_mime_type,
338 struct GNUNET_CONTAINER_MetaData *md = cls;
339 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
341 data_mime_type, data, data_len);
347 * Extend metadata. Merges the meta data from the second argument
348 * into the first, discarding duplicate key-value pairs.
350 * @param md metadata to extend
351 * @param in metadata to merge
354 GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
355 const struct GNUNET_CONTAINER_MetaData *in)
357 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md);
364 * @param md metadata to manipulate
365 * @param type type of the item to remove
366 * @param data specific value to remove, NULL to remove all
367 * entries of the given type
368 * @param data_len number of bytes in data
369 * @return GNUNET_OK on success, GNUNET_SYSERR if the item does not exist in md
372 GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
373 enum EXTRACTOR_MetaType type,
377 struct MetaItem *pos;
378 struct MetaItem *prev;
384 if ( (pos->type == type) &&
386 ( (pos->data_size == data_len) &&
387 (0 == memcmp (pos->data,
392 md->items = pos->next;
394 prev->next = pos->next;
395 meta_item_free (pos);
397 invalidate_sbuf (md);
403 return GNUNET_SYSERR;
408 * Add the current time as the publication date
411 * @param md metadata to modify
414 GNUNET_CONTAINER_meta_data_add_publication_date (struct
415 GNUNET_CONTAINER_MetaData
419 struct GNUNET_TIME_Absolute t;
421 t = GNUNET_TIME_absolute_get ();
422 GNUNET_CONTAINER_meta_data_delete (md,
423 EXTRACTOR_METATYPE_PUBLICATION_DATE,
426 dat = GNUNET_STRINGS_absolute_time_to_string (t);
427 GNUNET_CONTAINER_meta_data_insert (md,
429 EXTRACTOR_METATYPE_PUBLICATION_DATE,
430 EXTRACTOR_METAFORMAT_UTF8,
439 * Iterate over MD entries.
441 * @param md metadata to inspect
442 * @param iter function to call on each entry
443 * @param iter_cls closure for iterator
444 * @return number of entries
447 GNUNET_CONTAINER_meta_data_iterate (const struct
448 GNUNET_CONTAINER_MetaData *md,
449 EXTRACTOR_MetaDataProcessor
450 iter, void *iter_cls)
452 struct MetaItem *pos;
455 return md->item_count;
459 if (0 != iter (iter_cls,
466 return md->item_count;
469 return md->item_count;
474 * Get the first MD entry of the given type. Caller
475 * is responsible for freeing the return value.
476 * Also, only meta data items that are strings (0-terminated)
477 * are returned by this function.
479 * @param md metadata to inspect
480 * @param type type to look for
481 * @return NULL if no entry was found
484 GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData
485 *md, enum EXTRACTOR_MetaType type)
487 struct MetaItem *pos;
492 if ( (type == pos->type) &&
493 ( (pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
494 (pos->format == EXTRACTOR_METAFORMAT_C_STRING) ) )
495 return GNUNET_strdup (pos->data);
503 * Get the first matching MD entry of the given types. Caller is
504 * responsible for freeing the return value. Also, only meta data
505 * items that are strings (0-terminated) are returned by this
508 * @param md metadata to inspect
509 * @param ... -1-terminated list of types
510 * @return NULL if we do not have any such entry,
511 * otherwise client is responsible for freeing the value!
514 GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
515 GNUNET_CONTAINER_MetaData *md,
520 enum EXTRACTOR_MetaType type;
526 type = va_arg (args, enum EXTRACTOR_MetaType);
529 ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type);
539 * Get a thumbnail from the meta-data (if present).
541 * @param md metadata to get the thumbnail from
542 * @param thumb will be set to the thumbnail data. Must be
543 * freed by the caller!
544 * @return number of bytes in thumbnail, 0 if not available
547 GNUNET_CONTAINER_meta_data_get_thumbnail (const struct
548 GNUNET_CONTAINER_MetaData * md,
549 unsigned char **thumb)
551 struct MetaItem *pos;
552 struct MetaItem *match;
558 if ( (0 == strncasecmp ("image/", pos->mime_type,
559 strlen("image/"))) &&
560 (pos->format == EXTRACTOR_METAFORMAT_BINARY) )
564 else if ( (match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
565 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL) )
570 if ( (match == NULL) ||
571 (match->data_size == 0) )
573 *thumb = GNUNET_malloc (match->data_size);
574 memcpy (*thumb, match->data, match->data_size);
575 return match->data_size;
580 * Duplicate struct GNUNET_CONTAINER_MetaData.
582 * @param md what to duplicate
583 * @return duplicate meta-data container
585 struct GNUNET_CONTAINER_MetaData *
586 GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
589 struct GNUNET_CONTAINER_MetaData *ret;
590 struct MetaItem *pos;
594 ret = GNUNET_CONTAINER_meta_data_create ();
598 GNUNET_CONTAINER_meta_data_insert (ret,
612 * Add meta data that libextractor finds to our meta data
615 * @param cls closure, our meta data container
616 * @param plugin_name name of the plugin that produced this value;
617 * special values can be used (i.e. '<zlib>' for zlib being
618 * used in the main libextractor library and yielding
620 * @param type libextractor-type describing the meta data
621 * @param format basic format information about data
622 * @param data_mime_type mime-type of data (not of the original file);
623 * can be NULL (if mime-type is not known)
624 * @param data actual meta-data found
625 * @param data_len number of bytes in data
626 * @return always 0 to continue extracting
630 const char *plugin_name,
631 enum EXTRACTOR_MetaType type,
632 enum EXTRACTOR_MetaFormat format,
633 const char *data_mime_type,
637 struct GNUNET_CONTAINER_MetaData *md = cls;
638 (void) GNUNET_CONTAINER_meta_data_insert (md,
650 * Extract meta-data from a file.
652 * @return GNUNET_SYSERR on error, otherwise the number
653 * of meta-data items obtained
656 GNUNET_CONTAINER_meta_data_extract_from_file (struct GNUNET_CONTAINER_MetaData
657 *md, const char *filename,
658 struct EXTRACTOR_PluginList *
663 if (filename == NULL)
664 return GNUNET_SYSERR;
665 if (extractors == NULL)
667 old = md->item_count;
668 EXTRACTOR_extract (extractors,
673 return (int) (md->item_count - old);
678 * Try to compress the given block of data.
680 * @param data block to compress; if compression
681 * resulted in a smaller block, the first
682 * bytes of data are updated to the compressed
684 * @param oldSize number of bytes in data
685 * @param result set to the compressed data
686 * @param newSize set to size of result
687 * @return GNUNET_YES if compression reduce the size,
688 * GNUNET_NO if compression did not help
691 try_compression (const char *data,
700 dlen = compressBound (oldSize);
702 dlen = oldSize + (oldSize / 100) + 20;
703 /* documentation says 100.1% oldSize + 12 bytes, but we
704 should be able to overshoot by more to be safe */
706 tmp = GNUNET_malloc (dlen);
707 if (Z_OK == compress2 ((Bytef *) tmp,
708 &dlen, (const Bytef *) data, oldSize, 9))
723 * Flag in 'version' that indicates compressed meta-data.
725 #define HEADER_COMPRESSED 0x80000000
729 * Bits in 'version' that give the version number.
731 #define HEADER_VERSION_MASK 0x7FFFFFFF
735 * Header for serialized meta data.
737 struct MetaDataHeader
740 * The version of the MD serialization. The highest bit is used to
741 * indicate compression.
743 * Version 0 is traditional (pre-0.9) meta data (unsupported)
744 * Version is 1 for a NULL pointer
745 * Version 2 is for 0.9.x (and possibly higher)
746 * Other version numbers are not yet defined.
751 * How many MD entries are there?
756 * Size of the decompressed meta data.
761 * This is followed by 'entries' values of type 'struct MetaDataEntry'
762 * and then by 'entry' plugin names, mime-types and data blocks
763 * as specified in those meta data entries.
769 * Entry of serialized meta data.
774 * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType'
779 * Meta data format. Corresponds to an 'enum EXTRACTOR_MetaFormat'
784 * Number of bytes of meta data.
789 * Number of bytes in the plugin name including 0-terminator. 0 for NULL.
791 uint32_t plugin_name_len;
794 * Number of bytes in the mime type including 0-terminator. 0 for NULL.
796 uint32_t mime_type_len;
802 * Serialize meta-data to target.
804 * @param md metadata to serialize
805 * @param target where to write the serialized metadata;
806 * *target can be NULL, in which case memory is allocated
807 * @param max maximum number of bytes available in target
808 * @param opt is it ok to just write SOME of the
809 * meta-data to match the size constraint,
810 * possibly discarding some data?
811 * @return number of bytes written on success,
812 * GNUNET_SYSERR on error (typically: not enough
816 GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
817 *md, char **target, size_t max,
819 GNUNET_CONTAINER_MetaDataSerializationOptions
822 struct GNUNET_CONTAINER_MetaData *vmd;
823 struct MetaItem *pos;
824 struct MetaDataHeader ihdr;
825 struct MetaDataHeader *hdr;
826 struct MetaDataEntry *ent;
841 if (max < sizeof (struct MetaDataHeader))
842 return GNUNET_SYSERR; /* far too small */
846 if (md->sbuf != NULL)
848 /* try to use serialization cache */
849 if (md->sbuf_size <= max)
852 *target = GNUNET_malloc (md->sbuf_size);
856 return md->sbuf_size;
858 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
859 return GNUNET_SYSERR; /* can say that this will fail */
860 /* need to compute a partial serialization, sbuf useless ... */
867 msize += sizeof (struct MetaDataEntry);
868 msize += pos->data_size;
869 if (pos->plugin_name != NULL)
870 msize += strlen (pos->plugin_name) + 1;
871 if (pos->mime_type != NULL)
872 msize += strlen (pos->mime_type) + 1;
875 size = (size_t) msize;
878 GNUNET_break (0); /* integer overflow */
879 return GNUNET_SYSERR;
881 if (size >= GNUNET_MAX_MALLOC_CHECKED)
883 /* too large to be processed */
884 return GNUNET_SYSERR;
886 ent = GNUNET_malloc (size);
887 mdata = (char *) &ent[md->item_count];
888 off = size - (md->item_count * sizeof(struct MetaDataEntry));
893 ent[i].type = htonl ((uint32_t) pos->type);
894 ent[i].format = htonl ((uint32_t) pos->format);
895 ent[i].data_size = htonl ((uint32_t) pos->data_size);
896 if (pos->plugin_name == NULL)
899 plen = strlen (pos->plugin_name) + 1;
900 ent[i].plugin_name_len = htonl ( (uint32_t) plen);
901 if (pos->mime_type == NULL)
904 mlen = strlen (pos->mime_type) + 1;
905 ent[i].mime_type_len = htonl ((uint32_t) mlen);
906 off -= pos->data_size;
907 memcpy (&mdata[off], pos->data, pos->data_size);
909 if (pos->plugin_name != NULL)
910 memcpy (&mdata[off], pos->plugin_name, plen);
912 if (pos->mime_type != NULL)
913 memcpy (&mdata[off], pos->mime_type, mlen);
917 GNUNET_assert (off == 0);
927 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
928 comp = try_compression ((const char*) &ent[i],
933 if ( (md->sbuf == NULL) &&
936 /* fill 'sbuf'; this "modifies" md, but since this is only
937 an internal cache we will cast away the 'const' instead
938 of making the API look strange. */
939 vmd = (struct GNUNET_CONTAINER_MetaData*) md;
940 hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
941 hdr->size = htonl (left);
942 hdr->entries = htonl (md->item_count);
943 if (GNUNET_YES == comp)
945 GNUNET_assert (clen < left);
946 hdr->version = htonl (2 | HEADER_COMPRESSED);
950 vmd->sbuf_size = clen + sizeof (struct MetaDataHeader);
954 hdr->version = htonl (2);
958 vmd->sbuf_size = left + sizeof (struct MetaDataHeader);
960 vmd->sbuf = (char*) hdr;
963 if ( ( (left + sizeof (struct MetaDataHeader)) <= max) ||
964 ( (comp == GNUNET_YES) &&
967 /* success, this now fits! */
968 if (GNUNET_YES == comp)
971 dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
972 hdr = (struct MetaDataHeader*) dst;
973 hdr->version = htonl (2 | HEADER_COMPRESSED);
974 hdr->size = htonl (left);
975 hdr->entries = htonl (md->item_count - i);
976 memcpy (&dst[sizeof(struct MetaDataHeader)],
981 rlen = clen + sizeof (struct MetaDataHeader);
986 dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
987 hdr = (struct MetaDataHeader*) dst;
988 hdr->version = htonl (2);
989 hdr->entries = htonl (md->item_count - i);
990 hdr->size = htonl (left);
991 memcpy (&dst[sizeof(struct MetaDataHeader)],
995 rlen = left + sizeof (struct MetaDataHeader);
999 memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
1009 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
1013 return GNUNET_SYSERR;
1016 /* next iteration: ignore the corresponding meta data at the
1017 end and try again without it */
1018 left -= sizeof (struct MetaDataEntry);
1019 left -= pos->data_size;
1020 if (pos->plugin_name != NULL)
1021 left -= strlen (pos->plugin_name) + 1;
1022 if (pos->mime_type != NULL)
1023 left -= strlen (pos->mime_type) + 1;
1029 /* nothing fit, only write header! */
1030 ihdr.version = htonl (2);
1031 ihdr.entries = htonl (0);
1032 ihdr.size = htonl (0);
1033 if (*target == NULL)
1034 *target = GNUNET_malloc (sizeof (struct MetaDataHeader));
1035 memcpy (*target, &ihdr, sizeof (struct MetaDataHeader));
1036 return sizeof (struct MetaDataHeader);
1041 * Get the size of the full meta-data in serialized form.
1043 * @param md metadata to inspect
1044 * @return number of bytes needed for serialization, -1 on error
1047 GNUNET_CONTAINER_meta_data_get_serialized_size (const struct GNUNET_CONTAINER_MetaData *md)
1052 if (md->sbuf != NULL)
1053 return md->sbuf_size;
1055 ret = GNUNET_CONTAINER_meta_data_serialize (md,
1057 GNUNET_MAX_MALLOC_CHECKED,
1058 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
1066 * Decompress input, return the decompressed data
1067 * as output, set outputSize to the number of bytes
1070 * @param input compressed data
1071 * @param inputSize number of bytes in input
1072 * @param outputSize expected size of the output
1073 * @return NULL on error
1076 decompress (const char *input,
1084 output = GNUNET_malloc (olen);
1085 if (Z_OK == uncompress ((Bytef *) output,
1086 &olen, (const Bytef *) input, inputSize))
1092 GNUNET_free (output);
1099 * Deserialize meta-data. Initializes md.
1101 * @param input buffer with the serialized metadata
1102 * @param size number of bytes available in input
1103 * @return MD on success, NULL on error (i.e.
1106 struct GNUNET_CONTAINER_MetaData *
1107 GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size)
1109 struct GNUNET_CONTAINER_MetaData *md;
1110 struct MetaDataHeader hdr;
1111 struct MetaDataEntry ent;
1124 const char *meta_data;
1125 const char *plugin_name;
1126 const char *mime_type;
1127 enum EXTRACTOR_MetaFormat format;
1129 if (size < sizeof (struct MetaDataHeader))
1133 sizeof (struct MetaDataHeader));
1134 version = ntohl (hdr.version) & HEADER_VERSION_MASK;
1135 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
1138 return NULL; /* null pointer */
1141 GNUNET_break_op (0); /* unsupported version */
1145 ic = ntohl (hdr.entries);
1146 dataSize = ntohl (hdr.size);
1147 if ((sizeof (struct MetaDataEntry) * ic) > dataSize)
1149 GNUNET_break_op (0);
1155 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1157 /* make sure we don't blow our memory limit because of a mal-formed
1159 GNUNET_break_op (0);
1163 decompress ((const char *) &input[sizeof (struct MetaDataHeader)],
1164 size - sizeof (struct MetaDataHeader), dataSize);
1167 GNUNET_break_op (0);
1175 cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
1176 if (dataSize != size - sizeof (struct MetaDataHeader))
1178 GNUNET_break_op (0);
1183 md = GNUNET_CONTAINER_meta_data_create ();
1184 left = dataSize - ic * sizeof (struct MetaDataEntry);
1185 mdata = &cdata[ic * sizeof (struct MetaDataEntry)];
1189 &cdata[i * sizeof(struct MetaDataEntry)],
1190 sizeof (struct MetaDataEntry));
1191 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1192 if ( (format != EXTRACTOR_METAFORMAT_UTF8) &&
1193 (format != EXTRACTOR_METAFORMAT_C_STRING) &&
1194 (format != EXTRACTOR_METAFORMAT_BINARY) )
1196 GNUNET_break_op (0);
1199 dlen = ntohl (ent.data_size);
1200 plen = ntohl (ent.plugin_name_len);
1201 mlen = ntohl (ent.mime_type_len);
1204 GNUNET_break_op (0);
1208 meta_data = &mdata[left];
1209 if ( (format == EXTRACTOR_METAFORMAT_UTF8) ||
1210 (format == EXTRACTOR_METAFORMAT_C_STRING) )
1213 (mdata[left + dlen - 1] != '\0') )
1215 GNUNET_break_op (0);
1221 GNUNET_break_op (0);
1226 (mdata[left + plen - 1] != '\0') )
1228 GNUNET_break_op (0);
1234 plugin_name = &mdata[left];
1238 GNUNET_break_op (0);
1243 (mdata[left + mlen - 1] != '\0') )
1245 GNUNET_break_op (0);
1251 mime_type = &mdata[left];
1252 GNUNET_CONTAINER_meta_data_insert (md,
1254 (enum EXTRACTOR_MetaType) ntohl (ent.type),
1260 GNUNET_free_non_null (data);
1265 /* end of container_meta_data.c */