aboutsummaryrefslogtreecommitdiff
path: root/src/util/container_meta_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/container_meta_data.c')
-rw-r--r--src/util/container_meta_data.c975
1 files changed, 484 insertions, 491 deletions
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c
index 4989b876a..e134ef869 100644
--- a/src/util/container_meta_data.c
+++ b/src/util/container_meta_data.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20 20
21/** 21/**
22 * @file util/container_meta_data.c 22 * @file util/container_meta_data.c
@@ -31,7 +31,7 @@
31#endif 31#endif
32#include <zlib.h> 32#include <zlib.h>
33 33
34#define LOG(kind,...) GNUNET_log_from (kind, "util-container-meta-data", __VA_ARGS__) 34#define LOG(kind, ...) GNUNET_log_from(kind, "util-container-meta-data", __VA_ARGS__)
35 35
36 36
37 37
@@ -51,10 +51,10 @@
51 * #GNUNET_NO if compression did not help 51 * #GNUNET_NO if compression did not help
52 */ 52 */
53int 53int
54GNUNET_try_compression (const char *data, 54GNUNET_try_compression(const char *data,
55 size_t old_size, 55 size_t old_size,
56 char **result, 56 char **result,
57 size_t *new_size) 57 size_t *new_size)
58{ 58{
59 char *tmp; 59 char *tmp;
60 uLongf dlen; 60 uLongf dlen;
@@ -62,27 +62,27 @@ GNUNET_try_compression (const char *data,
62 *result = NULL; 62 *result = NULL;
63 *new_size = 0; 63 *new_size = 0;
64#ifdef compressBound 64#ifdef compressBound
65 dlen = compressBound (old_size); 65 dlen = compressBound(old_size);
66#else 66#else
67 dlen = old_size + (old_size / 100) + 20; 67 dlen = old_size + (old_size / 100) + 20;
68 /* documentation says 100.1% oldSize + 12 bytes, but we 68 /* documentation says 100.1% oldSize + 12 bytes, but we
69 * should be able to overshoot by more to be safe */ 69 * should be able to overshoot by more to be safe */
70#endif 70#endif
71 tmp = GNUNET_malloc (dlen); 71 tmp = GNUNET_malloc(dlen);
72 if (Z_OK == 72 if (Z_OK ==
73 compress2 ((Bytef *) tmp, 73 compress2((Bytef *)tmp,
74 &dlen, 74 &dlen,
75 (const Bytef *) data, 75 (const Bytef *)data,
76 old_size, 9)) 76 old_size, 9))
77 {
78 if (dlen < old_size)
79 { 77 {
80 *result = tmp; 78 if (dlen < old_size)
81 *new_size = dlen; 79 {
82 return GNUNET_YES; 80 *result = tmp;
81 *new_size = dlen;
82 return GNUNET_YES;
83 }
83 } 84 }
84 } 85 GNUNET_free(tmp);
85 GNUNET_free (tmp);
86 return GNUNET_NO; 86 return GNUNET_NO;
87} 87}
88 88
@@ -98,22 +98,22 @@ GNUNET_try_compression (const char *data,
98 * @return NULL on error, buffer of @a output_size decompressed bytes otherwise 98 * @return NULL on error, buffer of @a output_size decompressed bytes otherwise
99 */ 99 */
100char * 100char *
101GNUNET_decompress (const char *input, 101GNUNET_decompress(const char *input,
102 size_t input_size, 102 size_t input_size,
103 size_t output_size) 103 size_t output_size)
104{ 104{
105 char *output; 105 char *output;
106 uLongf olen; 106 uLongf olen;
107 107
108 olen = output_size; 108 olen = output_size;
109 output = GNUNET_malloc (olen); 109 output = GNUNET_malloc(olen);
110 if (Z_OK == 110 if (Z_OK ==
111 uncompress ((Bytef *) output, 111 uncompress((Bytef *)output,
112 &olen, 112 &olen,
113 (const Bytef *) input, 113 (const Bytef *)input,
114 input_size)) 114 input_size))
115 return output; 115 return output;
116 GNUNET_free (output); 116 GNUNET_free(output);
117 return NULL; 117 return NULL;
118} 118}
119 119
@@ -121,8 +121,7 @@ GNUNET_decompress (const char *input,
121/** 121/**
122 * Meta data item. 122 * Meta data item.
123 */ 123 */
124struct MetaItem 124struct MetaItem {
125{
126 /** 125 /**
127 * This is a doubly linked list. 126 * This is a doubly linked list.
128 */ 127 */
@@ -162,14 +161,12 @@ struct MetaItem
162 * Format of the meta data. 161 * Format of the meta data.
163 */ 162 */
164 enum EXTRACTOR_MetaFormat format; 163 enum EXTRACTOR_MetaFormat format;
165
166}; 164};
167 165
168/** 166/**
169 * Meta data to associate with a file, directory or namespace. 167 * Meta data to associate with a file, directory or namespace.
170 */ 168 */
171struct GNUNET_CONTAINER_MetaData 169struct GNUNET_CONTAINER_MetaData {
172{
173 /** 170 /**
174 * Head of linked list of the meta data items. 171 * Head of linked list of the meta data items.
175 */ 172 */
@@ -195,7 +192,6 @@ struct GNUNET_CONTAINER_MetaData
195 * Number of items in the linked list. 192 * Number of items in the linked list.
196 */ 193 */
197 unsigned int item_count; 194 unsigned int item_count;
198
199}; 195};
200 196
201 197
@@ -205,9 +201,9 @@ struct GNUNET_CONTAINER_MetaData
205 * @return empty meta-data container 201 * @return empty meta-data container
206 */ 202 */
207struct GNUNET_CONTAINER_MetaData * 203struct GNUNET_CONTAINER_MetaData *
208GNUNET_CONTAINER_meta_data_create () 204GNUNET_CONTAINER_meta_data_create()
209{ 205{
210 return GNUNET_new (struct GNUNET_CONTAINER_MetaData); 206 return GNUNET_new(struct GNUNET_CONTAINER_MetaData);
211} 207}
212 208
213 209
@@ -217,12 +213,12 @@ GNUNET_CONTAINER_meta_data_create ()
217 * @param mi item to free 213 * @param mi item to free
218 */ 214 */
219static void 215static void
220meta_item_free (struct MetaItem *mi) 216meta_item_free(struct MetaItem *mi)
221{ 217{
222 GNUNET_free_non_null (mi->plugin_name); 218 GNUNET_free_non_null(mi->plugin_name);
223 GNUNET_free_non_null (mi->mime_type); 219 GNUNET_free_non_null(mi->mime_type);
224 GNUNET_free_non_null (mi->data); 220 GNUNET_free_non_null(mi->data);
225 GNUNET_free (mi); 221 GNUNET_free(mi);
226} 222}
227 223
228 224
@@ -233,11 +229,11 @@ meta_item_free (struct MetaItem *mi)
233 * @param md meta data that changed 229 * @param md meta data that changed
234 */ 230 */
235static void 231static void
236invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md) 232invalidate_sbuf(struct GNUNET_CONTAINER_MetaData *md)
237{ 233{
238 if (NULL == md->sbuf) 234 if (NULL == md->sbuf)
239 return; 235 return;
240 GNUNET_free (md->sbuf); 236 GNUNET_free(md->sbuf);
241 md->sbuf = NULL; 237 md->sbuf = NULL;
242 md->sbuf_size = 0; 238 md->sbuf_size = 0;
243} 239}
@@ -249,19 +245,19 @@ invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md)
249 * @param md what to free 245 * @param md what to free
250 */ 246 */
251void 247void
252GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md) 248GNUNET_CONTAINER_meta_data_destroy(struct GNUNET_CONTAINER_MetaData *md)
253{ 249{
254 struct MetaItem *pos; 250 struct MetaItem *pos;
255 251
256 if (NULL == md) 252 if (NULL == md)
257 return; 253 return;
258 while (NULL != (pos = md->items_head)) 254 while (NULL != (pos = md->items_head))
259 { 255 {
260 GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos); 256 GNUNET_CONTAINER_DLL_remove(md->items_head, md->items_tail, pos);
261 meta_item_free (pos); 257 meta_item_free(pos);
262 } 258 }
263 GNUNET_free_non_null (md->sbuf); 259 GNUNET_free_non_null(md->sbuf);
264 GNUNET_free (md); 260 GNUNET_free(md);
265} 261}
266 262
267 263
@@ -271,19 +267,19 @@ GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md)
271 * @param md metadata to manipulate 267 * @param md metadata to manipulate
272 */ 268 */
273void 269void
274GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md) 270GNUNET_CONTAINER_meta_data_clear(struct GNUNET_CONTAINER_MetaData *md)
275{ 271{
276 struct MetaItem *mi; 272 struct MetaItem *mi;
277 273
278 if (NULL == md) 274 if (NULL == md)
279 return; 275 return;
280 while (NULL != (mi = md->items_head)) 276 while (NULL != (mi = md->items_head))
281 { 277 {
282 GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, mi); 278 GNUNET_CONTAINER_DLL_remove(md->items_head, md->items_tail, mi);
283 meta_item_free (mi); 279 meta_item_free(mi);
284 } 280 }
285 GNUNET_free_non_null (md->sbuf); 281 GNUNET_free_non_null(md->sbuf);
286 memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData)); 282 memset(md, 0, sizeof(struct GNUNET_CONTAINER_MetaData));
287} 283}
288 284
289 285
@@ -298,10 +294,10 @@ GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md)
298 * @return #GNUNET_YES if they are equal 294 * @return #GNUNET_YES if they are equal
299 */ 295 */
300int 296int
301GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData 297GNUNET_CONTAINER_meta_data_test_equal(const struct GNUNET_CONTAINER_MetaData
302 *md1, 298 *md1,
303 const struct GNUNET_CONTAINER_MetaData 299 const struct GNUNET_CONTAINER_MetaData
304 *md2) 300 *md2)
305{ 301{
306 struct MetaItem *i; 302 struct MetaItem *i;
307 struct MetaItem *j; 303 struct MetaItem *j;
@@ -312,23 +308,23 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
312 if (md1->item_count != md2->item_count) 308 if (md1->item_count != md2->item_count)
313 return GNUNET_NO; 309 return GNUNET_NO;
314 for (i = md1->items_head; NULL != i; i = i->next) 310 for (i = md1->items_head; NULL != i; i = i->next)
315 {
316 found = GNUNET_NO;
317 for (j = md2->items_head; NULL != j; j = j->next)
318 { 311 {
319 if ((i->type == j->type) && (i->format == j->format) && 312 found = GNUNET_NO;
320 (i->data_size == j->data_size) && 313 for (j = md2->items_head; NULL != j; j = j->next)
321 (0 == memcmp (i->data, j->data, i->data_size))) 314 {
322 { 315 if ((i->type == j->type) && (i->format == j->format) &&
323 found = GNUNET_YES; 316 (i->data_size == j->data_size) &&
324 break; 317 (0 == memcmp(i->data, j->data, i->data_size)))
325 } 318 {
326 if (j->data_size < i->data_size) 319 found = GNUNET_YES;
327 break; /* elements are sorted by (decreasing) size... */ 320 break;
321 }
322 if (j->data_size < i->data_size)
323 break; /* elements are sorted by (decreasing) size... */
324 }
325 if (GNUNET_NO == found)
326 return GNUNET_NO;
328 } 327 }
329 if (GNUNET_NO == found)
330 return GNUNET_NO;
331 }
332 return GNUNET_YES; 328 return GNUNET_YES;
333} 329}
334 330
@@ -352,12 +348,12 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
352 * data_mime_type and plugin_name are not considered for "exists" checks 348 * data_mime_type and plugin_name are not considered for "exists" checks
353 */ 349 */
354int 350int
355GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, 351GNUNET_CONTAINER_meta_data_insert(struct GNUNET_CONTAINER_MetaData *md,
356 const char *plugin_name, 352 const char *plugin_name,
357 enum EXTRACTOR_MetaType type, 353 enum EXTRACTOR_MetaType type,
358 enum EXTRACTOR_MetaFormat format, 354 enum EXTRACTOR_MetaFormat format,
359 const char *data_mime_type, const char *data, 355 const char *data_mime_type, const char *data,
360 size_t data_size) 356 size_t data_size)
361{ 357{
362 struct MetaItem *pos; 358 struct MetaItem *pos;
363 struct MetaItem *mi; 359 struct MetaItem *mi;
@@ -365,61 +361,61 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
365 361
366 if ((EXTRACTOR_METAFORMAT_UTF8 == format) || 362 if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
367 (EXTRACTOR_METAFORMAT_C_STRING == format)) 363 (EXTRACTOR_METAFORMAT_C_STRING == format))
368 GNUNET_break ('\0' == data[data_size - 1]); 364 GNUNET_break('\0' == data[data_size - 1]);
369 365
370 for (pos = md->items_head; NULL != pos; pos = pos->next) 366 for (pos = md->items_head; NULL != pos; pos = pos->next)
371 {
372 if (pos->data_size < data_size)
373 break; /* elements are sorted by size in the list */
374 if ((pos->type == type) && (pos->data_size == data_size) &&
375 (0 == memcmp (pos->data, data, data_size)))
376 { 367 {
377 if ((NULL == pos->mime_type) && (NULL != data_mime_type)) 368 if (pos->data_size < data_size)
378 { 369 break; /* elements are sorted by size in the list */
379 pos->mime_type = GNUNET_strdup (data_mime_type); 370 if ((pos->type == type) && (pos->data_size == data_size) &&
380 invalidate_sbuf (md); 371 (0 == memcmp(pos->data, data, data_size)))
381 } 372 {
382 if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) && 373 if ((NULL == pos->mime_type) && (NULL != data_mime_type))
383 (EXTRACTOR_METAFORMAT_UTF8 == format)) 374 {
384 { 375 pos->mime_type = GNUNET_strdup(data_mime_type);
385 pos->format = EXTRACTOR_METAFORMAT_UTF8; 376 invalidate_sbuf(md);
386 invalidate_sbuf (md); 377 }
387 } 378 if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
388 return GNUNET_SYSERR; 379 (EXTRACTOR_METAFORMAT_UTF8 == format))
380 {
381 pos->format = EXTRACTOR_METAFORMAT_UTF8;
382 invalidate_sbuf(md);
383 }
384 return GNUNET_SYSERR;
385 }
389 } 386 }
390 }
391 md->item_count++; 387 md->item_count++;
392 mi = GNUNET_new (struct MetaItem); 388 mi = GNUNET_new(struct MetaItem);
393 mi->type = type; 389 mi->type = type;
394 mi->format = format; 390 mi->format = format;
395 mi->data_size = data_size; 391 mi->data_size = data_size;
396 if (NULL == pos) 392 if (NULL == pos)
397 GNUNET_CONTAINER_DLL_insert_tail (md->items_head, 393 GNUNET_CONTAINER_DLL_insert_tail(md->items_head,
398 md->items_tail, 394 md->items_tail,
399 mi); 395 mi);
400 else 396 else
401 GNUNET_CONTAINER_DLL_insert_after (md->items_head, 397 GNUNET_CONTAINER_DLL_insert_after(md->items_head,
402 md->items_tail, 398 md->items_tail,
403 pos->prev, 399 pos->prev,
404 mi); 400 mi);
405 mi->mime_type = 401 mi->mime_type =
406 (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type); 402 (NULL == data_mime_type) ? NULL : GNUNET_strdup(data_mime_type);
407 mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name); 403 mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup(plugin_name);
408 mi->data = GNUNET_malloc (data_size); 404 mi->data = GNUNET_malloc(data_size);
409 GNUNET_memcpy (mi->data, data, data_size); 405 GNUNET_memcpy(mi->data, data, data_size);
410 /* change all dir separators to POSIX style ('/') */ 406 /* change all dir separators to POSIX style ('/') */
411 if ( (EXTRACTOR_METATYPE_FILENAME == type) || 407 if ((EXTRACTOR_METATYPE_FILENAME == type) ||
412 (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type) ) 408 (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type))
413 {
414 p = mi->data;
415 while (('\0' != *p) && (p < mi->data + data_size))
416 { 409 {
417 if ('\\' == *p) 410 p = mi->data;
418 *p = '/'; 411 while (('\0' != *p) && (p < mi->data + data_size))
419 p++; 412 {
413 if ('\\' == *p)
414 *p = '/';
415 p++;
416 }
420 } 417 }
421 } 418 invalidate_sbuf(md);
422 invalidate_sbuf (md);
423 return GNUNET_OK; 419 return GNUNET_OK;
424} 420}
425 421
@@ -441,14 +437,14 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
441 * @return 0 (to continue) 437 * @return 0 (to continue)
442 */ 438 */
443static int 439static int
444merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, 440merge_helper(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
445 enum EXTRACTOR_MetaFormat format, const char *data_mime_type, 441 enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
446 const char *data, size_t data_size) 442 const char *data, size_t data_size)
447{ 443{
448 struct GNUNET_CONTAINER_MetaData *md = cls; 444 struct GNUNET_CONTAINER_MetaData *md = cls;
449 445
450 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, 446 (void)GNUNET_CONTAINER_meta_data_insert(md, plugin_name, type, format,
451 data_mime_type, data, data_size); 447 data_mime_type, data, data_size);
452 return 0; 448 return 0;
453} 449}
454 450
@@ -461,10 +457,10 @@ merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
461 * @param in metadata to merge 457 * @param in metadata to merge
462 */ 458 */
463void 459void
464GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md, 460GNUNET_CONTAINER_meta_data_merge(struct GNUNET_CONTAINER_MetaData *md,
465 const struct GNUNET_CONTAINER_MetaData *in) 461 const struct GNUNET_CONTAINER_MetaData *in)
466{ 462{
467 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md); 463 GNUNET_CONTAINER_meta_data_iterate(in, &merge_helper, md);
468} 464}
469 465
470 466
@@ -479,28 +475,28 @@ GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
479 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the item does not exist in md 475 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the item does not exist in md
480 */ 476 */
481int 477int
482GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md, 478GNUNET_CONTAINER_meta_data_delete(struct GNUNET_CONTAINER_MetaData *md,
483 enum EXTRACTOR_MetaType type, 479 enum EXTRACTOR_MetaType type,
484 const char *data, size_t data_size) 480 const char *data, size_t data_size)
485{ 481{
486 struct MetaItem *pos; 482 struct MetaItem *pos;
487 483
488 for (pos = md->items_head; NULL != pos; pos = pos->next) 484 for (pos = md->items_head; NULL != pos; pos = pos->next)
489 {
490 if (pos->data_size < data_size)
491 break; /* items are sorted by (decreasing) size */
492 if ((pos->type == type) &&
493 ((NULL == data) ||
494 ((pos->data_size == data_size) &&
495 (0 == memcmp (pos->data, data, data_size)))))
496 { 485 {
497 GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos); 486 if (pos->data_size < data_size)
498 meta_item_free (pos); 487 break; /* items are sorted by (decreasing) size */
499 md->item_count--; 488 if ((pos->type == type) &&
500 invalidate_sbuf (md); 489 ((NULL == data) ||
501 return GNUNET_OK; 490 ((pos->data_size == data_size) &&
491 (0 == memcmp(pos->data, data, data_size)))))
492 {
493 GNUNET_CONTAINER_DLL_remove(md->items_head, md->items_tail, pos);
494 meta_item_free(pos);
495 md->item_count--;
496 invalidate_sbuf(md);
497 return GNUNET_OK;
498 }
502 } 499 }
503 }
504 return GNUNET_SYSERR; 500 return GNUNET_SYSERR;
505} 501}
506 502
@@ -512,21 +508,21 @@ GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
512 * @param md metadata to modify 508 * @param md metadata to modify
513 */ 509 */
514void 510void
515GNUNET_CONTAINER_meta_data_add_publication_date (struct 511GNUNET_CONTAINER_meta_data_add_publication_date(struct
516 GNUNET_CONTAINER_MetaData *md) 512 GNUNET_CONTAINER_MetaData *md)
517{ 513{
518 const char *dat; 514 const char *dat;
519 struct GNUNET_TIME_Absolute t; 515 struct GNUNET_TIME_Absolute t;
520 516
521 t = GNUNET_TIME_absolute_get (); 517 t = GNUNET_TIME_absolute_get();
522 GNUNET_CONTAINER_meta_data_delete (md, 518 GNUNET_CONTAINER_meta_data_delete(md,
523 EXTRACTOR_METATYPE_PUBLICATION_DATE, 519 EXTRACTOR_METATYPE_PUBLICATION_DATE,
524 NULL, 0); 520 NULL, 0);
525 dat = GNUNET_STRINGS_absolute_time_to_string (t); 521 dat = GNUNET_STRINGS_absolute_time_to_string(t);
526 GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>", 522 GNUNET_CONTAINER_meta_data_insert(md, "<gnunet>",
527 EXTRACTOR_METATYPE_PUBLICATION_DATE, 523 EXTRACTOR_METATYPE_PUBLICATION_DATE,
528 EXTRACTOR_METAFORMAT_UTF8, "text/plain", 524 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
529 dat, strlen (dat) + 1); 525 dat, strlen(dat) + 1);
530} 526}
531 527
532 528
@@ -539,9 +535,9 @@ GNUNET_CONTAINER_meta_data_add_publication_date (struct
539 * @return number of entries 535 * @return number of entries
540 */ 536 */
541int 537int
542GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md, 538GNUNET_CONTAINER_meta_data_iterate(const struct GNUNET_CONTAINER_MetaData *md,
543 EXTRACTOR_MetaDataProcessor iter, 539 EXTRACTOR_MetaDataProcessor iter,
544 void *iter_cls) 540 void *iter_cls)
545{ 541{
546 struct MetaItem *pos; 542 struct MetaItem *pos;
547 543
@@ -551,8 +547,8 @@ GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md,
551 return md->item_count; 547 return md->item_count;
552 for (pos = md->items_head; NULL != pos; pos = pos->next) 548 for (pos = md->items_head; NULL != pos; pos = pos->next)
553 if (0 != 549 if (0 !=
554 iter (iter_cls, pos->plugin_name, pos->type, pos->format, 550 iter(iter_cls, pos->plugin_name, pos->type, pos->format,
555 pos->mime_type, pos->data, pos->data_size)) 551 pos->mime_type, pos->data, pos->data_size))
556 return md->item_count; 552 return md->item_count;
557 return md->item_count; 553 return md->item_count;
558} 554}
@@ -569,8 +565,8 @@ GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md,
569 * @return NULL if no entry was found 565 * @return NULL if no entry was found
570 */ 566 */
571char * 567char *
572GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData *md, 568GNUNET_CONTAINER_meta_data_get_by_type(const struct GNUNET_CONTAINER_MetaData *md,
573 enum EXTRACTOR_MetaType type) 569 enum EXTRACTOR_MetaType type)
574{ 570{
575 struct MetaItem *pos; 571 struct MetaItem *pos;
576 572
@@ -580,7 +576,7 @@ GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData *
580 if ((type == pos->type) && 576 if ((type == pos->type) &&
581 ((pos->format == EXTRACTOR_METAFORMAT_UTF8) || 577 ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
582 (pos->format == EXTRACTOR_METAFORMAT_C_STRING))) 578 (pos->format == EXTRACTOR_METAFORMAT_C_STRING)))
583 return GNUNET_strdup (pos->data); 579 return GNUNET_strdup(pos->data);
584 return NULL; 580 return NULL;
585} 581}
586 582
@@ -597,9 +593,9 @@ GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData *
597 * otherwise client is responsible for freeing the value! 593 * otherwise client is responsible for freeing the value!
598 */ 594 */
599char * 595char *
600GNUNET_CONTAINER_meta_data_get_first_by_types (const struct 596GNUNET_CONTAINER_meta_data_get_first_by_types(const struct
601 GNUNET_CONTAINER_MetaData *md, 597 GNUNET_CONTAINER_MetaData *md,
602 ...) 598 ...)
603{ 599{
604 char *ret; 600 char *ret;
605 va_list args; 601 va_list args;
@@ -608,16 +604,16 @@ GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
608 if (NULL == md) 604 if (NULL == md)
609 return NULL; 605 return NULL;
610 ret = NULL; 606 ret = NULL;
611 va_start (args, md); 607 va_start(args, md);
612 while (1) 608 while (1)
613 { 609 {
614 type = va_arg (args, int); 610 type = va_arg(args, int);
615 if (-1 == type) 611 if (-1 == type)
616 break; 612 break;
617 if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type))) 613 if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type(md, type)))
618 break; 614 break;
619 } 615 }
620 va_end (args); 616 va_end(args);
621 return ret; 617 return ret;
622} 618}
623 619
@@ -631,8 +627,8 @@ GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
631 * @return number of bytes in thumbnail, 0 if not available 627 * @return number of bytes in thumbnail, 0 if not available
632 */ 628 */
633size_t 629size_t
634GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData 630GNUNET_CONTAINER_meta_data_get_thumbnail(const struct GNUNET_CONTAINER_MetaData
635 * md, unsigned char **thumb) 631 * md, unsigned char **thumb)
636{ 632{
637 struct MetaItem *pos; 633 struct MetaItem *pos;
638 struct MetaItem *match; 634 struct MetaItem *match;
@@ -641,22 +637,22 @@ GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData
641 return 0; 637 return 0;
642 match = NULL; 638 match = NULL;
643 for (pos = md->items_head; NULL != pos; pos = pos->next) 639 for (pos = md->items_head; NULL != pos; pos = pos->next)
644 {
645 if ((NULL != pos->mime_type) &&
646 (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
647 (EXTRACTOR_METAFORMAT_BINARY == pos->format))
648 { 640 {
649 if (NULL == match) 641 if ((NULL != pos->mime_type) &&
650 match = pos; 642 (0 == strncasecmp("image/", pos->mime_type, strlen("image/"))) &&
651 else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) && 643 (EXTRACTOR_METAFORMAT_BINARY == pos->format))
652 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL)) 644 {
653 match = pos; 645 if (NULL == match)
646 match = pos;
647 else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
648 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL))
649 match = pos;
650 }
654 } 651 }
655 }
656 if ((NULL == match) || (0 == match->data_size)) 652 if ((NULL == match) || (0 == match->data_size))
657 return 0; 653 return 0;
658 *thumb = GNUNET_malloc (match->data_size); 654 *thumb = GNUNET_malloc(match->data_size);
659 GNUNET_memcpy (*thumb, match->data, match->data_size); 655 GNUNET_memcpy(*thumb, match->data, match->data_size);
660 return match->data_size; 656 return match->data_size;
661} 657}
662 658
@@ -668,19 +664,19 @@ GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData
668 * @return duplicate meta-data container 664 * @return duplicate meta-data container
669 */ 665 */
670struct GNUNET_CONTAINER_MetaData * 666struct GNUNET_CONTAINER_MetaData *
671GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData 667GNUNET_CONTAINER_meta_data_duplicate(const struct GNUNET_CONTAINER_MetaData
672 *md) 668 *md)
673{ 669{
674 struct GNUNET_CONTAINER_MetaData *ret; 670 struct GNUNET_CONTAINER_MetaData *ret;
675 struct MetaItem *pos; 671 struct MetaItem *pos;
676 672
677 if (NULL == md) 673 if (NULL == md)
678 return NULL; 674 return NULL;
679 ret = GNUNET_CONTAINER_meta_data_create (); 675 ret = GNUNET_CONTAINER_meta_data_create();
680 for (pos = md->items_tail; NULL != pos; pos = pos->prev) 676 for (pos = md->items_tail; NULL != pos; pos = pos->prev)
681 GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type, 677 GNUNET_CONTAINER_meta_data_insert(ret, pos->plugin_name, pos->type,
682 pos->format, pos->mime_type, pos->data, 678 pos->format, pos->mime_type, pos->data,
683 pos->data_size); 679 pos->data_size);
684 return ret; 680 return ret;
685} 681}
686 682
@@ -700,8 +696,7 @@ GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
700/** 696/**
701 * Header for serialized meta data. 697 * Header for serialized meta data.
702 */ 698 */
703struct MetaDataHeader 699struct MetaDataHeader {
704{
705 /** 700 /**
706 * The version of the MD serialization. The highest bit is used to 701 * The version of the MD serialization. The highest bit is used to
707 * indicate compression. 702 * indicate compression.
@@ -734,8 +729,7 @@ struct MetaDataHeader
734/** 729/**
735 * Entry of serialized meta data. 730 * Entry of serialized meta data.
736 */ 731 */
737struct MetaDataEntry 732struct MetaDataEntry {
738{
739 /** 733 /**
740 * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType' 734 * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType'
741 */ 735 */
@@ -760,7 +754,6 @@ struct MetaDataEntry
760 * Number of bytes in the mime type including 0-terminator. 0 for NULL. 754 * Number of bytes in the mime type including 0-terminator. 0 for NULL.
761 */ 755 */
762 uint32_t mime_type_len; 756 uint32_t mime_type_len;
763
764}; 757};
765 758
766 759
@@ -779,11 +772,11 @@ struct MetaDataEntry
779 * space) 772 * space)
780 */ 773 */
781ssize_t 774ssize_t
782GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData 775GNUNET_CONTAINER_meta_data_serialize(const struct GNUNET_CONTAINER_MetaData
783 *md, char **target, size_t max, 776 *md, char **target, size_t max,
784 enum 777 enum
785 GNUNET_CONTAINER_MetaDataSerializationOptions 778 GNUNET_CONTAINER_MetaDataSerializationOptions
786 opt) 779 opt)
787{ 780{
788 struct GNUNET_CONTAINER_MetaData *vmd; 781 struct GNUNET_CONTAINER_MetaData *vmd;
789 struct MetaItem *pos; 782 struct MetaItem *pos;
@@ -804,195 +797,195 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
804 size_t rlen; 797 size_t rlen;
805 int comp; 798 int comp;
806 799
807 if (max < sizeof (struct MetaDataHeader)) 800 if (max < sizeof(struct MetaDataHeader))
808 return GNUNET_SYSERR; /* far too small */ 801 return GNUNET_SYSERR; /* far too small */
809 if (NULL == md) 802 if (NULL == md)
810 return 0; 803 return 0;
811 804
812 if (NULL != md->sbuf) 805 if (NULL != md->sbuf)
813 {
814 /* try to use serialization cache */
815 if (md->sbuf_size <= max)
816 { 806 {
817 if (NULL == *target) 807 /* try to use serialization cache */
818 *target = GNUNET_malloc (md->sbuf_size); 808 if (md->sbuf_size <= max)
819 GNUNET_memcpy (*target, md->sbuf, md->sbuf_size); 809 {
820 return md->sbuf_size; 810 if (NULL == *target)
811 *target = GNUNET_malloc(md->sbuf_size);
812 GNUNET_memcpy(*target, md->sbuf, md->sbuf_size);
813 return md->sbuf_size;
814 }
815 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
816 return GNUNET_SYSERR; /* can say that this will fail */
817 /* need to compute a partial serialization, sbuf useless ... */
821 } 818 }
822 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
823 return GNUNET_SYSERR; /* can say that this will fail */
824 /* need to compute a partial serialization, sbuf useless ... */
825 }
826 dst = NULL; 819 dst = NULL;
827 msize = 0; 820 msize = 0;
828 for (pos = md->items_tail; NULL != pos; pos = pos->prev) 821 for (pos = md->items_tail; NULL != pos; pos = pos->prev)
829 { 822 {
830 msize += sizeof (struct MetaDataEntry); 823 msize += sizeof(struct MetaDataEntry);
831 msize += pos->data_size; 824 msize += pos->data_size;
832 if (NULL != pos->plugin_name) 825 if (NULL != pos->plugin_name)
833 msize += strlen (pos->plugin_name) + 1; 826 msize += strlen(pos->plugin_name) + 1;
834 if (NULL != pos->mime_type) 827 if (NULL != pos->mime_type)
835 msize += strlen (pos->mime_type) + 1; 828 msize += strlen(pos->mime_type) + 1;
836 } 829 }
837 size = (size_t) msize; 830 size = (size_t)msize;
838 if (size != msize) 831 if (size != msize)
839 { 832 {
840 GNUNET_break (0); /* integer overflow */ 833 GNUNET_break(0); /* integer overflow */
841 return GNUNET_SYSERR; 834 return GNUNET_SYSERR;
842 } 835 }
843 if (size >= GNUNET_MAX_MALLOC_CHECKED) 836 if (size >= GNUNET_MAX_MALLOC_CHECKED)
844 { 837 {
845 /* too large to be processed */ 838 /* too large to be processed */
846 return GNUNET_SYSERR; 839 return GNUNET_SYSERR;
847 } 840 }
848 ent = GNUNET_malloc (size); 841 ent = GNUNET_malloc(size);
849 mdata = (char *) &ent[md->item_count]; 842 mdata = (char *)&ent[md->item_count];
850 off = size - (md->item_count * sizeof (struct MetaDataEntry)); 843 off = size - (md->item_count * sizeof(struct MetaDataEntry));
851 i = 0; 844 i = 0;
852 for (pos = md->items_head; NULL != pos; pos = pos->next) 845 for (pos = md->items_head; NULL != pos; pos = pos->next)
853 { 846 {
854 ent[i].type = htonl ((uint32_t) pos->type); 847 ent[i].type = htonl((uint32_t)pos->type);
855 ent[i].format = htonl ((uint32_t) pos->format); 848 ent[i].format = htonl((uint32_t)pos->format);
856 ent[i].data_size = htonl ((uint32_t) pos->data_size); 849 ent[i].data_size = htonl((uint32_t)pos->data_size);
857 if (NULL == pos->plugin_name) 850 if (NULL == pos->plugin_name)
858 plen = 0; 851 plen = 0;
859 else 852 else
860 plen = strlen (pos->plugin_name) + 1; 853 plen = strlen(pos->plugin_name) + 1;
861 ent[i].plugin_name_len = htonl ((uint32_t) plen); 854 ent[i].plugin_name_len = htonl((uint32_t)plen);
862 if (NULL == pos->mime_type) 855 if (NULL == pos->mime_type)
863 mlen = 0; 856 mlen = 0;
864 else 857 else
865 mlen = strlen (pos->mime_type) + 1; 858 mlen = strlen(pos->mime_type) + 1;
866 ent[i].mime_type_len = htonl ((uint32_t) mlen); 859 ent[i].mime_type_len = htonl((uint32_t)mlen);
867 off -= pos->data_size; 860 off -= pos->data_size;
868 if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) || 861 if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
869 (EXTRACTOR_METAFORMAT_C_STRING == pos->format)) 862 (EXTRACTOR_METAFORMAT_C_STRING == pos->format))
870 GNUNET_break ('\0' == pos->data[pos->data_size - 1]); 863 GNUNET_break('\0' == pos->data[pos->data_size - 1]);
871 GNUNET_memcpy (&mdata[off], pos->data, pos->data_size); 864 GNUNET_memcpy(&mdata[off], pos->data, pos->data_size);
872 off -= plen; 865 off -= plen;
873 if (NULL != pos->plugin_name) 866 if (NULL != pos->plugin_name)
874 GNUNET_memcpy (&mdata[off], pos->plugin_name, plen); 867 GNUNET_memcpy(&mdata[off], pos->plugin_name, plen);
875 off -= mlen; 868 off -= mlen;
876 if (NULL != pos->mime_type) 869 if (NULL != pos->mime_type)
877 GNUNET_memcpy (&mdata[off], pos->mime_type, mlen); 870 GNUNET_memcpy(&mdata[off], pos->mime_type, mlen);
878 i++; 871 i++;
879 } 872 }
880 GNUNET_assert (0 == off); 873 GNUNET_assert(0 == off);
881 874
882 clen = 0; 875 clen = 0;
883 cdata = NULL; 876 cdata = NULL;
884 left = size; 877 left = size;
885 i = 0; 878 i = 0;
886 for (pos = md->items_head; NULL != pos; pos = pos->next) 879 for (pos = md->items_head; NULL != pos; pos = pos->next)
887 {
888 comp = GNUNET_NO;
889 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
890 comp = GNUNET_try_compression ((const char *) &ent[i],
891 left,
892 &cdata,
893 &clen);
894
895 if ((NULL == md->sbuf) && (0 == i))
896 { 880 {
897 /* fill 'sbuf'; this "modifies" md, but since this is only 881 comp = GNUNET_NO;
898 * an internal cache we will cast away the 'const' instead 882 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
899 * of making the API look strange. */ 883 comp = GNUNET_try_compression((const char *)&ent[i],
900 vmd = (struct GNUNET_CONTAINER_MetaData *) md; 884 left,
901 hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader)); 885 &cdata,
902 hdr->size = htonl (left); 886 &clen);
903 hdr->entries = htonl (md->item_count); 887
904 if (GNUNET_YES == comp) 888 if ((NULL == md->sbuf) && (0 == i))
905 { 889 {
906 GNUNET_assert (clen < left); 890 /* fill 'sbuf'; this "modifies" md, but since this is only
907 hdr->version = htonl (2 | HEADER_COMPRESSED); 891 * an internal cache we will cast away the 'const' instead
908 GNUNET_memcpy (&hdr[1], cdata, clen); 892 * of making the API look strange. */
909 vmd->sbuf_size = clen + sizeof (struct MetaDataHeader); 893 vmd = (struct GNUNET_CONTAINER_MetaData *)md;
910 } 894 hdr = GNUNET_malloc(left + sizeof(struct MetaDataHeader));
911 else 895 hdr->size = htonl(left);
912 { 896 hdr->entries = htonl(md->item_count);
913 hdr->version = htonl (2); 897 if (GNUNET_YES == comp)
914 GNUNET_memcpy (&hdr[1], &ent[0], left); 898 {
915 vmd->sbuf_size = left + sizeof (struct MetaDataHeader); 899 GNUNET_assert(clen < left);
916 } 900 hdr->version = htonl(2 | HEADER_COMPRESSED);
917 vmd->sbuf = (char *) hdr; 901 GNUNET_memcpy(&hdr[1], cdata, clen);
902 vmd->sbuf_size = clen + sizeof(struct MetaDataHeader);
903 }
904 else
905 {
906 hdr->version = htonl(2);
907 GNUNET_memcpy(&hdr[1], &ent[0], left);
908 vmd->sbuf_size = left + sizeof(struct MetaDataHeader);
909 }
910 vmd->sbuf = (char *)hdr;
911 }
912
913 if (((left + sizeof(struct MetaDataHeader)) <= max) ||
914 ((GNUNET_YES == comp) && (clen <= max)))
915 {
916 /* success, this now fits! */
917 if (GNUNET_YES == comp)
918 {
919 if (NULL == dst)
920 dst = GNUNET_malloc(clen + sizeof(struct MetaDataHeader));
921 hdr = (struct MetaDataHeader *)dst;
922 hdr->version = htonl(2 | HEADER_COMPRESSED);
923 hdr->size = htonl(left);
924 hdr->entries = htonl(md->item_count - i);
925 GNUNET_memcpy(&dst[sizeof(struct MetaDataHeader)], cdata, clen);
926 GNUNET_free(cdata);
927 cdata = NULL;
928 GNUNET_free(ent);
929 rlen = clen + sizeof(struct MetaDataHeader);
930 }
931 else
932 {
933 if (NULL == dst)
934 dst = GNUNET_malloc(left + sizeof(struct MetaDataHeader));
935 hdr = (struct MetaDataHeader *)dst;
936 hdr->version = htonl(2);
937 hdr->entries = htonl(md->item_count - i);
938 hdr->size = htonl(left);
939 GNUNET_memcpy(&dst[sizeof(struct MetaDataHeader)], &ent[i], left);
940 GNUNET_free(ent);
941 rlen = left + sizeof(struct MetaDataHeader);
942 }
943 if (NULL != *target)
944 {
945 if (GNUNET_YES == comp)
946 GNUNET_memcpy(*target, dst, clen + sizeof(struct MetaDataHeader));
947 else
948 GNUNET_memcpy(*target, dst, left + sizeof(struct MetaDataHeader));
949 GNUNET_free(dst);
950 }
951 else
952 {
953 *target = dst;
954 }
955 return rlen;
956 }
957
958 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
959 {
960 /* does not fit! */
961 GNUNET_free(ent);
962 return GNUNET_SYSERR;
963 }
964
965 /* next iteration: ignore the corresponding meta data at the
966 * end and try again without it */
967 left -= sizeof(struct MetaDataEntry);
968 left -= pos->data_size;
969 if (NULL != pos->plugin_name)
970 left -= strlen(pos->plugin_name) + 1;
971 if (NULL != pos->mime_type)
972 left -= strlen(pos->mime_type) + 1;
973
974 GNUNET_free_non_null(cdata);
975 cdata = NULL;
976
977 i++;
918 } 978 }
919 979 GNUNET_free(ent);
920 if (((left + sizeof (struct MetaDataHeader)) <= max) ||
921 ((GNUNET_YES == comp) && (clen <= max)))
922 {
923 /* success, this now fits! */
924 if (GNUNET_YES == comp)
925 {
926 if (NULL == dst)
927 dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
928 hdr = (struct MetaDataHeader *) dst;
929 hdr->version = htonl (2 | HEADER_COMPRESSED);
930 hdr->size = htonl (left);
931 hdr->entries = htonl (md->item_count - i);
932 GNUNET_memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen);
933 GNUNET_free (cdata);
934 cdata = NULL;
935 GNUNET_free (ent);
936 rlen = clen + sizeof (struct MetaDataHeader);
937 }
938 else
939 {
940 if (NULL == dst)
941 dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
942 hdr = (struct MetaDataHeader *) dst;
943 hdr->version = htonl (2);
944 hdr->entries = htonl (md->item_count - i);
945 hdr->size = htonl (left);
946 GNUNET_memcpy (&dst[sizeof (struct MetaDataHeader)], &ent[i], left);
947 GNUNET_free (ent);
948 rlen = left + sizeof (struct MetaDataHeader);
949 }
950 if (NULL != *target)
951 {
952 if (GNUNET_YES == comp)
953 GNUNET_memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
954 else
955 GNUNET_memcpy (*target, dst, left + sizeof (struct MetaDataHeader));
956 GNUNET_free (dst);
957 }
958 else
959 {
960 *target = dst;
961 }
962 return rlen;
963 }
964
965 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
966 {
967 /* does not fit! */
968 GNUNET_free (ent);
969 return GNUNET_SYSERR;
970 }
971
972 /* next iteration: ignore the corresponding meta data at the
973 * end and try again without it */
974 left -= sizeof (struct MetaDataEntry);
975 left -= pos->data_size;
976 if (NULL != pos->plugin_name)
977 left -= strlen (pos->plugin_name) + 1;
978 if (NULL != pos->mime_type)
979 left -= strlen (pos->mime_type) + 1;
980
981 GNUNET_free_non_null (cdata);
982 cdata = NULL;
983
984 i++;
985 }
986 GNUNET_free (ent);
987 980
988 /* nothing fit, only write header! */ 981 /* nothing fit, only write header! */
989 ihdr.version = htonl (2); 982 ihdr.version = htonl(2);
990 ihdr.entries = htonl (0); 983 ihdr.entries = htonl(0);
991 ihdr.size = htonl (0); 984 ihdr.size = htonl(0);
992 if (NULL == *target) 985 if (NULL == *target)
993 *target = (char *) GNUNET_new (struct MetaDataHeader); 986 *target = (char *)GNUNET_new(struct MetaDataHeader);
994 GNUNET_memcpy (*target, &ihdr, sizeof (struct MetaDataHeader)); 987 GNUNET_memcpy(*target, &ihdr, sizeof(struct MetaDataHeader));
995 return sizeof (struct MetaDataHeader); 988 return sizeof(struct MetaDataHeader);
996} 989}
997 990
998 991
@@ -1003,8 +996,8 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
1003 * @return number of bytes needed for serialization, -1 on error 996 * @return number of bytes needed for serialization, -1 on error
1004 */ 997 */
1005ssize_t 998ssize_t
1006GNUNET_CONTAINER_meta_data_get_serialized_size (const struct 999GNUNET_CONTAINER_meta_data_get_serialized_size(const struct
1007 GNUNET_CONTAINER_MetaData *md) 1000 GNUNET_CONTAINER_MetaData *md)
1008{ 1001{
1009 ssize_t ret; 1002 ssize_t ret;
1010 char *ptr; 1003 char *ptr;
@@ -1013,10 +1006,10 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
1013 return md->sbuf_size; 1006 return md->sbuf_size;
1014 ptr = NULL; 1007 ptr = NULL;
1015 ret = 1008 ret =
1016 GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED, 1009 GNUNET_CONTAINER_meta_data_serialize(md, &ptr, GNUNET_MAX_MALLOC_CHECKED,
1017 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); 1010 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
1018 if (-1 != ret) 1011 if (-1 != ret)
1019 GNUNET_free (ptr); 1012 GNUNET_free(ptr);
1020 return ret; 1013 return ret;
1021} 1014}
1022 1015
@@ -1030,7 +1023,7 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
1030 * bad format) 1023 * bad format)
1031 */ 1024 */
1032struct GNUNET_CONTAINER_MetaData * 1025struct GNUNET_CONTAINER_MetaData *
1033GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) 1026GNUNET_CONTAINER_meta_data_deserialize(const char *input, size_t size)
1034{ 1027{
1035 struct GNUNET_CONTAINER_MetaData *md; 1028 struct GNUNET_CONTAINER_MetaData *md;
1036 struct MetaDataHeader hdr; 1029 struct MetaDataHeader hdr;
@@ -1052,137 +1045,137 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size)
1052 const char *mime_type; 1045 const char *mime_type;
1053 enum EXTRACTOR_MetaFormat format; 1046 enum EXTRACTOR_MetaFormat format;
1054 1047
1055 if (size < sizeof (struct MetaDataHeader)) 1048 if (size < sizeof(struct MetaDataHeader))
1056 return NULL; 1049 return NULL;
1057 GNUNET_memcpy (&hdr, input, sizeof (struct MetaDataHeader)); 1050 GNUNET_memcpy(&hdr, input, sizeof(struct MetaDataHeader));
1058 version = ntohl (hdr.version) & HEADER_VERSION_MASK; 1051 version = ntohl(hdr.version) & HEADER_VERSION_MASK;
1059 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0; 1052 compressed = (ntohl(hdr.version) & HEADER_COMPRESSED) != 0;
1060 1053
1061 if (1 == version) 1054 if (1 == version)
1062 return NULL; /* null pointer */ 1055 return NULL; /* null pointer */
1063 if (2 != version) 1056 if (2 != version)
1064 {
1065 GNUNET_break_op (0); /* unsupported version */
1066 return NULL;
1067 }
1068
1069 ic = ntohl (hdr.entries);
1070 dataSize = ntohl (hdr.size);
1071 if ( ((sizeof (struct MetaDataEntry) * ic) > dataSize) ||
1072 ( (0 != ic) &&
1073 (dataSize / ic < sizeof (struct MetaDataEntry)) ) )
1074 {
1075 GNUNET_break_op (0);
1076 return NULL;
1077 }
1078
1079 if (compressed)
1080 {
1081 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1082 { 1057 {
1083 /* make sure we don't blow our memory limit because of a mal-formed 1058 GNUNET_break_op(0); /* unsupported version */
1084 * message... */
1085 GNUNET_break_op (0);
1086 return NULL; 1059 return NULL;
1087 } 1060 }
1088 data = 1061
1089 GNUNET_decompress ((const char *) &input[sizeof (struct MetaDataHeader)], 1062 ic = ntohl(hdr.entries);
1090 size - sizeof (struct MetaDataHeader), 1063 dataSize = ntohl(hdr.size);
1091 dataSize); 1064 if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
1092 if (NULL == data) 1065 ((0 != ic) &&
1093 { 1066 (dataSize / ic < sizeof(struct MetaDataEntry))))
1094 GNUNET_break_op (0);
1095 return NULL;
1096 }
1097 cdata = data;
1098 }
1099 else
1100 {
1101 data = NULL;
1102 cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
1103 if (dataSize != size - sizeof (struct MetaDataHeader))
1104 { 1067 {
1105 GNUNET_break_op (0); 1068 GNUNET_break_op(0);
1106 return NULL; 1069 return NULL;
1107 } 1070 }
1108 }
1109 1071
1110 md = GNUNET_CONTAINER_meta_data_create (); 1072 if (compressed)
1111 left = dataSize - ic * sizeof (struct MetaDataEntry);
1112 mdata = &cdata[ic * sizeof (struct MetaDataEntry)];
1113 for (i = 0; i < ic; i++)
1114 {
1115 GNUNET_memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)],
1116 sizeof (struct MetaDataEntry));
1117 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1118 if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1119 (EXTRACTOR_METAFORMAT_C_STRING != format) &&
1120 (EXTRACTOR_METAFORMAT_BINARY != format))
1121 {
1122 GNUNET_break_op (0);
1123 break;
1124 }
1125 dlen = ntohl (ent.data_size);
1126 plen = ntohl (ent.plugin_name_len);
1127 mlen = ntohl (ent.mime_type_len);
1128 if (dlen > left)
1129 {
1130 GNUNET_break_op (0);
1131 break;
1132 }
1133 left -= dlen;
1134 meta_data = &mdata[left];
1135 if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1136 (EXTRACTOR_METAFORMAT_C_STRING == format))
1137 {
1138 if (0 == dlen)
1139 {
1140 GNUNET_break_op (0);
1141 break;
1142 }
1143 if ('\0' != meta_data[dlen - 1])
1144 {
1145 GNUNET_break_op (0);
1146 break;
1147 }
1148 }
1149 if (plen > left)
1150 { 1073 {
1151 GNUNET_break_op (0); 1074 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1152 break; 1075 {
1076 /* make sure we don't blow our memory limit because of a mal-formed
1077 * message... */
1078 GNUNET_break_op(0);
1079 return NULL;
1080 }
1081 data =
1082 GNUNET_decompress((const char *)&input[sizeof(struct MetaDataHeader)],
1083 size - sizeof(struct MetaDataHeader),
1084 dataSize);
1085 if (NULL == data)
1086 {
1087 GNUNET_break_op(0);
1088 return NULL;
1089 }
1090 cdata = data;
1153 } 1091 }
1154 left -= plen; 1092 else
1155 if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1156 { 1093 {
1157 GNUNET_break_op (0); 1094 data = NULL;
1158 break; 1095 cdata = (const char *)&input[sizeof(struct MetaDataHeader)];
1096 if (dataSize != size - sizeof(struct MetaDataHeader))
1097 {
1098 GNUNET_break_op(0);
1099 return NULL;
1100 }
1159 } 1101 }
1160 if (0 == plen)
1161 plugin_name = NULL;
1162 else
1163 plugin_name = &mdata[left];
1164 1102
1165 if (mlen > left) 1103 md = GNUNET_CONTAINER_meta_data_create();
1166 { 1104 left = dataSize - ic * sizeof(struct MetaDataEntry);
1167 GNUNET_break_op (0); 1105 mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
1168 break; 1106 for (i = 0; i < ic; i++)
1169 }
1170 left -= mlen;
1171 if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1172 { 1107 {
1173 GNUNET_break_op (0); 1108 GNUNET_memcpy(&ent, &cdata[i * sizeof(struct MetaDataEntry)],
1174 break; 1109 sizeof(struct MetaDataEntry));
1110 format = (enum EXTRACTOR_MetaFormat)ntohl(ent.format);
1111 if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1112 (EXTRACTOR_METAFORMAT_C_STRING != format) &&
1113 (EXTRACTOR_METAFORMAT_BINARY != format))
1114 {
1115 GNUNET_break_op(0);
1116 break;
1117 }
1118 dlen = ntohl(ent.data_size);
1119 plen = ntohl(ent.plugin_name_len);
1120 mlen = ntohl(ent.mime_type_len);
1121 if (dlen > left)
1122 {
1123 GNUNET_break_op(0);
1124 break;
1125 }
1126 left -= dlen;
1127 meta_data = &mdata[left];
1128 if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1129 (EXTRACTOR_METAFORMAT_C_STRING == format))
1130 {
1131 if (0 == dlen)
1132 {
1133 GNUNET_break_op(0);
1134 break;
1135 }
1136 if ('\0' != meta_data[dlen - 1])
1137 {
1138 GNUNET_break_op(0);
1139 break;
1140 }
1141 }
1142 if (plen > left)
1143 {
1144 GNUNET_break_op(0);
1145 break;
1146 }
1147 left -= plen;
1148 if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1149 {
1150 GNUNET_break_op(0);
1151 break;
1152 }
1153 if (0 == plen)
1154 plugin_name = NULL;
1155 else
1156 plugin_name = &mdata[left];
1157
1158 if (mlen > left)
1159 {
1160 GNUNET_break_op(0);
1161 break;
1162 }
1163 left -= mlen;
1164 if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1165 {
1166 GNUNET_break_op(0);
1167 break;
1168 }
1169 if (0 == mlen)
1170 mime_type = NULL;
1171 else
1172 mime_type = &mdata[left];
1173 GNUNET_CONTAINER_meta_data_insert(md, plugin_name,
1174 (enum EXTRACTOR_MetaType)
1175 ntohl(ent.type), format, mime_type,
1176 meta_data, dlen);
1175 } 1177 }
1176 if (0 == mlen) 1178 GNUNET_free_non_null(data);
1177 mime_type = NULL;
1178 else
1179 mime_type = &mdata[left];
1180 GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1181 (enum EXTRACTOR_MetaType)
1182 ntohl (ent.type), format, mime_type,
1183 meta_data, dlen);
1184 }
1185 GNUNET_free_non_null (data);
1186 return md; 1179 return md;
1187} 1180}
1188 1181