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.c889
1 files changed, 423 insertions, 466 deletions
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c
index 9d20f8dc5..64a58e133 100644
--- a/src/util/container_meta_data.c
+++ b/src/util/container_meta_data.c
@@ -39,7 +39,7 @@ struct MetaItem
39{ 39{
40 /** 40 /**
41 * This is a linked list. 41 * This is a linked list.
42 */ 42 */
43 struct MetaItem *next; 43 struct MetaItem *next;
44 44
45 /** 45 /**
@@ -160,10 +160,10 @@ GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md)
160 if (md == NULL) 160 if (md == NULL)
161 return; 161 return;
162 while (NULL != (item = md->items)) 162 while (NULL != (item = md->items))
163 { 163 {
164 md->items = item->next; 164 md->items = item->next;
165 meta_item_free (item); 165 meta_item_free (item);
166 } 166 }
167 GNUNET_free_non_null (md->sbuf); 167 GNUNET_free_non_null (md->sbuf);
168 GNUNET_free (md); 168 GNUNET_free (md);
169} 169}
@@ -174,7 +174,7 @@ GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md)
174 * 174 *
175 * @param md metadata to manipulate 175 * @param md metadata to manipulate
176 */ 176 */
177void 177void
178GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md) 178GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md)
179{ 179{
180 struct MetaItem *item; 180 struct MetaItem *item;
@@ -182,10 +182,10 @@ GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md)
182 if (md == NULL) 182 if (md == NULL)
183 return; 183 return;
184 while (NULL != (item = md->items)) 184 while (NULL != (item = md->items))
185 { 185 {
186 md->items = item->next; 186 md->items = item->next;
187 meta_item_free (item); 187 meta_item_free (item);
188 } 188 }
189 GNUNET_free_non_null (md->sbuf); 189 GNUNET_free_non_null (md->sbuf);
190 memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData)); 190 memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData));
191} 191}
@@ -219,27 +219,25 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
219 219
220 i = md1->items; 220 i = md1->items;
221 while (NULL != i) 221 while (NULL != i)
222 {
223 found = GNUNET_NO;
224 j = md2->items;
225 while (NULL != j)
222 { 226 {
223 found = GNUNET_NO; 227 if ((i->type == j->type) &&
224 j = md2->items; 228 (i->format == j->format) &&
225 while (NULL != j) 229 (i->data_size == j->data_size) &&
226 { 230 (0 == memcmp (i->data, j->data, i->data_size)))
227 if ( (i->type == j->type) && 231 {
228 (i->format == j->format) && 232 found = GNUNET_YES;
229 (i->data_size == j->data_size) && 233 break;
230 (0 == memcmp (i->data, 234 }
231 j->data, 235 j = j->next;
232 i->data_size)))
233 {
234 found = GNUNET_YES;
235 break;
236 }
237 j = j->next;
238 }
239 if (found == GNUNET_NO)
240 return GNUNET_NO;
241 i = i->next;
242 } 236 }
237 if (found == GNUNET_NO)
238 return GNUNET_NO;
239 i = i->next;
240 }
243 return GNUNET_YES; 241 return GNUNET_YES;
244} 242}
245 243
@@ -264,12 +262,11 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
264 */ 262 */
265int 263int
266GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, 264GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
267 const char *plugin_name, 265 const char *plugin_name,
268 enum EXTRACTOR_MetaType type, 266 enum EXTRACTOR_MetaType type,
269 enum EXTRACTOR_MetaFormat format, 267 enum EXTRACTOR_MetaFormat format,
270 const char *data_mime_type, 268 const char *data_mime_type,
271 const char *data, 269 const char *data, size_t data_len)
272 size_t data_len)
273{ 270{
274 struct MetaItem *prev; 271 struct MetaItem *prev;
275 struct MetaItem *pos; 272 struct MetaItem *pos;
@@ -279,32 +276,29 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
279 prev = NULL; 276 prev = NULL;
280 pos = md->items; 277 pos = md->items;
281 while (NULL != pos) 278 while (NULL != pos)
279 {
280 if (pos->data_size < data_len)
281 break;
282 if ((pos->type == type) &&
283 (pos->data_size == data_len) &&
284 (0 == memcmp (pos->data, data, data_len)))
282 { 285 {
283 if (pos->data_size < data_len) 286 if ((pos->mime_type == NULL) && (data_mime_type != NULL))
284 break; 287 {
285 if ( (pos->type == type) && 288 pos->mime_type = GNUNET_strdup (data_mime_type);
286 (pos->data_size == data_len) && 289 invalidate_sbuf (md);
287 (0 == memcmp (pos->data, 290 }
288 data, 291 if ((pos->format == EXTRACTOR_METAFORMAT_C_STRING) &&
289 data_len))) 292 (format == EXTRACTOR_METAFORMAT_UTF8))
290 { 293 {
291 if ( (pos->mime_type == NULL) && 294 pos->format = EXTRACTOR_METAFORMAT_UTF8;
292 (data_mime_type != NULL) ) 295 invalidate_sbuf (md);
293 { 296 }
294 pos->mime_type = GNUNET_strdup (data_mime_type); 297 return GNUNET_SYSERR;
295 invalidate_sbuf (md);
296 }
297 if ( (pos->format == EXTRACTOR_METAFORMAT_C_STRING) &&
298 (format == EXTRACTOR_METAFORMAT_UTF8) )
299 {
300 pos->format = EXTRACTOR_METAFORMAT_UTF8;
301 invalidate_sbuf (md);
302 }
303 return GNUNET_SYSERR;
304 }
305 prev = pos;
306 pos = pos->next;
307 } 298 }
299 prev = pos;
300 pos = pos->next;
301 }
308 md->item_count++; 302 md->item_count++;
309 i = GNUNET_malloc (sizeof (struct MetaItem)); 303 i = GNUNET_malloc (sizeof (struct MetaItem));
310 i->type = type; 304 i->type = type;
@@ -315,24 +309,24 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
315 md->items = i; 309 md->items = i;
316 else 310 else
317 prev->next = i; 311 prev->next = i;
318 i->mime_type = (data_mime_type == NULL) ? NULL : GNUNET_strdup (data_mime_type); 312 i->mime_type =
313 (data_mime_type == NULL) ? NULL : GNUNET_strdup (data_mime_type);
319 i->plugin_name = (plugin_name == NULL) ? NULL : GNUNET_strdup (plugin_name); 314 i->plugin_name = (plugin_name == NULL) ? NULL : GNUNET_strdup (plugin_name);
320 i->data = GNUNET_malloc (data_len); 315 i->data = GNUNET_malloc (data_len);
321 memcpy (i->data, data, data_len); 316 memcpy (i->data, data, data_len);
322 /* change OS native dir separators to unix '/' and others to '_' */ 317 /* change OS native dir separators to unix '/' and others to '_' */
323 if (type == EXTRACTOR_METATYPE_FILENAME) 318 if (type == EXTRACTOR_METATYPE_FILENAME)
319 {
320 p = i->data;
321 while ((*p != '\0') && (p < i->data + data_len))
324 { 322 {
325 p = i->data; 323 if (*p == DIR_SEPARATOR)
326 while ( (*p != '\0') && 324 *p = '/';
327 (p < i->data + data_len) ) 325 else if (*p == '\\')
328 { 326 *p = '_';
329 if (*p == DIR_SEPARATOR) 327 p++;
330 *p = '/';
331 else if (*p == '\\')
332 *p = '_';
333 p++;
334 }
335 } 328 }
329 }
336 invalidate_sbuf (md); 330 invalidate_sbuf (md);
337 return GNUNET_OK; 331 return GNUNET_OK;
338} 332}
@@ -353,20 +347,19 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
353 * @param data actual meta-data found 347 * @param data actual meta-data found
354 * @param data_len number of bytes in data 348 * @param data_len number of bytes in data
355 * @return 0 (to continue) 349 * @return 0 (to continue)
356 */ 350 */
357static int 351static int
358merge_helper(void *cls, 352merge_helper (void *cls,
359 const char *plugin_name, 353 const char *plugin_name,
360 enum EXTRACTOR_MetaType type, 354 enum EXTRACTOR_MetaType type,
361 enum EXTRACTOR_MetaFormat format, 355 enum EXTRACTOR_MetaFormat format,
362 const char *data_mime_type, 356 const char *data_mime_type, const char *data, size_t data_len)
363 const char *data,
364 size_t data_len)
365{ 357{
366 struct GNUNET_CONTAINER_MetaData *md = cls; 358 struct GNUNET_CONTAINER_MetaData *md = cls;
359
367 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, 360 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
368 type, format, 361 type, format,
369 data_mime_type, data, data_len); 362 data_mime_type, data, data_len);
370 return 0; 363 return 0;
371} 364}
372 365
@@ -378,9 +371,9 @@ merge_helper(void *cls,
378 * @param md metadata to extend 371 * @param md metadata to extend
379 * @param in metadata to merge 372 * @param in metadata to merge
380 */ 373 */
381void 374void
382GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md, 375GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
383 const struct GNUNET_CONTAINER_MetaData *in) 376 const struct GNUNET_CONTAINER_MetaData *in)
384{ 377{
385 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md); 378 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md);
386} 379}
@@ -398,9 +391,8 @@ GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
398 */ 391 */
399int 392int
400GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md, 393GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
401 enum EXTRACTOR_MetaType type, 394 enum EXTRACTOR_MetaType type,
402 const char *data, 395 const char *data, size_t data_len)
403 size_t data_len)
404{ 396{
405 struct MetaItem *pos; 397 struct MetaItem *pos;
406 struct MetaItem *prev; 398 struct MetaItem *prev;
@@ -408,26 +400,24 @@ GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
408 prev = NULL; 400 prev = NULL;
409 pos = md->items; 401 pos = md->items;
410 while (NULL != pos) 402 while (NULL != pos)
403 {
404 if ((pos->type == type) &&
405 ((data == NULL) ||
406 ((pos->data_size == data_len) &&
407 (0 == memcmp (pos->data, data, data_len)))))
411 { 408 {
412 if ( (pos->type == type) && 409 if (prev == NULL)
413 ( (data == NULL) || 410 md->items = pos->next;
414 ( (pos->data_size == data_len) && 411 else
415 (0 == memcmp (pos->data, 412 prev->next = pos->next;
416 data, 413 meta_item_free (pos);
417 data_len))) ) ) 414 md->item_count--;
418 { 415 invalidate_sbuf (md);
419 if (prev == NULL) 416 return GNUNET_OK;
420 md->items = pos->next;
421 else
422 prev->next = pos->next;
423 meta_item_free (pos);
424 md->item_count--;
425 invalidate_sbuf (md);
426 return GNUNET_OK;
427 }
428 prev = pos;
429 pos = pos->next;
430 } 417 }
418 prev = pos;
419 pos = pos->next;
420 }
431 return GNUNET_SYSERR; 421 return GNUNET_SYSERR;
432} 422}
433 423
@@ -440,25 +430,21 @@ GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
440 */ 430 */
441void 431void
442GNUNET_CONTAINER_meta_data_add_publication_date (struct 432GNUNET_CONTAINER_meta_data_add_publication_date (struct
443 GNUNET_CONTAINER_MetaData 433 GNUNET_CONTAINER_MetaData *md)
444 *md)
445{ 434{
446 char *dat; 435 char *dat;
447 struct GNUNET_TIME_Absolute t; 436 struct GNUNET_TIME_Absolute t;
448 437
449 t = GNUNET_TIME_absolute_get (); 438 t = GNUNET_TIME_absolute_get ();
450 GNUNET_CONTAINER_meta_data_delete (md, 439 GNUNET_CONTAINER_meta_data_delete (md,
451 EXTRACTOR_METATYPE_PUBLICATION_DATE, 440 EXTRACTOR_METATYPE_PUBLICATION_DATE,
452 NULL, 441 NULL, 0);
453 0);
454 dat = GNUNET_STRINGS_absolute_time_to_string (t); 442 dat = GNUNET_STRINGS_absolute_time_to_string (t);
455 GNUNET_CONTAINER_meta_data_insert (md, 443 GNUNET_CONTAINER_meta_data_insert (md,
456 "<gnunet>", 444 "<gnunet>",
457 EXTRACTOR_METATYPE_PUBLICATION_DATE, 445 EXTRACTOR_METATYPE_PUBLICATION_DATE,
458 EXTRACTOR_METAFORMAT_UTF8, 446 EXTRACTOR_METAFORMAT_UTF8,
459 "text/plain", 447 "text/plain", dat, strlen (dat) + 1);
460 dat,
461 strlen(dat)+1);
462 GNUNET_free (dat); 448 GNUNET_free (dat);
463} 449}
464 450
@@ -473,9 +459,9 @@ GNUNET_CONTAINER_meta_data_add_publication_date (struct
473 */ 459 */
474int 460int
475GNUNET_CONTAINER_meta_data_iterate (const struct 461GNUNET_CONTAINER_meta_data_iterate (const struct
476 GNUNET_CONTAINER_MetaData *md, 462 GNUNET_CONTAINER_MetaData *md,
477 EXTRACTOR_MetaDataProcessor 463 EXTRACTOR_MetaDataProcessor
478 iter, void *iter_cls) 464 iter, void *iter_cls)
479{ 465{
480 struct MetaItem *pos; 466 struct MetaItem *pos;
481 467
@@ -485,17 +471,14 @@ GNUNET_CONTAINER_meta_data_iterate (const struct
485 return md->item_count; 471 return md->item_count;
486 pos = md->items; 472 pos = md->items;
487 while (NULL != pos) 473 while (NULL != pos)
488 { 474 {
489 if (0 != iter (iter_cls, 475 if (0 != iter (iter_cls,
490 pos->plugin_name, 476 pos->plugin_name,
491 pos->type, 477 pos->type,
492 pos->format, 478 pos->format, pos->mime_type, pos->data, pos->data_size))
493 pos->mime_type, 479 return md->item_count;
494 pos->data, 480 pos = pos->next;
495 pos->data_size)) 481 }
496 return md->item_count;
497 pos = pos->next;
498 }
499 return md->item_count; 482 return md->item_count;
500} 483}
501 484
@@ -520,13 +503,13 @@ GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData
520 return NULL; 503 return NULL;
521 pos = md->items; 504 pos = md->items;
522 while (NULL != pos) 505 while (NULL != pos)
523 { 506 {
524 if ( (type == pos->type) && 507 if ((type == pos->type) &&
525 ( (pos->format == EXTRACTOR_METAFORMAT_UTF8) || 508 ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
526 (pos->format == EXTRACTOR_METAFORMAT_C_STRING) ) ) 509 (pos->format == EXTRACTOR_METAFORMAT_C_STRING)))
527 return GNUNET_strdup (pos->data); 510 return GNUNET_strdup (pos->data);
528 pos = pos->next; 511 pos = pos->next;
529 } 512 }
530 return NULL; 513 return NULL;
531} 514}
532 515
@@ -556,14 +539,15 @@ GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
556 ret = NULL; 539 ret = NULL;
557 va_start (args, md); 540 va_start (args, md);
558 while (1) 541 while (1)
559 { 542 {
560 type = va_arg (args, enum EXTRACTOR_MetaType); 543 type = va_arg (args, enum EXTRACTOR_MetaType);
561 if (type == -1) 544
562 break; 545 if (type == -1)
563 ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type); 546 break;
564 if (ret != NULL) 547 ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type);
565 break; 548 if (ret != NULL)
566 } 549 break;
550 }
567 va_end (args); 551 va_end (args);
568 return ret; 552 return ret;
569} 553}
@@ -590,22 +574,21 @@ GNUNET_CONTAINER_meta_data_get_thumbnail (const struct
590 match = NULL; 574 match = NULL;
591 pos = md->items; 575 pos = md->items;
592 while (NULL != pos) 576 while (NULL != pos)
593 { 577 {
594 if ( (NULL != pos->mime_type) && 578 if ((NULL != pos->mime_type) &&
595 (0 == strncasecmp ("image/", pos->mime_type, 579 (0 == strncasecmp ("image/", pos->mime_type,
596 strlen("image/"))) && 580 strlen ("image/"))) &&
597 (pos->format == EXTRACTOR_METAFORMAT_BINARY) ) 581 (pos->format == EXTRACTOR_METAFORMAT_BINARY))
598 { 582 {
599 if (match == NULL) 583 if (match == NULL)
600 match = pos; 584 match = pos;
601 else if ( (match->type != EXTRACTOR_METATYPE_THUMBNAIL) && 585 else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
602 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL) ) 586 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL))
603 match = pos; 587 match = pos;
604 }
605 pos = pos->next;
606 } 588 }
607 if ( (match == NULL) || 589 pos = pos->next;
608 (match->data_size == 0) ) 590 }
591 if ((match == NULL) || (match->data_size == 0))
609 return 0; 592 return 0;
610 *thumb = GNUNET_malloc (match->data_size); 593 *thumb = GNUNET_malloc (match->data_size);
611 memcpy (*thumb, match->data, match->data_size); 594 memcpy (*thumb, match->data, match->data_size);
@@ -631,16 +614,15 @@ GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
631 ret = GNUNET_CONTAINER_meta_data_create (); 614 ret = GNUNET_CONTAINER_meta_data_create ();
632 pos = md->items; 615 pos = md->items;
633 while (NULL != pos) 616 while (NULL != pos)
634 { 617 {
635 GNUNET_CONTAINER_meta_data_insert (ret, 618 GNUNET_CONTAINER_meta_data_insert (ret,
636 pos->plugin_name, 619 pos->plugin_name,
637 pos->type, 620 pos->type,
638 pos->format, 621 pos->format,
639 pos->mime_type, 622 pos->mime_type,
640 pos->data, 623 pos->data, pos->data_size);
641 pos->data_size); 624 pos = pos->next;
642 pos = pos->next; 625 }
643 }
644 return ret; 626 return ret;
645} 627}
646 628
@@ -660,10 +642,8 @@ GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
660 * GNUNET_NO if compression did not help 642 * GNUNET_NO if compression did not help
661 */ 643 */
662static int 644static int
663try_compression (const char *data, 645try_compression (const char *data,
664 size_t oldSize, 646 size_t oldSize, char **result, size_t * newSize)
665 char **result,
666 size_t *newSize)
667{ 647{
668 char *tmp; 648 char *tmp;
669 uLongf dlen; 649 uLongf dlen;
@@ -673,19 +653,19 @@ try_compression (const char *data,
673#else 653#else
674 dlen = oldSize + (oldSize / 100) + 20; 654 dlen = oldSize + (oldSize / 100) + 20;
675 /* documentation says 100.1% oldSize + 12 bytes, but we 655 /* documentation says 100.1% oldSize + 12 bytes, but we
676 should be able to overshoot by more to be safe */ 656 * should be able to overshoot by more to be safe */
677#endif 657#endif
678 tmp = GNUNET_malloc (dlen); 658 tmp = GNUNET_malloc (dlen);
679 if (Z_OK == compress2 ((Bytef *) tmp, 659 if (Z_OK == compress2 ((Bytef *) tmp,
680 &dlen, (const Bytef *) data, oldSize, 9)) 660 &dlen, (const Bytef *) data, oldSize, 9))
661 {
662 if (dlen < oldSize)
681 { 663 {
682 if (dlen < oldSize) 664 *result = tmp;
683 { 665 *newSize = dlen;
684 *result = tmp; 666 return GNUNET_YES;
685 *newSize = dlen;
686 return GNUNET_YES;
687 }
688 } 667 }
668 }
689 GNUNET_free (tmp); 669 GNUNET_free (tmp);
690 return GNUNET_NO; 670 return GNUNET_NO;
691} 671}
@@ -744,7 +724,7 @@ struct MetaDataEntry
744{ 724{
745 /** 725 /**
746 * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType' 726 * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType'
747 */ 727 */
748 uint32_t type; 728 uint32_t type;
749 729
750 /** 730 /**
@@ -793,8 +773,8 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
793{ 773{
794 struct GNUNET_CONTAINER_MetaData *vmd; 774 struct GNUNET_CONTAINER_MetaData *vmd;
795 struct MetaItem *pos; 775 struct MetaItem *pos;
796 struct MetaDataHeader ihdr; 776 struct MetaDataHeader ihdr;
797 struct MetaDataHeader *hdr; 777 struct MetaDataHeader *hdr;
798 struct MetaDataEntry *ent; 778 struct MetaDataEntry *ent;
799 char *dst; 779 char *dst;
800 unsigned int i; 780 unsigned int i;
@@ -814,78 +794,76 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
814 return GNUNET_SYSERR; /* far too small */ 794 return GNUNET_SYSERR; /* far too small */
815 if (md == NULL) 795 if (md == NULL)
816 return 0; 796 return 0;
817 797
818 if (md->sbuf != NULL) 798 if (md->sbuf != NULL)
799 {
800 /* try to use serialization cache */
801 if (md->sbuf_size <= max)
819 { 802 {
820 /* try to use serialization cache */ 803 if (NULL == *target)
821 if (md->sbuf_size <= max) 804 *target = GNUNET_malloc (md->sbuf_size);
822 { 805 memcpy (*target, md->sbuf, md->sbuf_size);
823 if (NULL == *target) 806 return md->sbuf_size;
824 *target = GNUNET_malloc (md->sbuf_size);
825 memcpy (*target,
826 md->sbuf,
827 md->sbuf_size);
828 return md->sbuf_size;
829 }
830 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
831 return GNUNET_SYSERR; /* can say that this will fail */
832 /* need to compute a partial serialization, sbuf useless ... */
833 } 807 }
834 dst = NULL; 808 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
809 return GNUNET_SYSERR; /* can say that this will fail */
810 /* need to compute a partial serialization, sbuf useless ... */
811 }
812 dst = NULL;
835 msize = 0; 813 msize = 0;
836 pos = md->items; 814 pos = md->items;
837 while (NULL != pos) 815 while (NULL != pos)
838 { 816 {
839 msize += sizeof (struct MetaDataEntry); 817 msize += sizeof (struct MetaDataEntry);
840 msize += pos->data_size; 818 msize += pos->data_size;
841 if (pos->plugin_name != NULL) 819 if (pos->plugin_name != NULL)
842 msize += strlen (pos->plugin_name) + 1; 820 msize += strlen (pos->plugin_name) + 1;
843 if (pos->mime_type != NULL) 821 if (pos->mime_type != NULL)
844 msize += strlen (pos->mime_type) + 1; 822 msize += strlen (pos->mime_type) + 1;
845 pos = pos->next; 823 pos = pos->next;
846 } 824 }
847 size = (size_t) msize; 825 size = (size_t) msize;
848 if (size != msize) 826 if (size != msize)
849 { 827 {
850 GNUNET_break (0); /* integer overflow */ 828 GNUNET_break (0); /* integer overflow */
851 return GNUNET_SYSERR; 829 return GNUNET_SYSERR;
852 } 830 }
853 if (size >= GNUNET_MAX_MALLOC_CHECKED) 831 if (size >= GNUNET_MAX_MALLOC_CHECKED)
854 { 832 {
855 /* too large to be processed */ 833 /* too large to be processed */
856 return GNUNET_SYSERR; 834 return GNUNET_SYSERR;
857 } 835 }
858 ent = GNUNET_malloc (size); 836 ent = GNUNET_malloc (size);
859 mdata = (char *) &ent[md->item_count]; 837 mdata = (char *) &ent[md->item_count];
860 off = size - (md->item_count * sizeof(struct MetaDataEntry)); 838 off = size - (md->item_count * sizeof (struct MetaDataEntry));
861 i = 0; 839 i = 0;
862 pos = md->items; 840 pos = md->items;
863 while (NULL != pos) 841 while (NULL != pos)
864 { 842 {
865 ent[i].type = htonl ((uint32_t) pos->type); 843 ent[i].type = htonl ((uint32_t) pos->type);
866 ent[i].format = htonl ((uint32_t) pos->format); 844 ent[i].format = htonl ((uint32_t) pos->format);
867 ent[i].data_size = htonl ((uint32_t) pos->data_size); 845 ent[i].data_size = htonl ((uint32_t) pos->data_size);
868 if (pos->plugin_name == NULL) 846 if (pos->plugin_name == NULL)
869 plen = 0; 847 plen = 0;
870 else 848 else
871 plen = strlen (pos->plugin_name) + 1; 849 plen = strlen (pos->plugin_name) + 1;
872 ent[i].plugin_name_len = htonl ( (uint32_t) plen); 850 ent[i].plugin_name_len = htonl ((uint32_t) plen);
873 if (pos->mime_type == NULL) 851 if (pos->mime_type == NULL)
874 mlen = 0; 852 mlen = 0;
875 else 853 else
876 mlen = strlen (pos->mime_type) + 1; 854 mlen = strlen (pos->mime_type) + 1;
877 ent[i].mime_type_len = htonl ((uint32_t) mlen); 855 ent[i].mime_type_len = htonl ((uint32_t) mlen);
878 off -= pos->data_size; 856 off -= pos->data_size;
879 memcpy (&mdata[off], pos->data, pos->data_size); 857 memcpy (&mdata[off], pos->data, pos->data_size);
880 off -= plen; 858 off -= plen;
881 if (pos->plugin_name != NULL) 859 if (pos->plugin_name != NULL)
882 memcpy (&mdata[off], pos->plugin_name, plen); 860 memcpy (&mdata[off], pos->plugin_name, plen);
883 off -= mlen; 861 off -= mlen;
884 if (pos->mime_type != NULL) 862 if (pos->mime_type != NULL)
885 memcpy (&mdata[off], pos->mime_type, mlen); 863 memcpy (&mdata[off], pos->mime_type, mlen);
886 i++; 864 i++;
887 pos = pos->next; 865 pos = pos->next;
888 } 866 }
889 GNUNET_assert (off == 0); 867 GNUNET_assert (off == 0);
890 868
891 clen = 0; 869 clen = 0;
@@ -894,115 +872,102 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
894 i = 0; 872 i = 0;
895 pos = md->items; 873 pos = md->items;
896 while (pos != NULL) 874 while (pos != NULL)
897 { 875 {
898 comp = GNUNET_NO; 876 comp = GNUNET_NO;
899 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS)) 877 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
900 comp = try_compression ((const char*) &ent[i], 878 comp = try_compression ((const char *) &ent[i], left, &cdata, &clen);
901 left, 879
902 &cdata, 880 if ((md->sbuf == NULL) && (i == 0))
903 &clen); 881 {
904 882 /* fill 'sbuf'; this "modifies" md, but since this is only
905 if ( (md->sbuf == NULL) && 883 * an internal cache we will cast away the 'const' instead
906 (i == 0) ) 884 * of making the API look strange. */
907 { 885 vmd = (struct GNUNET_CONTAINER_MetaData *) md;
908 /* fill 'sbuf'; this "modifies" md, but since this is only 886 hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
909 an internal cache we will cast away the 'const' instead 887 hdr->size = htonl (left);
910 of making the API look strange. */ 888 hdr->entries = htonl (md->item_count);
911 vmd = (struct GNUNET_CONTAINER_MetaData*) md; 889 if (GNUNET_YES == comp)
912 hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader)); 890 {
913 hdr->size = htonl (left); 891 GNUNET_assert (clen < left);
914 hdr->entries = htonl (md->item_count); 892 hdr->version = htonl (2 | HEADER_COMPRESSED);
915 if (GNUNET_YES == comp) 893 memcpy (&hdr[1], cdata, clen);
916 { 894 vmd->sbuf_size = clen + sizeof (struct MetaDataHeader);
917 GNUNET_assert (clen < left); 895 }
918 hdr->version = htonl (2 | HEADER_COMPRESSED); 896 else
919 memcpy (&hdr[1], 897 {
920 cdata, 898 hdr->version = htonl (2);
921 clen); 899 memcpy (&hdr[1], &ent[0], left);
922 vmd->sbuf_size = clen + sizeof (struct MetaDataHeader); 900 vmd->sbuf_size = left + sizeof (struct MetaDataHeader);
923 } 901 }
924 else 902 vmd->sbuf = (char *) hdr;
925 { 903 }
926 hdr->version = htonl (2); 904
927 memcpy (&hdr[1], 905 if (((left + sizeof (struct MetaDataHeader)) <= max) ||
928 &ent[0], 906 ((comp == GNUNET_YES) && (clen <= max)))
929 left); 907 {
930 vmd->sbuf_size = left + sizeof (struct MetaDataHeader); 908 /* success, this now fits! */
931 } 909 if (GNUNET_YES == comp)
932 vmd->sbuf = (char*) hdr; 910 {
933 } 911 if (dst == NULL)
934 912 dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
935 if ( ( (left + sizeof (struct MetaDataHeader)) <= max) || 913 hdr = (struct MetaDataHeader *) dst;
936 ( (comp == GNUNET_YES) && 914 hdr->version = htonl (2 | HEADER_COMPRESSED);
937 (clen <= max)) ) 915 hdr->size = htonl (left);
938 { 916 hdr->entries = htonl (md->item_count - i);
939 /* success, this now fits! */ 917 memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen);
940 if (GNUNET_YES == comp) 918 GNUNET_free (cdata);
941 { 919 GNUNET_free (ent);
942 if (dst == NULL) 920 rlen = clen + sizeof (struct MetaDataHeader);
943 dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader)); 921 }
944 hdr = (struct MetaDataHeader*) dst; 922 else
945 hdr->version = htonl (2 | HEADER_COMPRESSED); 923 {
946 hdr->size = htonl (left); 924 if (dst == NULL)
947 hdr->entries = htonl (md->item_count - i); 925 dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
948 memcpy (&dst[sizeof(struct MetaDataHeader)], 926 hdr = (struct MetaDataHeader *) dst;
949 cdata, 927 hdr->version = htonl (2);
950 clen); 928 hdr->entries = htonl (md->item_count - i);
951 GNUNET_free (cdata); 929 hdr->size = htonl (left);
952 GNUNET_free (ent); 930 memcpy (&dst[sizeof (struct MetaDataHeader)], &ent[i], left);
953 rlen = clen + sizeof (struct MetaDataHeader); 931 GNUNET_free (ent);
954 } 932 rlen = left + sizeof (struct MetaDataHeader);
955 else 933 }
956 { 934 if (NULL != *target)
957 if (dst == NULL) 935 {
958 dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader)); 936 memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
959 hdr = (struct MetaDataHeader*) dst; 937 GNUNET_free (dst);
960 hdr->version = htonl (2); 938 }
961 hdr->entries = htonl (md->item_count - i); 939 else
962 hdr->size = htonl (left); 940 {
963 memcpy (&dst[sizeof(struct MetaDataHeader)], 941 *target = dst;
964 &ent[i], 942 }
965 left); 943 return rlen;
966 GNUNET_free (ent); 944 }
967 rlen = left + sizeof (struct MetaDataHeader); 945
968 } 946 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
969 if (NULL != *target) 947 {
970 { 948 /* does not fit! */
971 memcpy (*target, dst, clen + sizeof (struct MetaDataHeader)); 949 GNUNET_free (ent);
972 GNUNET_free (dst); 950 return GNUNET_SYSERR;
973 }
974 else
975 {
976 *target = dst;
977 }
978 return rlen;
979 }
980
981 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
982 {
983 /* does not fit! */
984 GNUNET_free (ent);
985 return GNUNET_SYSERR;
986 }
987
988 /* next iteration: ignore the corresponding meta data at the
989 end and try again without it */
990 left -= sizeof (struct MetaDataEntry);
991 left -= pos->data_size;
992 if (pos->plugin_name != NULL)
993 left -= strlen (pos->plugin_name) + 1;
994 if (pos->mime_type != NULL)
995 left -= strlen (pos->mime_type) + 1;
996 pos = pos->next;
997 i++;
998 } 951 }
952
953 /* next iteration: ignore the corresponding meta data at the
954 * end and try again without it */
955 left -= sizeof (struct MetaDataEntry);
956 left -= pos->data_size;
957 if (pos->plugin_name != NULL)
958 left -= strlen (pos->plugin_name) + 1;
959 if (pos->mime_type != NULL)
960 left -= strlen (pos->mime_type) + 1;
961 pos = pos->next;
962 i++;
963 }
999 GNUNET_free (ent); 964 GNUNET_free (ent);
1000 965
1001 /* nothing fit, only write header! */ 966 /* nothing fit, only write header! */
1002 ihdr.version = htonl (2); 967 ihdr.version = htonl (2);
1003 ihdr.entries = htonl (0); 968 ihdr.entries = htonl (0);
1004 ihdr.size = htonl (0); 969 ihdr.size = htonl (0);
1005 if (*target == NULL) 970 if (*target == NULL)
1006 *target = GNUNET_malloc (sizeof (struct MetaDataHeader)); 971 *target = GNUNET_malloc (sizeof (struct MetaDataHeader));
1007 memcpy (*target, &ihdr, sizeof (struct MetaDataHeader)); 972 memcpy (*target, &ihdr, sizeof (struct MetaDataHeader));
1008 return sizeof (struct MetaDataHeader); 973 return sizeof (struct MetaDataHeader);
@@ -1016,18 +981,19 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
1016 * @return number of bytes needed for serialization, -1 on error 981 * @return number of bytes needed for serialization, -1 on error
1017 */ 982 */
1018ssize_t 983ssize_t
1019GNUNET_CONTAINER_meta_data_get_serialized_size (const struct GNUNET_CONTAINER_MetaData *md) 984GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
985 GNUNET_CONTAINER_MetaData *md)
1020{ 986{
1021 ssize_t ret; 987 ssize_t ret;
1022 char *ptr; 988 char *ptr;
1023 989
1024 if (md->sbuf != NULL) 990 if (md->sbuf != NULL)
1025 return md->sbuf_size; 991 return md->sbuf_size;
1026 ptr = NULL; 992 ptr = NULL;
1027 ret = GNUNET_CONTAINER_meta_data_serialize (md, 993 ret = GNUNET_CONTAINER_meta_data_serialize (md,
1028 &ptr, 994 &ptr,
1029 GNUNET_MAX_MALLOC_CHECKED, 995 GNUNET_MAX_MALLOC_CHECKED,
1030 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); 996 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
1031 if (ret != -1) 997 if (ret != -1)
1032 GNUNET_free (ptr); 998 GNUNET_free (ptr);
1033 return ret; 999 return ret;
@@ -1045,9 +1011,7 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct GNUNET_CONTAINER_Me
1045 * @return NULL on error 1011 * @return NULL on error
1046 */ 1012 */
1047static char * 1013static char *
1048decompress (const char *input, 1014decompress (const char *input, size_t inputSize, size_t outputSize)
1049 size_t inputSize,
1050 size_t outputSize)
1051{ 1015{
1052 char *output; 1016 char *output;
1053 uLongf olen; 1017 uLongf olen;
@@ -1056,14 +1020,14 @@ decompress (const char *input,
1056 output = GNUNET_malloc (olen); 1020 output = GNUNET_malloc (olen);
1057 if (Z_OK == uncompress ((Bytef *) output, 1021 if (Z_OK == uncompress ((Bytef *) output,
1058 &olen, (const Bytef *) input, inputSize)) 1022 &olen, (const Bytef *) input, inputSize))
1059 { 1023 {
1060 return output; 1024 return output;
1061 } 1025 }
1062 else 1026 else
1063 { 1027 {
1064 GNUNET_free (output); 1028 GNUNET_free (output);
1065 return NULL; 1029 return NULL;
1066 } 1030 }
1067} 1031}
1068 1032
1069 1033
@@ -1100,136 +1064,129 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size)
1100 1064
1101 if (size < sizeof (struct MetaDataHeader)) 1065 if (size < sizeof (struct MetaDataHeader))
1102 return NULL; 1066 return NULL;
1103 memcpy (&hdr, 1067 memcpy (&hdr, input, sizeof (struct MetaDataHeader));
1104 input,
1105 sizeof (struct MetaDataHeader));
1106 version = ntohl (hdr.version) & HEADER_VERSION_MASK; 1068 version = ntohl (hdr.version) & HEADER_VERSION_MASK;
1107 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0; 1069 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
1108 1070
1109 if (version == 1) 1071 if (version == 1)
1110 return NULL; /* null pointer */ 1072 return NULL; /* null pointer */
1111 if (version != 2) 1073 if (version != 2)
1112 { 1074 {
1113 GNUNET_break_op (0); /* unsupported version */ 1075 GNUNET_break_op (0); /* unsupported version */
1114 return NULL; 1076 return NULL;
1115 } 1077 }
1116 1078
1117 ic = ntohl (hdr.entries); 1079 ic = ntohl (hdr.entries);
1118 dataSize = ntohl (hdr.size); 1080 dataSize = ntohl (hdr.size);
1119 if ((sizeof (struct MetaDataEntry) * ic) > dataSize) 1081 if ((sizeof (struct MetaDataEntry) * ic) > dataSize)
1120 { 1082 {
1121 GNUNET_break_op (0); 1083 GNUNET_break_op (0);
1122 return NULL; 1084 return NULL;
1123 } 1085 }
1124 1086
1125 if (compressed) 1087 if (compressed)
1088 {
1089 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1126 { 1090 {
1127 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED) 1091 /* make sure we don't blow our memory limit because of a mal-formed
1128 { 1092 * message... */
1129 /* make sure we don't blow our memory limit because of a mal-formed 1093 GNUNET_break_op (0);
1130 message... */ 1094 return NULL;
1131 GNUNET_break_op (0); 1095 }
1132 return NULL; 1096 data =
1133 }
1134 data =
1135 decompress ((const char *) &input[sizeof (struct MetaDataHeader)], 1097 decompress ((const char *) &input[sizeof (struct MetaDataHeader)],
1136 size - sizeof (struct MetaDataHeader), dataSize); 1098 size - sizeof (struct MetaDataHeader), dataSize);
1137 if (data == NULL) 1099 if (data == NULL)
1138 { 1100 {
1139 GNUNET_break_op (0); 1101 GNUNET_break_op (0);
1140 return NULL; 1102 return NULL;
1141 }
1142 cdata = data;
1143 } 1103 }
1104 cdata = data;
1105 }
1144 else 1106 else
1107 {
1108 data = NULL;
1109 cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
1110 if (dataSize != size - sizeof (struct MetaDataHeader))
1145 { 1111 {
1146 data = NULL; 1112 GNUNET_break_op (0);
1147 cdata = (const char *) &input[sizeof (struct MetaDataHeader)]; 1113 return NULL;
1148 if (dataSize != size - sizeof (struct MetaDataHeader))
1149 {
1150 GNUNET_break_op (0);
1151 return NULL;
1152 }
1153 } 1114 }
1115 }
1154 1116
1155 md = GNUNET_CONTAINER_meta_data_create (); 1117 md = GNUNET_CONTAINER_meta_data_create ();
1156 left = dataSize - ic * sizeof (struct MetaDataEntry); 1118 left = dataSize - ic * sizeof (struct MetaDataEntry);
1157 mdata = &cdata[ic * sizeof (struct MetaDataEntry)]; 1119 mdata = &cdata[ic * sizeof (struct MetaDataEntry)];
1158 for (i=0;i<ic;i++) 1120 for (i = 0; i < ic; i++)
1121 {
1122 memcpy (&ent,
1123 &cdata[i * sizeof (struct MetaDataEntry)],
1124 sizeof (struct MetaDataEntry));
1125 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1126 if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1127 (format != EXTRACTOR_METAFORMAT_C_STRING) &&
1128 (format != EXTRACTOR_METAFORMAT_BINARY))
1159 { 1129 {
1160 memcpy (&ent, 1130 GNUNET_break_op (0);
1161 &cdata[i * sizeof(struct MetaDataEntry)], 1131 break;
1162 sizeof (struct MetaDataEntry)); 1132 }
1163 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format); 1133 dlen = ntohl (ent.data_size);
1164 if ( (format != EXTRACTOR_METAFORMAT_UTF8) && 1134 plen = ntohl (ent.plugin_name_len);
1165 (format != EXTRACTOR_METAFORMAT_C_STRING) && 1135 mlen = ntohl (ent.mime_type_len);
1166 (format != EXTRACTOR_METAFORMAT_BINARY) ) 1136 if (dlen > left)
1167 { 1137 {
1168 GNUNET_break_op (0); 1138 GNUNET_break_op (0);
1169 break; 1139 break;
1170 } 1140 }
1171 dlen = ntohl (ent.data_size); 1141 left -= dlen;
1172 plen = ntohl (ent.plugin_name_len); 1142 meta_data = &mdata[left];
1173 mlen = ntohl (ent.mime_type_len); 1143 if ((format == EXTRACTOR_METAFORMAT_UTF8) ||
1174 if (dlen > left) 1144 (format == EXTRACTOR_METAFORMAT_C_STRING))
1175 { 1145 {
1176 GNUNET_break_op (0); 1146 if ((dlen == 0) || (mdata[left + dlen - 1] != '\0'))
1177 break; 1147 {
1178 } 1148 GNUNET_break_op (0);
1179 left -= dlen; 1149 break;
1180 meta_data = &mdata[left]; 1150 }
1181 if ( (format == EXTRACTOR_METAFORMAT_UTF8) || 1151 }
1182 (format == EXTRACTOR_METAFORMAT_C_STRING) ) 1152 if (plen > left)
1183 { 1153 {
1184 if ( (dlen == 0) || 1154 GNUNET_break_op (0);
1185 (mdata[left + dlen - 1] != '\0') ) 1155 break;
1186 { 1156 }
1187 GNUNET_break_op (0); 1157 left -= plen;
1188 break; 1158 if ((plen > 0) && (mdata[left + plen - 1] != '\0'))
1189 } 1159 {
1190 } 1160 GNUNET_break_op (0);
1191 if (plen > left) 1161 break;
1192 { 1162 }
1193 GNUNET_break_op (0); 1163 if (plen == 0)
1194 break; 1164 plugin_name = NULL;
1195 } 1165 else
1196 left -= plen; 1166 plugin_name = &mdata[left];
1197 if ( (plen > 0) && 1167
1198 (mdata[left + plen - 1] != '\0') ) 1168 if (mlen > left)
1199 { 1169 {
1200 GNUNET_break_op (0); 1170 GNUNET_break_op (0);
1201 break; 1171 break;
1202 } 1172 }
1203 if (plen == 0) 1173 left -= mlen;
1204 plugin_name = NULL; 1174 if ((mlen > 0) && (mdata[left + mlen - 1] != '\0'))
1205 else 1175 {
1206 plugin_name = &mdata[left]; 1176 GNUNET_break_op (0);
1207 1177 break;
1208 if (mlen > left)
1209 {
1210 GNUNET_break_op (0);
1211 break;
1212 }
1213 left -= mlen;
1214 if ( (mlen > 0) &&
1215 (mdata[left + mlen - 1] != '\0') )
1216 {
1217 GNUNET_break_op (0);
1218 break;
1219 }
1220 if (mlen == 0)
1221 mime_type = NULL;
1222 else
1223 mime_type = &mdata[left];
1224 GNUNET_CONTAINER_meta_data_insert (md,
1225 plugin_name,
1226 (enum EXTRACTOR_MetaType) ntohl (ent.type),
1227 format,
1228 mime_type,
1229 meta_data,
1230 dlen);
1231 } 1178 }
1232 GNUNET_free_non_null (data); 1179 if (mlen == 0)
1180 mime_type = NULL;
1181 else
1182 mime_type = &mdata[left];
1183 GNUNET_CONTAINER_meta_data_insert (md,
1184 plugin_name,
1185 (enum EXTRACTOR_MetaType)
1186 ntohl (ent.type), format, mime_type,
1187 meta_data, dlen);
1188 }
1189 GNUNET_free_non_null (data);
1233 return md; 1190 return md;
1234} 1191}
1235 1192